问题描述
我有一个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:
- 创建视图的当前文件夹内的
EditorTemplates
文件夹(例如,如果你的观点是首页\\ Index.cshtml
,创建该文件夹首页\\ EditorTemplates
)。这个名字是很重要的,因为它遵循用于查找模板的惯例。 - 将这个文件夹中的部分观点。或者,把它放在
共享\\ EditorTemplates
文件夹中。 - 重新命名为
Datapoint.cshtml
局部视图(这很重要,因为模板的名称是基于类型的名称的约定)。
- Create an
EditorTemplates
folder inside your view's current folder (e.g. if your view isHome\Index.cshtml
, create the folderHome\EditorTemplates
). The name is important as it follows a convention for finding templates. - Place your partial view in that folder. Alternatively, put it in the
Shared\EditorTemplates
folder. - 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模式的后空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!