MVC 表单无法发布对象列表
Posted
技术标签:
【中文标题】MVC 表单无法发布对象列表【英文标题】:MVC Form not able to post List of objects 【发布时间】:2013-11-26 16:33:48 【问题描述】:所以我有一个有问题的 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>
这些是上面代码的类:
平面视图模型:
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”,它包含正确的值。谁能看到为什么活页夹没有创建正确的对象?我可以使用 javascript 解决这个问题,但这违背了目的!任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:您的模型是null
,因为您向表单提供输入的方式意味着模型绑定器无法区分元素。现在,这段代码:
@foreach (var planVM in Model)
@Html.Partial("_partialView", planVM)
没有为这些项目提供任何类型的索引。所以它会重复生成这样的 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" />
该索引使模型绑定器能够关联单独的数据片段,从而构建正确的模型。所以这就是我建议你解决它的方法。与其使用局部视图循环遍历您的集合,不如利用模板的强大功能。以下是您需要遵循的步骤:
-
在视图的当前文件夹内创建一个
EditorTemplates
文件夹(例如,如果您的视图是Home\Index.cshtml
,则创建文件夹Home\EditorTemplates
)。
在该目录中创建一个名称与您的模型匹配的强类型视图。你的情况是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>
DisplayTemplates
和 EditorTemplates
足够聪明,可以知道他们何时处理集合。这意味着它们会自动为您的表单元素生成正确的名称,包括索引,以便您可以正确地建模绑定到集合。
【讨论】:
谢谢,今天这个答案真的帮到了我。【参考方案2】:请阅读:http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
您应该为您的 html 元素“名称”属性设置索引,例如 planCompareViewModel[0].PlanId
、planCompareViewModel[1].PlanId
,以使 binder 能够将它们解析为 IEnumerable。
而不是 @foreach (var planVM in Model)
使用 for
循环并使用索引呈现名称。
【讨论】:
以上是关于MVC 表单无法发布对象列表的主要内容,如果未能解决你的问题,请参考以下文章