ViewModel:
public class CreateCDViewModel { public CustomsDeclaration CustomsDeclaration { get; set; } public IEnumerable<PurchaseOrderDetail> PurchaseOrderDetail { get; set; } public CreateCDViewModel() { CustomsDeclaration = new CustomsDeclaration(); } }
View绑定CreateCDViewModel,利用IEnumerable<PurchaseOrderDetail>显示表格:
订单号 | 发票号 | 供应商 | 物料号 | 数量 | 金额 |
---|---|---|---|---|---|
14/10/21-010-ZE-T | 2300072371 | HARTNGD | 1159644-00 | 800.00 | 6700.55 |
14/10/21-010-ZE-T | 2300072371 | HARTNGD | 1159649-00 | 300.00 | 3455.78 |
14/10/21-010-ZE-T | 2300072371 | HARTNGD | 1159650-00 | 350.00 | 3500.00 |
14/10/21-011-ZE-T | 2300072372 | HARTNGD | 1159644-00 | 200.00 | 2500.00 |
14/10/21-011-ZE-T | 2300072372 | HARTNGD | 1159649-00 | 400.00 | 4305.00 |
页面提交POST,想把表格内容传回Controller的HTTP POST Action,Action同样传回的是ViewModel,但是IEnumerable<PurchaseOrderDetail>无法获取到任何值;
View 代码:
@model FreightOrderTraceability.ViewModels.CreateCDViewModel @using (Html.BeginForm()) { @Html.AntiForgeryToken() <input type="submit" value="创建" class="btn btn-default" /> <table class="table table-striped table-bordered table-hover"> <thead> <tr> @*<th></th>*@ <th>订单号</th> <th>发票号</th> <th>供应商</th> <th>物料号</th> <th>数量</th> <th>金额</th> </tr> </thead> <tbody> @foreach (var item in Model.PurchaseOrderDetail) { @Html.HiddenFor(modelItem => item.Id) <tr> @*<td class="text-center">@Html.CheckBoxFor(modelItem => item.IsSelected)</td>*@ <td>@Html.DisplayFor(modelItem => item.PurchaseOrder.OrderNum) @Html.HiddenFor(modelItem => item.PurchaseOrder.OrderNum)</td> <td>@Html.DisplayFor(modelItem => item.PurchaseOrder.InvoiceNum) @Html.HiddenFor(modelItem => item.PurchaseOrder.InvoiceNum)</td> <td>@Html.DisplayFor(modelItem => item.PurchaseOrder.Supplier)</td> <td>@Html.DisplayFor(modelItem => item.PartNum)</td> <td>@Html.DisplayFor(modelItem => item.Qty)</td> <td>@Html.DisplayFor(modelItem => item.Amount)</td> </tr> } </tbody> </table> }
Controller:
public ActionResult Index()
{
CreateCDViewModel createCDViewModel = new CreateCDViewModel();
createCDViewModel.PurchaseOrderDetail = db.PurchaseOrderDetails.Include(p => p.PurchaseOrder);
return View(createCDViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(CreateCDViewModel createCDViewModel)
{
if (ModelState.IsValid)
{
TempData["QueryPOViewModel"] = createCDViewModel.PurchaseOrderDetail;
return RedirectToAction("Create", "CustomsDeclarations");
}
return View(createCDViewModel);
}
蓝色部分,传入页面的时候是有值的,黄色部分,POST传回时没有值。
请问:如何让控制器能绑定IEnumerable类型的模型?亦或者是IEnumerable是无法实现MVC绑定的,必须使用javascript返回JSON,然后在Controller接收?原生MVC无法实现获取表格内容吗?
正好前两天碰到这个问题。http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
另外记得哦,@Html.DisplayFor,是无法post到服务器的。input才可以的。
@Html.DisplayFor的值是不需要post的,主要是要传 @Html.HiddenFor(modelItem => item.Id) 的值post到Controller,这个文章我看了,IEnumerable和ICollection应该没大的区别,我也没看出和我写法的原理区别,也许是Razor的写法区别哪里有差错我没有对比出来;
@夕阳寸草畔:
数据POST到服务器端,获取数据是根据INPUT标签的Name,
<input type="hidden" name="PurchaseOrderDetail[0].Id" value="id" />
如果你获取的是集合的话,你页面输出的HTML应该是类似上面这样的。
这里需要注意下标是从0开始,并且不能中断。我看你页面上还有Checkbox,所以提交的数据下标有可能中断。
比如用户没有选择第一条数据,提交的数据下标就不是从0开始,那么PurchaseOrderDetail就获取不到值,根据你的需求建议你使用自定义下标,如下所示:
<input type="hidden" name="PurchaseOrderDetail.Index" value="0" /> <input type="text" name="PurchaseOrderDetail[0].Id" value="id" />
加油。
@写代码的小2B:
我看了下网页源代码,name的值没有下标,某列的每行的name值都是一样的,但我并不知道用Razor语法的话,怎么用HtmlHelper来写出下标,我这个是系统自动生成的html标签。
<tbody> <tr> <td class="text-center"><input type="checkbox"></td> <td><input data-val="true" data-val-number="字段 Id 必须是一个数字。" data-val-required="Id 字段是必需的。" id="item_Id" name="item.Id" type="hidden" value="8" /></td> <td>14/10/21-010-ZE-T <input data-val="true" data-val-required="订单号 字段是必需的。" id="item_PurchaseOrder_OrderNum" name="item.PurchaseOrder.OrderNum" type="hidden" value="14/10/21-010-ZE-T" /></td> <td>2300072371 <input data-val="true" data-val-required="发票号 字段是必需的。" id="item_PurchaseOrder_InvoiceNum" name="item.PurchaseOrder.InvoiceNum" type="hidden" value="2300072371" /></td> <td>HARTING</td> <td>1159644-00</td> <td>800.00</td> <td>6700.55</td> </tr> <tr> <td class="text-center"><input type="checkbox"></td> <td><input id="item_Id" name="item.Id" type="hidden" value="9" /></td> <td>14/10/21-010-ZE-T <input id="item_PurchaseOrder_OrderNum" name="item.PurchaseOrder.OrderNum" type="hidden" value="14/10/21-010-ZE-T" /></td> <td>2300072371 <input id="item_PurchaseOrder_InvoiceNum" name="item.PurchaseOrder.InvoiceNum" type="hidden" value="2300072371" /></td> <td>HARTING</td> <td>1159649-00</td> <td>300.00</td> <td>3455.78</td> </tr> <tr> <td class="text-center"><input type="checkbox"></td> <td><input id="item_Id" name="item.Id" type="hidden" value="11" /></td> <td>14/10/21-010-ZE-T <input id="item_PurchaseOrder_OrderNum" name="item.PurchaseOrder.OrderNum" type="hidden" value="14/10/21-010-ZE-T" /></td> <td>2300072371 <input id="item_PurchaseOrder_InvoiceNum" name="item.PurchaseOrder.InvoiceNum" type="hidden" value="2300072371" /></td> <td>HARTING</td> <td>1159650-00</td> <td>350.00</td> <td>3500.00</td> </tr> <tr> <td class="text-center"><input type="checkbox"></td> <td><input id="item_Id" name="item.Id" type="hidden" value="12" /></td> <td>14/10/21-011-ZE-T <input id="item_PurchaseOrder_OrderNum" name="item.PurchaseOrder.OrderNum" type="hidden" value="14/10/21-011-ZE-T " /></td> <td>2300072372 <input id="item_PurchaseOrder_InvoiceNum" name="item.PurchaseOrder.InvoiceNum" type="hidden" value="2300072372" /></td> <td>HARTING </td> <td>1159644-00</td> <td>200.00</td> <td>2500.00</td> </tr> <tr> <td class="text-center"><input type="checkbox"></td> <td><input id="item_Id" name="item.Id" type="hidden" value="13" /></td> <td>14/10/21-011-ZE-T <input id="item_PurchaseOrder_OrderNum" name="item.PurchaseOrder.OrderNum" type="hidden" value="14/10/21-011-ZE-T " /></td> <td>2300072372 <input id="item_PurchaseOrder_InvoiceNum" name="item.PurchaseOrder.InvoiceNum" type="hidden" value="2300072372" /></td> <td>HARTING </td> <td>1159649-00</td> <td>400.00</td> <td>4305.00</td> </tr> </tbody>
@夕阳寸草畔:
不一定要用这个@Html这种写法,直接输出INPUT就好。
@写代码的小2B:
不用@Html的话,请问如何绑定到@model上?
@夕阳寸草畔:
<input type="text" name="PurchaseOrderDetail[0].Id" value="@item.Id" />
直接这样输出就可以了。
给你看看我的例子
@foreach (var item in users.Where(m => m.OSType == type)) { <label class="checkbox-inline"> <input type="hidden" name="Notices.Index" value="@item.Id" /> <input type="checkbox" name="@String.Concat("Notices[",item.Id,"].AppUserName")" value="@item.AppUserName">@item.AppUserName <input type="checkbox" name="@String.Concat("Notices[",item.Id,"].OSType")" value="@item.OSType" style="display:none;" /> <input type="checkbox" name="@String.Concat("Notices[",item.Id,"].AppUserAccount")" value="@item.AppUserAccount" style="display:none;" /> <input type="checkbox" name="@String.Concat("Notices[",item.Id,"].iOSPushToken")" value="@item.iOSPushToken" style="display:none;" /> </label> }
和你的需求应该是一样的。
@写代码的小2B:
谢谢,通过拼接name属性得到传值,我刚开始搞错意思了,原来name=PurchaseOrderDetail[].Id的黄色部分必须和绑定的Model的名字PurchaseOrderDetail相同,我以为我用item,Razor会自动为我转换的。
不过我感觉这种写法有点歪门邪道的意思,不过问题是解决了,谢谢。
实际上form是可以数组接的,只是很麻烦。很不好用。这种复杂情况还是用json传把。