本文介绍了使用局部视图时,MVC模式的后空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个MVC控制器,其中对POST方法模型总是回来空。我不知道这是因为我使用的表格内的局部视图。

I have an MVC controller where the model on the post method always comes back as null. I'm not sure if this is because I am using a partial view within the form.

任何想法,为什么模型不被返回到控制器?

Any idea why the model is not being returned to the controller?

型号

加载模型

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;
}

控制器

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);
}

主视图

@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>

管窥

@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)

呈现的HTML呈现连续的ID

推荐答案

正如你正确地指出,这是因为你使用的部分。这是发生因为 Html.Partial 不知道,这是一个集经营,因此它不会与你结合的集合意向为您的表单元素的名称

As you've rightly noted, this is because you're using a partial. This is happening because Html.Partial has no idea that it's operating on a collection, so it doesn't generate the names for your form elements with your intention of binding to a collection.

不过,在你的情况下,修复似乎是相当简单的。而不是使用 Html.Partial ,你可以简单地改变你的部分成 EditorTemplate 并调用 Html.EditorFor 上模板。 Html.EditorFor 是足够聪明,知道什么时候它处理一个集合,所以它会调用你的模板集合中的每个项目,在窗体上生成正确的名称。

However, the fix in your case appears to be fairly straightforward. Rather than using Html.Partial, you can simply change your partial into an EditorTemplate and call Html.EditorFor on that template instead. Html.EditorFor is smart enough to know when it's handling a collection, so it will invoke your template for each item in the collection, generating the correct names on your form.

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

So to do what you need, follow these steps:


  1. 创建视图的当前文件夹内的 EditorTemplates 文件夹(例如,如果你的观点是首页\\ Index.cshtml ,创建该文件夹首页\\ EditorTemplates )。这个名字是很重要的,因为它遵循用于查找模板的惯例。

  2. 将这个文件夹中的部分观点。或者,把它放在共享\\ EditorTemplates 文件夹中。

  3. 重新命名为 Datapoint.cshtml 局部视图(这很重要,因为模板的名称是基于类型的名称的约定)。

  1. Create an EditorTemplates folder inside your view's current folder (e.g. if your view is Home\Index.cshtml, create the folder Home\EditorTemplates). The name is important as it follows a convention for finding templates.
  2. Place your partial view in that folder. Alternatively, put it in the Shared\EditorTemplates folder.
  3. Rename your partial view to Datapoint.cshtml (this is important as template names are based on the convention of the type's name).

现在相关视图code变为:

Now the relevant view code becomes:

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

这确保了你的观点的分离,因为你原本打算。

This ensures the separation of your views, as you had originally intended.

好了,所以我下面所提到的,现在的问题是,该模型粘结剂没有关联的方式数据点用正确的集团。最简单的解决方法是给视图code改成这样:

Alright, so as I mentioned below, the problem now is that the model binder has no way of associating a DataPoint with the correct Group. The simple fix is to change the view code to this:

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

这将产生正确的名字,并应解决模型绑定问题。

That will correctly generate the names, and should solve the model binding problem.

OP的编

继约翰的答案,我也作为HiddenFor的哪个游戏我的模型回到了岗位上组表缺少的属性。

Following John's answer I also included the missing properties on the Group table as HiddenFor's which game me the model back on the post.

@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 />
}

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

我对使用 EditorTemplate 每个数据点也适用于每个集团。而不是需要的循环,再次在视图洒逻辑,那么就可以避免完全由设立 EditorTemplate 。同样的步骤在哪里把模板条款上述适用。

Update 2 - Cleaner solution

My advice for using an EditorTemplate for each DataPoint also applies to each Group. Rather than needing the for loop, again sprinkling logic in the view, you can avoid that entirely by setting up an EditorTemplate for Group. Same steps apply as above in terms of where to put the template.

在这种情况下,模板将 Group.cshtml ,并且将如下所示:

In this case, the template would be Group.cshtml, and would look as follows:

@model Jmp.StaticMeasures.Models.Group

<h2>@Model.Name</h2>
@Html.EditorFor(m => m.DataPoints)
<hr />

如上所述,这将调用模板集合中的每个项目,这也将产生正确的指数每个。原始视图现在可以简化为:

As discussed above, this will invoke the template for each item in the collection, which will also generate the correct indices for each Group. Your original view can now be simplified to:

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

@using (Html.BeginForm())
{
    // Other markup
    @Html.EditorForModel();
}

这篇关于使用局部视图时,MVC模式的后空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 10:08