MVC表单无法发布对象列表

所以我有一个有问题的MVC Asp.net应用程序。 基本上,我有一个包含窗体的视图,其内容绑定到一个对象列表。 在这个循环中,它加载PartialView的项目被循环。 现在一切正常,直到提交表格。 当它被提交时,控制器被发送一个空对象列表。 下面的代码演示了这些问题。

父视图:

@model IEnumerable<PlanCompareViewModel> @using (Html.BeginForm("ComparePlans", "Plans", FormMethod.Post, new { id = "compareForm" })) { <div> @foreach (var planVM in Model) { @Html.Partial("_partialView", planVM) } </div> } 

_partialView:

 @model PlanCompareViewModel <div> @Html.HiddenFor(p => p.PlanID) @Html.HiddenFor(p => p.CurrentPlan) @Html.CheckBoxFor(p => p.ShouldCompare) <input type="submit" value="Compare"/> </div> 

这些是上述代码的类:

PlanViewModel:

 public class PlansCompareViewModel { public int PlanID { get; set; } public Plan CurrentPlan { get; set; } public bool ShouldCompare { get; set; } public PlansCompareViewModel(Plan plan) { ShouldCompare = false; PlanID = plan.PlanId; CurrentPlan = plan; } public PlansCompareViewModel() { // TODO: Complete member initialization } public static IEnumerable<PlansCompareViewModel> CreatePlansVM(IEnumerable<Plan> plans) { return plans.Select(p => new PlansCompareViewModel(p)).AsEnumerable(); } } 

控制器:

 public class PlansController : MyBaseController { [HttpPost] public ActionResult ComparePlans(IEnumerable<PlanCompareViewModel> model) { //the model passed into here is NULL } } 

问题在于控制器的行为。 据我所知,它应该发布PlanCompareViewModels的可枚举列表,但它是空的。 在检查正在发送的发布数据时,发送正确的参数。 如果我要将“IEnumerable”更改为“FormCollection”,它将包含正确的值。 任何人都可以看到为什么活页夹不创build正确的对象? 我可以解决这个使用javascript,但是这个失败的目的! 任何帮助将不胜感激!

您的模型为null因为您向input提供input的方式意味着模型联编程序无法区分这些元素。 现在,这个代码:

 @foreach (var planVM in Model) { @Html.Partial("_partialView", planVM) } 

没有提供任何types的索引这些项目。 所以它会重复生成像这样的HTML输出:

 <input type="hidden" name="yourmodelprefix.PlanID" /> <input type="hidden" name="yourmodelprefix.CurrentPlan" /> <input type="checkbox" name="yourmodelprefix.ShouldCompare" /> 

但是,如果您想绑定到集合,则需要使用索引来命名表单元素,例如:

 <input type="hidden" name="yourmodelprefix[0].PlanID" /> <input type="hidden" name="yourmodelprefix[0].CurrentPlan" /> <input type="checkbox" name="yourmodelprefix[0].ShouldCompare" /> <input type="hidden" name="yourmodelprefix[1].PlanID" /> <input type="hidden" name="yourmodelprefix[1].CurrentPlan" /> <input type="checkbox" name="yourmodelprefix[1].ShouldCompare" /> 

该索引使模型联编程序能够将单独的数据关联起来,从而构build正确的模型。 所以这里是我build议你做的解决它。 而不是循环使用部分视图,而是利用模板的强大function。 以下是您需要遵循的步骤:

  1. 在视图的当前文件夹内创buildEditorTemplates文件夹(例如,如果您的视图是Home\Index.cshtml ,则创build文件夹Home\EditorTemplates )。
  2. 在该目录中创build一个与您的模型匹配的名称的强types视图。 在你的情况下,这将是PlanCompareViewModel.cshtml

现在,你在局部视图中拥有的所有东西都希望进入该模板:

 @model PlanCompareViewModel <div> @Html.HiddenFor(p => p.PlanID) @Html.HiddenFor(p => p.CurrentPlan) @Html.CheckBoxFor(p => p.ShouldCompare) <input type="submit" value="Compare"/> </div> 

最后,你的父视图简化为:

 @model IEnumerable<PlanCompareViewModel> @using (Html.BeginForm("ComparePlans", "Plans", FormMethod.Post, new { id = "compareForm" })) { <div> @Html.EditorForModel() </div> } 

DisplayTemplatesEditorTemplates足够聪明,知道他们什么时候处理集合。 这意味着他们将自动为您的表单元素生成正确的名称(包括索引),以便您可以正确build模绑定到集合。

请阅读: http : //haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
您应该为您的html元素“名称”属性设置标记,例如planCompareViewModel[0].PlanIdplanCompareViewModel[1].PlanId以使绑定器能够将它们parsing为IEnumerable。
而不是@foreach (var planVM in Model)使用循环和渲染名称与索引。