从传递给局部视图的嵌套复杂对象中获取值

Bla*_*mes 24 asp.net-mvc model partial-views

我有一个ViewModel,它有一个复杂的对象作为其成员之一.复杂对象有4个属性(所有字符串).我正在尝试创建一个可重用的局部视图,我可以在其中传递复杂对象并让它为其属性生成带有html帮助器的html.这一切都很有效.但是,当我提交表单时,模型绑定器不会将值映射回ViewModel的成员,因此我不会在服务器端返回任何内容.如何读取用户在复杂对象的html帮助器中键入的值.

视图模型

public class MyViewModel
{
     public string SomeProperty { get; set; }
     public MyComplexModel ComplexModel { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

MyComplexModel

public class MyComplexModel
{
     public int id { get; set; }
     public string Name { get; set; }
     public string Address { get; set; }
     ....
}
Run Code Online (Sandbox Code Playgroud)

调节器

public class MyController : Controller
{
     public ActionResult Index()
     {
          MyViewModel model = new MyViewModel();
          model.ComplexModel = new MyComplexModel();
          model.ComplexModel.id = 15;
          return View(model);
     }

     [HttpPost]
     public ActionResult Index(MyViewModel model)
     {
          // model here never has my nested model populated in the partial view
          return View(model);
     }
}
Run Code Online (Sandbox Code Playgroud)

视图

@using(Html.BeginForm("Index", "MyController", FormMethod.Post))
{
     ....
     @Html.Partial("MyPartialView", Model.ComplexModel)
}
Run Code Online (Sandbox Code Playgroud)

局部视图

@model my.path.to.namespace.MyComplexModel
@Html.TextBoxFor(m => m.Name)
...
Run Code Online (Sandbox Code Playgroud)

如何在表单提交中绑定此数据,以便父模型包含从部分视图在Web表单上输入的数据?

谢谢

编辑:我发现我需要在"ComplexModel"前加上.部分视图(文本框)中的所有控件名称,以便它映射到嵌套对象,但我无法将ViewModel类型传递给局部视图以获取额外的图层,因为它需要是通用的以接受多个ViewModel类型.我可以用javascript重写name属性,但这对我来说似乎过于贫民窟.我怎么能这样做?

编辑2:我可以用新的{Name ="ComplexModel.Name"}静态设置name属性,所以我认为我在做生意,除非有人有更好的方法?

小智 39

您可以将前缀传递给部分使用

@Html.Partial("MyPartialView", Model.ComplexModel, 
    new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "ComplexModel" }})
Run Code Online (Sandbox Code Playgroud)

这将把你的前缀添加到你的控件name属性中,这样就<input name="Name" ../>可以在post back上成为<input name="ComplexModel.Name" ../>并正确绑定到typeofMyViewModel

编辑

为了使它更容易一些,你可以将它封装在一个html帮助器中

public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, 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 = string.IsNullOrEmpty(helper.ViewData.TemplateInfo.HtmlFieldPrefix) ? 
        name : $"{helper.ViewData.TemplateInfo.HtmlFieldPrefix}.{name}"
    }
  };
  return helper.Partial(partialViewName, model, viewData);
}
Run Code Online (Sandbox Code Playgroud)

并用它作为

@Html.PartialFor(m => m.ComplexModel, "MyPartialView")
Run Code Online (Sandbox Code Playgroud)


Tod*_*odd 6

如果您使用标签助手,partial标签助手会接受一个for属性,它可以满足您的期望。

<partial name="MyPartialView" for="ComplexModel" />
Run Code Online (Sandbox Code Playgroud)

使用for属性而不是典型model属性将导致部分中的所有表单字段都使用ComplexModel.前缀命名。