使用部分视图时,MVC模型在帖子上为空

Phi*_*ray 8 c# asp.net-mvc asp.net-mvc-4

我有一个MVC控制器,其中post方法上的模型总是返回null.我不确定这是因为我在表单中使用了局部视图.

知道为什么模型没有返回控制器吗?

模型

在此输入图像描述

加载模型

public List<Group> GetStaticMeasures(int businessUnitID)
{
    List<Group> groups = ctx.Groups
                           .Include("Datapoints")
                           .Where(w => w.BusinessUnitID.Equals(businessUnitID))
                           .OrderBy(o => o.SortOrder).ToList();

    groups.ForEach(g => g.Datapoints = g.Datapoints.OrderBy(d => d.SortOrder).ToList());

    return groups;
}
Run Code Online (Sandbox Code Playgroud)

调节器

public ActionResult Data()
{
    ViewBag.Notification = string.Empty;

    if (User.IsInRole(@"xxx\yyyyyy"))
    {
        List<Group> dataGroups = ctx.GetStaticMeasures(10);
        return View(dataGroups);
    }
    else
    {
        throw new HttpException(403, "You do not have access to the data.");
    }
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Data(List<Group> model)
{
    ViewBag.Notification = string.Empty;

    if (User.IsInRole(@"xxx\yyyyyy"))
    {
        if (ModelState.IsValid)
        {
            ctx.SaveChanges(model);
            ViewBag.Notification = "Save Successful";
        }
    }
    else
    {
        throw new HttpException(403, "You do not have access to save the data.");
    }

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

主要观点

@model List<Jmp.StaticMeasures.Models.Group>

<div class="row">
    @using (Html.BeginForm())
    { 
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)     

        <div class="large-12">
            <div class="large-8 large-centered columns panel">
                @foreach (var g in @Model)
                { 
                    <h2>@g.Name</h2>
                    foreach (var d in g.Datapoints)
                    { 
                        @Html.Partial("Measures", d)                                 
                    }
                    <hr />
                }   

                <input type="submit" class="button" value="Save Changes"/>

            </div>
        </div>    
    }
</div>
Run Code Online (Sandbox Code Playgroud)

局部视图

@model Jmp.StaticMeasures.Models.Datapoint

@Html.HiddenFor(d => d.ID)
@Html.HiddenFor(d => d.Name) 
@Html.HiddenFor(d => d.SortOrder)

@Html.DisplayTextFor(d => d.Name)
@Html.EditorFor(d => d.StaticValue)   
@Html.ValidationMessageFor(d => d.StaticValue)                      
Run Code Online (Sandbox Code Playgroud)

呈现显示连续ID的Html

在此输入图像描述

Joh*_*n H 14

正如你正确指出的那样,这是因为你使用的是偏爱的.这种情况正在发生,因为Html.Partial它不知道它在一个集合上运行,所以它不会为你的表单元素生成你想要绑定到集合的名称.

但是,您的案例中的修复似乎相当简单.而不是使用Html.Partial,你可以简单地改变你的部分为EditorTemplate,并调用Html.EditorFor,而不是该模板. Html.EditorFor非常聪明,可以知道它何时处理集合,因此它将为集合中的每个项目调用模板,在表单上生成正确的名称.

所以要做你需要的,请按照下列步骤操作:

  1. EditorTemplates在视图的当前文件夹中创建一个文件夹(例如,如果您的视图是Home\Index.cshtml,则创建该文件夹Home\EditorTemplates).名称很重要,因为它遵循查找模板的惯例.
  2. 将部分视图放在该文件夹中.或者,将其放在Shared\EditorTemplates文件夹中.
  3. 将部分视图重命名为Datapoint.cshtml(这很重要,因为模板名称基于类型名称的约定).

现在相关的视图代码变为:

// Note:  I removed @ from Model here.
@foreach (var g in Model)
{ 
    <h2>@g.Name</h2>
    @Html.EditorFor(m => g.DataPoints)
    <hr />
}
Run Code Online (Sandbox Code Playgroud)

这可以确保您的视图分离,就像您最初的预期一样.

每条评论更新

好吧,正如我在下面提到的,现在的问题是模型绑定器无法将a DataPoint与正确关联Group.简单的解决方法是将视图代码更改为:

for (int i = 0; i < Model.Count; i++)
{ 
    <h2>@Model[i].Name</h2>
    @Html.EditorFor(m => m[i].DataPoints)
    <hr />
}
Run Code Online (Sandbox Code Playgroud)

这将正确生成名称,并应解决模型绑定问题.

OP的附录

按照John的回答,我还将Group表中缺少的属性包含在HiddenFor中,然后将模型重新发布在帖子上.

@for (int i = 0; i < Model.Count(); i++)
{ 
    @Html.HiddenFor(t => Model[i].ID)
    @Html.HiddenFor(t => Model[i].BusinessUnitID)
    @Html.HiddenFor(t => Model[i].SortOrder)
    @Html.HiddenFor(t => Model[i].Name)

    <h2>@Model[i].Name</h2>
    @Html.EditorFor(m => Model[i].Datapoints)                                 
    <hr />                    
}
Run Code Online (Sandbox Code Playgroud)

更新2 - 更清洁的解决方案

EditorTemplate对每个使用a的建议DataPoint也适用于每个Group.而不是需要for循环,再次在视图中喷洒逻辑,您可以完全通过设置EditorTemplatefor 来避免这种情况Group.在放置模板的位置方面,上述步骤同样适用.

在这种情况下,模板将是Group.cshtml,并将看起来如下:

@model Jmp.StaticMeasures.Models.Group

<h2>@Model.Name</h2>
@Html.EditorFor(m => m.DataPoints)
<hr />
Run Code Online (Sandbox Code Playgroud)

如上所述,这将为集合中的每个项调用模板,这也将为每个项生成正确的索引Group.您的原始视图现在可以简化为:

@model List<Jmp.StaticMeasures.Models.Group>

@using (Html.BeginForm())
{
    // Other markup
    @Html.EditorForModel();
}
Run Code Online (Sandbox Code Playgroud)