【问题标题】:MVC Form not able to post List of objectsMVC 表单无法发布对象列表
【发布时间】: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 解决这个问题,但这违背了目的!任何帮助将不胜感激!

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 asp.net-mvc-partialview


    【解决方案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" />
    

    该索引使模型绑定器能够关联单独的数据片段,从而构建正确的模型。所以这就是我建议你解决它的方法。与其使用局部视图循环遍历您的集合,不如利用模板的强大功能。以下是您需要遵循的步骤:

    1. 在视图的当前文件夹内创建一个EditorTemplates 文件夹(例如,如果您的视图是Home\Index.cshtml,则创建文件夹Home\EditorTemplates)。
    2. 在该目录中创建一个名称与您的模型匹配的强类型视图。你的情况是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 足够聪明,可以知道他们何时处理集合。这意味着它们会自动为您的表单元素生成正确的名称,包括索引,以便您可以正确地建模绑定到集合。

    【讨论】:

    • 谢谢,今天这个答案真的帮到了我。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 2018-11-13
      相关资源
      最近更新 更多