Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 - Partial View Model binding during Submit

I have view model which has another child model to render the partial view (below).

public class ExamResultsFormViewModel
{
    public PreliminaryInformationViewModel PreliminaryInformation { get; set; }

    public string MemberID { get; set; }

    public string MemberName { get; set; }

    public int PatientID { get; set; }

    public string ConfirmationID { get; set; }

    public bool IsEditable { get; set; }

    #region Select Lists
    public SelectList ProviderOptions { get; set; }
    #endregion
}

public class PreliminaryInformationViewModel
{
    public string ProviderName { get; set; }

    public string ProviderID { get; set; }

    public string ServiceLocation { get; set; }
}

This PreliminaryInformationViewModel view model also used as a child models in another view model since this preliminary information can be updated at different pages.

So I created this preliminary information as a separate partial and to include in other pages.

@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);}

Inside the partial

@model Web.Models.Preliminary.PreliminaryInformationViewModel
<div>
    @Html.TextBoxFor(x => x.DateOfService })
</div>

But the problem is during submit this preliminary model is always null due to the reason HTML name attribute is always is rendered as

but when I pass the parent model to the partial as below.

@model Web.Models.Exam.ExamResultsFormViewModel
<div>
    @Html.TextBoxFor(x => x.PreliminaryInformation.DateOfService })
</div>

Now the HTML element is generated as

<input type = 'text' name='PreliminaryInformation.DateOfService.DateOfService' id='PreliminaryInformation.DateOfService'>

and it binds properly during the submit.

I understand MVC bind the element value based on the name attribute value, but the second implementation would need me to create a multiple partial for each page, which I don't like.

So far I couldn't find a solution to work with the first implementation, is there way I can make preliminary information model value bind during submit with the first implementation.

like image 246
Sathish Avatar asked Dec 19 '13 23:12

Sathish


3 Answers

You can add the HtmlFieldPrefix to the top of your partial view:

@{
    ViewData.TemplateInfo.HtmlFieldPrefix = "Contact";
}

This is the same approach as that described by @cpoDesign but it means you can keep the prefix in your partial view if you need to do that.

like image 164
Chaholl Avatar answered Dec 22 '22 17:12

Chaholl


I know its a bit late but it might help to someone

If you have complex model, you can still pass it into partial using:

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

where I have defined model with property "Contact". Now what HtmlFieldPrefix do is add the property binding for each model "so the model binder can find the parent model"

There is a blog post about it: http://www.cpodesign.com/blog/bind-partial-view-model-binding-during-submit/

.NET Core 2 binding

In .NET Core 2 and MVC the answer above will not work, the property is no longer settable.

How ever the solution is very similar.

 @{ Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Contact"; }
 @await Html.PartialAsync("_YourPartialName", Model.Contact)

after you can submit your model, it will bind again.

Hope that helps

like image 30
cpoDesign Avatar answered Dec 22 '22 16:12

cpoDesign


You need to create an editor template for PreliminaryInformationViewModel to replace the partial view, then call with Html.EditorFor( m => m.PreliminaryInformation ). Reference this solution. Creating the template should be as simple as moving your partial view to the Views/Shared/EditorTemplates directory. Html.EditorFor(...) will automatically use this template based on the type you're passing in as the model (in this case, PreliminaryInformationViewModel)

like image 33
Moho Avatar answered Dec 22 '22 17:12

Moho