2013-07-08 163 views
0

我在ASP.NET網站的一個特定部分遇到問題。該頁面基本上是用戶編輯發票併發布更改的地方。通過POST傳遞模型

在這一點上,我正在重寫一個現有的頁面,它的工作原理。我想不出有什麼區別以外的另一種是較舊的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」的模型視圖是List

現在的觀點加載罰款,並顯示所有表單中的憑證行項目:

<%@ 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。發生什麼事!?

+0

看,它們會在你的HTML生成的表單元素的'name'屬性。看起來他們會有一點點關閉。對於輸入字段,我總是看到使用'for'循環而不是'foreach'完成MVC表單帖子,'Html.TextBoxFor(x => x [i] .Price)'。這給了字段唯一的名稱,並正確地發佈收集。我不知道是否有辦法讓你的例子工作。 –

回答

2

當您使用Html.TextBox(string, object)時,第一個參數將用作表單字段的名稱。當您將此表單發回服務器時,MVC將查看您的操作方法的參數列表,並使用表單字段的名稱來嘗試構建這些參數。在你的情況下,它試圖建立一個List<SalesDocumentLineItem>

它看起來像你使用「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進入更詳細的關於究竟是如何工作的。)

+0

這立即解決了我的問題。只要我將HTML幫助程序更改爲「For」等效項,它就起作用了。 MVC4中肯定有東西,我無視我的感謝您的協助! – user1104203