这个问题已经问过了,但是没有人能解决我的问题。问题是缺少或来自部分视图的空数据未与主视图数据一起提交(POST)。
我有一个名为_Address的类型化部分视图。cshtml,我将其包含在另一个名为Site.cshtml的视图中。
类型化站点视图绑定到名为SiteEditModel.cs
的视图模型public class SiteEditModel
{
...properties
public AddressEditModel Address {get;set;}
public SiteEditModel()
{
Address = new AddressEditModel();
}
}
Site视图有一个表单:
@model Insight.Pos.Web.Models.SiteEditModel
...
@using ( Html.BeginForm( "Edit", "Site", FormMethod.Post ) )
{
@Html.HiddenFor( m => m.SiteId )
...
@Html.Partial( "~/Views/Shared/Address.cshtml", this.Model.Address )
...
@Html.SaveChangesButton()
}
部分地址视图只是一堆@Html…绑定到Address模型的调用。
@model Insight.Pos.Web.Models.AddressEditModel
@{
Layout = null;
}
<div>
@Html.HiddenFor(...)
@Html.HiddenFor(...)
@Html.HiddenFor(...)
@hmtl.LabelFor(...)
</div>
在控制器操作Edit中,我可以看到SiteEditModel是正确填充的,但该模型的Address属性不是。我哪里做错了?
http://davybrion.com/blog/2011/01/prefixing-input-elements-of-partial-views-with-asp-net-mvc/
@Html.Partial("~/Views/Shared/_Address.cshtml", Model.Address, new ViewDataDictionary
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Address" }
})
解决这个问题的关键是命名partialviews的输入元素。渲染部分不知道它是某个更大的东西的一部分。
我已经做了一个简单的例子,如何解决这个问题,你可以有多个地址使用相同的部分视图:
public static class HtmlHelperExtensions
{
public static MvcHtmlString PartialWithPrefix(this HtmlHelper html, string partialViewName, object model, string prefix)
{
var viewData = new ViewDataDictionary(html.ViewData)
{
TemplateInfo = new TemplateInfo
{
HtmlFieldPrefix = prefix
}
};
return html.Partial(partialViewName, model, viewData);
}
}
在视图中使用如下扩展:
@using (Html.BeginForm("Edit", "Site", FormMethod.Post))
{
@Html.HiddenFor(m => m.SiteId)
@Html.PartialWithPrefix("_Adress", this.Model.Address, "Address")
<input type="submit" />
}
你当然可以用表达式和反射让它更花哨一点,但那是另一个问题;-)
您的SiteEditModel
Address
属性未标记为public
,更改为:
public AddressEditModel Address {get;set;}
我也会改变你的部分使用SiteEditModel
代替:
@model Insight.Pos.Web.Models.SiteEditModel
@{
Layout = null;
}
<div>
@Html.HiddenFor(m => m.Address.FooProperty)
...
</div>
这将意味着您的属性最终将被正确命名,以便模型绑定器拾取它们。使用上面的示例,它将是Name"=Address.FooProperty"
。
我没记错,问题是Html.Partial
没有正确地填充输入名称。您应该设置如下:
<input id="Address.Street" name="Address.Street" />
但我假设你有以下HTML:
<input id="Street" name="Street" />
你有几个解决方案:
手动插入输入名称:
@Html.HiddenFor(x => x.Street, new { Name = "Address.Street" })
使用
Html.EditorFor()
覆盖
Html.Partial()
中解析的名称
第一个解决方案的缺点是您正在硬编码属性名称,这是不理想的。我建议使用Html.EditorFor()
或Html.DisplayFor()
帮助程序,因为它们可以正确填充输入名称。
如果在局部视图中填充子模型,则模型绑定器无法正确绑定子模型。考虑使用编辑器模板,因为它是为此而实现的。
把你的AddressEditModel.cshtml
文件放在ViewsSharedEditorTemplates
文件夹中,在你的主视图中使用如下命令:
@using ( Html.BeginForm( "Edit", "Site", FormMethod.Post ) )
{
// because model type name same as template name MVC automatically picks our template
@Html.EditorFor(model=>model.Address)
// or if names do not match set template name explicitly
@Html.EditorFor(model=>model.Address,"NameOfTemplate")
}