getting the values from a nested complex object that is passed to a partial view

后端 未结 4 917
感动是毒
感动是毒 2020-11-22 12:32

I have a ViewModel that has a complex object as one of its members. The complex object has 4 properties (all strings). I\'m trying to create a re-usable partial view where

相关标签:
4条回答
  • 2020-11-22 12:46

    You can pass the prefix to the partial using

    @Html.Partial("MyPartialView", Model.ComplexModel, 
        new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "ComplexModel" }})
    

    which will perpend the prefix to you controls name attribute so that <input name="Name" ../> will become <input name="ComplexModel.Name" ../> and correctly bind to typeof MyViewModel on post back

    Edit

    To make it a little easier, you can encapsulate this in a html helper

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

    and use it as

    @Html.PartialFor(m => m.ComplexModel, "MyPartialView")
    
    0 讨论(0)
  • 2020-11-22 12:48

    I came across the same situation and with the help of such informative posts changed my partial code to have prefix on generated in input elements generated by partial view

    I have used Html.partial helper giving partialview name and object of ModelType and an instance of ViewDataDictionary object with Html Field Prefix to constructor of Html.partial.

    This results in GET request of "xyz url" of "Main view" and rendering partial view inside it with input elements generated with prefix e.g. earlier Name="Title" now becomes Name="MySubType.Title" in respective HTML element and same for rest of the form input elements.

    The problem occurred when POST request is made to "xyz url", expecting the Form which is filled in gets saved in to my database. But the MVC Modelbinder didn't bind my POSTed model data with form values filled in and also ModelState is also lost. The model in viewdata was also coming to null.

    Finally I tried to update model data in Posted form using TryUppdateModel method which takes model instance and html prefix which was passed earlier to partial view,and can see now model is bound with values and model state is also present.

    Please let me know if this approach is fine or bit diversified!

    0 讨论(0)
  • 2020-11-22 12:57

    If you use tag helpers, the partial tag helper accepts a for attribute, which does what you expect.

    <partial name="MyPartialView" for="ComplexModel" />
    

    Using the for attribute, rather than the typical model attribute, will cause all of the form fields within the partial to be named with the ComplexModel. prefix.

    0 讨论(0)
  • 2020-11-22 12:59

    You can try passing the ViewModel to the partial.

    @model my.path.to.namespace.MyViewModel
    @Html.TextBoxFor(m => m.ComplexModel.Name)
    

    Edit

    You can create a base model and push the complex model in there and pass the based model to the partial.

    public class MyViewModel :BaseModel
    {
        public string SomeProperty { get; set; }
    }
    
     public class MyViewModel2 :BaseModel
    {
        public string SomeProperty2 { get; set; }
    }
    
    public class BaseModel
    {
        public MyComplexModel ComplexModel { get; set; }
    }
    public class MyComplexModel
    {
        public int id { get; set; }
        public string Name { get; set; }
        ...
    }
    

    Then your partial will be like below :

    @model my.path.to.namespace.BaseModel
    @Html.TextBoxFor(m => m.ComplexModel.Name)
    

    If this is not an acceptable solution, you may have to think in terms of overriding the model binder. You can read about that here.

    0 讨论(0)
提交回复
热议问题