【问题标题】:Passing Model Through POST通过 POST 传递模型
【发布时间】:2013-07-08 21:25:18
【问题描述】:

我的 ASP.NET 网站的某个特定部分出现了一些问题。此页面本质上是用户编辑发票然后发布更改的地方。

此时,我正在重写现有页面,这很有效。除了旧的 MVC 3 之外,我不知道有什么区别。

当我第一次进入 EditInvoice 操作时:

public ActionResult EditInvoice()
{
    SalesDocument invoice = null;

    try
    {
        invoice = SomeService.GetTheInvoice();
    }
    catch (Exception ex)
    {
        return HandleControllerException(ex);
    }

    return View("InvoiceEdit", invoice.LineItems);
}

“InvoiceEdit”视图的模型是列表

现在视图加载正常,并在一个表单中显示所有文档行项目:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<MyApp.SalesDocumentLineItem>>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Line Items</legend>
            <div id="lineItems" class="table">
                <div class="row">
                    <div class="colHButton">X</div>
                    <div class="colH">Item</div>
                    <div class="colHPrice">Price</div>
                    <div class="colHQty">Qty</div>
                </div>
              <% foreach (var item in Model.Where(m => m.LineItemType.Id == NexTow.Client.Framework.UnitsService.LineItemTypes.SaleItem || m.LineItemType.Id == NexTow.Client.Framework.UnitsService.LineItemTypes.NonSaleItem))
              { %>    
                <div class="row">
                    <%=Html.Hidden("Model.LineItemNameId", item.LineItemNameId)%>
                    <div class="cellButton"><button onclick="DeleteContainer(event);">X</button></div>
                    <div class="cell"><span class="formData"><%=item.LineItemDescription %></span></div>                
                    <div class="cellPrice">
                        <span class="formData">$</span>
                        <%= Html.TextBox("Model.Price", item.Price, new { style="width:75px;" })%>
                    </div>
                    <div class="cellQty">
                        <%= Html.TextBox("Model.Quantity", item.Quantity, new { style = "width:60px;" })%>
                    </div>
                </div>  
            <%} %>
        </div>
    </fieldset>
    <p>
        <input type="submit" value="Update Invoice" onclick="SequenceFormElementsNames('salesItems');" />
    </p>

    <% } %>
</asp:Content>

这使用户能够编辑条目,然后用户单击“更新发票”提交按钮。这使用 POST 发布到相同的视图和操作:

[HttpPost]
public ActionResult EditInvoice(List<SalesDocumentLineItem> salesItems)
{
    if (salesItems == null || salesItems.Count == 0)
    {
        return View("ClientError", new ErrorModel() { Description = "Line items required." });
    }

    SalesDocument invoice = null;

    try
    {
        invoice = SomeService.UpdateInvoice();
    }
    catch (Exception ex)
    {
        return HandleControllerException(ex);
    }

    InvoiceModel model = new InvoiceModel();
    model.Document = invoice;

    return View("InvoicePreview", model);
}

但是,尽管这在旧应用程序中有效。在新版本中,这不起作用。当我们在最终的 EditInvoice POST 操作方法处断点时,salesItems 的集合为 NULL。发生了什么事!?

【问题讨论】:

  • 查看在 HTML 中生成的表单元素的 name 属性。看起来他们会差很多。我总是看到 MVC 表单帖子使用 for 循环而不是 foreachHtml.TextBoxFor(x =&gt; x[i].Price) 来完成输入字段。这为字段提供了唯一的名称,并正确发布了集合。我不知道是否有办法让您的示例工作。

标签: asp.net-mvc-4


【解决方案1】:

当您使用Html.TextBox(string, object) 时,第一个参数用作表单字段的名称。当您将此表单发送回服务器时,MVC 会查看您的操作方法的参数列表并使用表单字段的名称来尝试构建这些参数。在您的情况下,它会尝试构建一个List&lt;SalesDocumentLineItem&gt;

您似乎使用“Model.Something”作为表单字段的名称。这可能在过去有效,但我猜 MVC4 中发生了一些变化,以至于框架不再知道你在说什么。幸运的是,有更好的方法。

不要使用字符串设置表单字段的名称,而是使用强类型 HTML 帮助器,如下所示:

<% for (var i = 0; i < Model.Count; i++) { %>
  <div class="row">
    <%= Html.HiddenFor(model => model[i].LineItemNameId) %>
    <!-- etc... -->
  </div>
<% } %>

这些版本的 HTML 帮助程序使用 lambda 表达式 来指向模型中的一个属性并说“看到那个属性了吗?就在那儿吗?为它生成一个适当的表单字段名称。” (奖励:由于表达式无论如何都指向属性,因此您不必再指定值 - MVC 将只使用表达式所代表的属性的值)

由于 lambda 表达式是 C# 代码,如果输入错误,您将收到编译时错误,并且如果您更改属性名称,Visual Studio 的“重命名”功能等工具将起作用。

This answer 更详细地说明了它的工作原理。)

【讨论】:

  • 这立即解决了我的问题。一旦我将 HTML 帮助器更改为“For”等价物,它就起作用了。 MVC4 中一定有一些东西我忽略了感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-23
  • 2019-03-09
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多