MVC 6 complex model binding

I'm trying to implement a complex view model and bind it to a form. Unfortunately the binding seems to drop/miss the child model prefix so when I try to submit the model back the model binder does not know how to interpret the data. Here's a simplified version of the code...

Parent model

public class MainVM
{
    public bool MainProperty1 { get; set; }

    public ChildVM ChildModel { get; set; }
}

Child model

public class ChildVM
{
    public int ChildProperty1 { get; set; }
    public string ChildProperty2 { get; set; }
    public string ChildProperty3 { get; set; }
}

index.cshtml

@model MainVM

<form id="main-form" asp-controller="main" asp-action="submit" method="post"> 
   <div>
      @await Html.PartialAsync("partial", Model.ChildModel)
   </div>
</form>

partial.cshtml

@model ChildVM

<div>
   <input asp-for="ChildProperty1" />
   <input asp-for="ChildProperty2" />
   <input asp-for="ChildProperty3" />
</div>

Output

<form id="main-form" method="post" action="/main/submit">    
   <div>
      <div>
         <input type="text" data-val="true" name="ChildProperty1" data-val-maxlength-max="17" data-val-minlength-min="4" id="ChildProperty1" />
         <input type="text" data-val="true" name="ChildProperty2" data-val-maxlength-max="50" data-val-minlength-min="3" id="ChildProperty2" />
         <input type="text" data-val="true" name="ChildProperty3" data-val-maxlength-max="50" data-val-minlength-min="3" id="ChildProperty3" />
      </div>
   </div>
</form>

As you can see the binding on the name attribute is missing the prefix of ChildVM (ex. name="ChildVM.ChildProperty1") My question is why would this be dropped or missing? Not sure what I'm missing or if this is a MVC6 thing because as far as I'm aware, this should just work?

Thanks

Answers


That is the expected behavior. If you want to keep the view model structure as it is and still want model binding to work you can try either of the following solutions.

Explicitly specifying the name property value of the inputs

In the main view, you can explicitly specify that your input form is for the child property of the model using the asp-for tag

@model MainVM
<form id="main-form" asp-controller="main" asp-action="submit" method="post">

    <input asp-for="MainProperty1" />
    <div>
        <h5>Child items</h5>
        <input asp-for="ChildModel.ChildProperty1"/>
        <input asp-for="ChildModel.ChildProperty2"/>
        <input asp-for="ChildModel.ChildProperty3"/>

    </div>
    <input type="submit"/>
</form>

This will generate input fields with name property such as name="ChildModel.ChildProperty1" and name="ChildModel.ChildProperty2" etc.. And model binding will work fine when you post the form.

Use an editor template

You can create a new directory called EditorTemplates under ~/Views/YourCurrentControllerName and create a new view called ChildVM.cshtml under that and paste the following code to that

@model ChildVM
<div>
    <input asp-for="ChildProperty1"/>
    <input asp-for="ChildProperty2"/>
    <input asp-for="ChildProperty3"/>
</div>

And in the main view, use Html.EditorFor helper method

@model MainVM
<form id="main-form" asp-controller="main" asp-action="submit" method="post">

    <input asp-for="MainProperty1" />
    @Html.EditorFor(s => s.ChildModel)
    <input type="submit"/>

</form>

This will also generate input fields with name property such as name="ChildModel.ChildProperty1" and name="ChildModel.ChildProperty2" etc.. And model binding will work fine when you post the form.


  • why would this be dropped or missing

Neither it's dropped nor missing. Because child view will not be aware whether it's model is having any parent or not. It'll just know that ChildVM is it's model, and name it's properties without any prefix.


Need Your Help

Bring back mobile version of website in WebBrowser control for wp7?

windows-phone-7 webbrowser-control

Is it possible to bring back web pages in a mobile format, if available, before showing the normal rendering of a web page? I noticed I was getting both when I used it. Or is this enabled by defaul...

Opening new Activity after clickingg item of listview Recycle view

android listview android-listview android-recyclerview

I found this tutorial on recyclerview with cardview but i am not able to add onitemclick listener to it..i want to click on the items and go to another activity. Please help me. Will be highly