如何确保模型绑定能够按预期工作
本文关键字:工作 绑定 模型 何确保 确保 | 更新日期: 2023-09-27 18:24:53
我正在C#ASP.NET MVC4(Razor引擎)中编程。我需要创建一个局部视图,并在多个地方重用它。问题是视图是一个表单,在某些情况下,我需要将它与ViewModel一起使用。我的问题是模型绑定将如何工作,因为在ViewModel中,它将是属性的属性。示例:
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class OfficeViewModel
{
public PersonModel Person { get; set; }
// other properties
}
PersonModel的部分视图是:
@model SomeNameSpace.PersonModel
@Html.TextBoxFor(m => m.FirstName)
@Html.TextBoxFor(m => m.LastName)
当这个视图被渲染时,它看起来像这样:
<input type="textbox" id="FirstName" name="FirstName" />
<input type="textbox" id="LastName" name="LastName" />
现在,我想在OfficeViewModel中使用相同的视图。在这种情况下,我会在我的办公室视图中这样做:
@{ Html.RenderPartial("Person", Model.Person); }
渲染此局部视图时,将按上面所示进行渲染。如果我不重复使用该视图,我的Office视图将是这样的:
@model SomeNameSpace.OfficeViewModel
@Html.TextBoxFor(m => m.Person.FirstName)
@Html.TextBoxFor(m => m.Person.LastName)
这将被呈现为:
<input type="textbox" id="Person_FirstName" name="Person.FirstName" />
<input type="textbox" id="Person_LastName" name="Person.LastName" />
请注意name属性如何具有Person前缀属性。因此,如果我使用RenderPartial选项并传入Model.Person,模型绑定器会知道在OfficeViewModel中绑定FirstName和LastName 如果模型绑定器足够聪明,可以检查属性的属性,那么当我在OfficeViewModel中有一个ManagerModel和EmployeeModel,并且它们都有名为FirstName和LastName的属性时,会发生什么? 我希望我已经清楚了,并提前表示感谢。
不幸的是,在这种情况下,Html.RenderPartial没有携带得出正确字段名所需的信息。
如果您想以这种方式重用局部视图,请考虑将编辑器模板与Html.EditorFor一起使用。与其他*For帮助程序一样,EditorFor采用lambda表达式,该表达式允许它继承传递到模板的属性的名称。
@Gerald是对的。默认的RenderPartial
无法解决。尽管你可以编写一个自定义的助手来处理这个问题:
public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
{
string name = ExpressionHelper.GetExpressionText(expression);
object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
var viewData = new ViewDataDictionary(helper.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo
{
HtmlFieldPrefix = name
}
};
return helper.Partial(partialViewName, model, viewData);
}
在视图中这样使用:
@Html.PartialFor(x => x.Person, "Person")
在这里找到答案:https://stackoverflow.com/a/4807655/78739
基本上我需要设置ViewData.TemplateInfo.HtmlFieldPrefix.
因此,我向PersonModel添加了一个属性,并将其命名为HtmlFieldPrefix。示例:
public class PersonModel
{
public string HtmlFieldPrefix { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
然后在我的部分观点中,我这样做:
@model SomeNameSpace.PersonModel
@{
ViewData.TemplateInfo.HtmlFieldPrefix = Model.HtmlFieldPrefix;
}
@Html.TextBoxFor(m => m.FirstName)
@Html.TextBoxFor(m => m.LastName)
在我的控制器操作中,我可以这样做:
model.HtmlFieldPrefix = "Person";
return View("_Person", model);
现在我的渲染视图将如下所示:
<input type="textbox" id="Person_FirstName" name="Person.FirstName" />
<input type="textbox" id="Person_LastName" name="Person.LastName" />
如果我离开模特。HtmlFieldPrefix为null,视图将呈现为:
<input type="textbox" id="FirstName" name="FirstName" />
<input type="textbox" id="LastName" name="LastName" />
因此,这修复了我的问题,并允许我将部分视图与ViewModels一起使用。