【问题标题】:How do I connect a form in .cshtml to a controller in C#?如何将 .cshtml 中的表单连接到 C# 中的控制器?
【发布时间】:2021-02-09 22:45:01
【问题描述】:

问题: 我正在用 C# 构建一个完整的堆栈 Web 应用程序,但我无法将表单数据从 Razor 页面获取到控制器中!

这是我的输入表单:

@model OrderProcessingApplication.Model.Order
@{
  ViewData["Title"] = "Ordering Application";
}

<div class="text-center">
<h1 class="display-4">Shirt Ordering Application</h1>
<p>Process an order</p>
p>Process an order</p>
<form id="submitOrderForm" action="ProcessNewOrder" method="post">
    <fieldset>
        <!--Name-->
        <label for="fname">First name:</label><br>
        <input type="text" id="fname" name="fname" required><br>
        <label for="lname">Last name:</label><br>
        <input type="text" id="lname" name="lname" required><br><br>

        <!--address-->
        <label for="address">Address:</label><br>
        <input type="text" id="address" name="address" required><br>

        <input type="submit" value="Submit">
    </fieldset>
</form>

**注意“表单的动作是“ProcessNewOrder”**

这是我的控制器:

    public class processOrder : ControllerBase
{ 
    [HttpPost]
    public String ProcessNewOrder(Order order)
    {
        return "order received";
    }
}
}

问题:

  1. 如何更改此设置,以便在发布请求中提交此表单时向控制器提交新的订单模型?

我已经尝试过的:

  1. This example from Microsoft 没有帮助,因为它说我应该使用 ProcessOrder : Controller 但它似乎不起作用。 ControllerBase 是唯一可用的。当我尝试使用完全相同的导入时,它显示“控制器是一个命名空间,但被用作一种类型”。

  2. This second example from Microsoft 没有帮助,因为: (1) 示例代码不存在了 (2) 11岁以上 (3) 它实际上甚至没有显示正在使用的表单(没有帮助)

  3. 这两个似乎最接近,this examplethis other example 仍然指示我使用 : Controller 选项。

我将继续解决这个问题,但这似乎是一件相对常规的事情,我很惊讶没有人对此有明确的文档。

对于那些想知道的人:这是我的订单模型:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading.Tasks;

  namespace OrderProcessingApplication.Model
  {
      public class Order : Entity
      {
    
    public Order(Guid id, DateTime date, string customerName, string customerAddress, string 
       customerPhone, COLOR color, Size size, double price, int quantity, double totalCost, Status 
         status, string notes)
    {

        DateTime Date = date;
        string CustomerName = customerName;
        string CustomerAddress = customerAddress;
        string CustomerPhone = customerPhone;
        COLOR Color = color;
        Size Size = size;
        double Price = price;
        int Quantity = quantity;
        Status Status = status;
        double TotalCost = totalCost;
        string Notes = notes;

    }

    public DateTime Date { get; set; }
    string CustomerName { get; set; }
    string CustomerAddress { get; set; }
    string CustomerPhone { get; set; }
    COLOR Color { get; set; }
    Size size { get; set; }
    double price { get; set; }
    int Quantity { get; set; }
    Status Status { get; set; }
    double TotalCost { get; set; }
    string Notes { get; set; }
}

}

更新

我得到的错误总是一样的:

找不到此本地主机页面 没有找到该网络的网页 地址:https://localhost:44367/ProcessNewOrder HTTP ERROR 404

我尝试过以下更接近的示例之一:

namespace OrderProcessingApplication.Controller
{
    [Route("ProcessNewOrder")]
    [ApiController]
    public class processOrder : ControllerBase
    { 
        [HttpPost]
        public String ProcessNewOrder([FromBody] Order order)
        {
            return "order received";
        }
    }
}

再次出现同样的 404 错误。

【问题讨论】:

  • Route("/....") 或者它是一个相对路径......虽然我实际上会用表单标签助手修复它。
  • @JeremyLakeman 不起作用。完全相同的结果。
  • 我认为 MVC 只会绑定 c#9 记录类型的构造函数。否则,您将需要可设置的属性和默认构造函数。

标签: c# asp.net-mvc asp.net-core razor


【解决方案1】:

尝试将action="ProcessNewOrder" 更改为action="/ProcessNewOrder"。这是一个演示:

查看:

<form id="submitOrderForm" action="/ProcessNewOrder" method="post">
   

        <input type="submit" value="Submit">
</form>

控制器:

[Route("ProcessNewOrder")]
    [ApiController]
    public class processOrder : ControllerBase
    {
        [HttpPost]
        public String ProcessNewOrder()
        {
            return "order received";
        }
    }

结果:

更新:

如果你在 razor 页面应用中使用控制器,你需要在 startup.cs 中添加端点,如下所示:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

【讨论】:

  • 我确实有这个完全相同的代码,但它不起作用。
  • 所以你的意思是你使用相同的代码,你会去localhost:44367/ProcessNewOrder,but你得到404。你在剃须刀页面应用程序中使用控制器,对吧?
  • 答案是 startup.cs 中没有正确的端点。我不知道它是如何切换的,但这就是答案。谢谢!
【解决方案2】:

有多种方法可以提交表单或相关数据。您可以通过请求(通过表单提交或通过 ajax)或通过打开的套接字发送它。

其中一些可能比我们正在研究的情况要先进一些。

当您考虑通过表单提交来提交表单时,例如单击提交按钮并发布,然后在后台使用模型绑定器。

首先,路由处理程序启动,并使用反射获取 url 路径并将其映射到控制器操作,以便调用该方法并调用它。一旦发生这种情况,提交的表单的值就会被注入到参数中。

当使用经典的表单提交时(ajax 不同),动作结果中的参数名称无关紧要。但是,属性名称可以。当您将一个类定义为参数时,它本质上是一个具有属性的对象。模型绑定器将尝试使用表单中的值填充该对象中的任何属性值,方法是将 name="" 匹配为属性名称,然后获取该值并将其分配给属性值。

现在,模型被认为是由模型绑定器填充到操作结果中。然后你可以处理响应。通常使用return redirectToAction('ReturnViewName'); 来促进 POST-REDIRECT-GET 模式,也称为 PRG 模式。在您的情况下,您只是返回一个字符串,它可能会在完成后将其写入浏览器的屏幕。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 2023-04-09
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    相关资源
    最近更新 更多