In the weeks since my last post, I’ve been doing more client-side work and re-acquainting myself with ASP.NET MVC model binding. The default model binder in ASP.NET MVC works extremely well. In the applications I’ve worked on over the past 2 1/2 years, there have been maybe a couple of instances where the default model binder didn’t work the way I needed. The problems I’ve encountered with model binding lately have had more to do with read-only scenarios where certain data still needs to be posted back. In the Razor template, I’ll have something like the following:
@Html.LabelFor(m => m.Entity.Person, "Person: ") @Html.DisplayFor(m => m.Entity.Person.Name) @Html.HiddenFor(m => m.Entity.Person.Name)
Nothing is wrong with the approach above if Name is a primitive (i.e. string). But if I forgot that Name was a complex type (as I did on one occasion), the end result was that no name was persisted to our datastore (RavenDB) which meant that there was no data to bring back when the entity was retrieved. The correct approach for leveraging the default model binder in such cases is this:
@Html.LabelFor(m => m.Entity.Person, "Person: ") @Html.DisplayFor(m => m.Entity.Person.Name) @Html.HiddenFor(m => m.Entity.Person.Name.FirstName) @Html.HiddenFor(m => m.Entity.Person.Name.LastName) @Html.HiddenFor(m => m.Entity.Person.Name.Id)
Since FirstName, LastName and Id are all primitives, the default model binder handles them appropriately and the data is persisted on postback.