Introduction
In this article we will see (hopefully) the magic (in my opinion) of Model Binding in ASP.NET MVC, a framework mechanism that makes our life easier.
Context
Model Binding is useful when we want to submit a form and retrieve the submitted values on the server. Essentially this mechanism binds html inputs from the view to class properties on the server. The binding is done by the ‘name’ attribute of the html elements. Let`s try to illustrate this with an example and suppose we have a View with the following Form:
<form action="/User/Submit" method="post"> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" name="FirstName"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" name="LastName"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form>
Of course it is easier and more elegant to use html helpers for forms, labels and inputs but this better illustrates the concept. Notice that we have two text inputs, one with the name attribute “FirstName” and the other with the name “LastName”. This means that these two inputs will bind to two properties with the same name as shown below:
public class UserViewModel { public string FirstName { get; set; } public string LastName { get; set; } } public class UserController : Controller { [HttpPost] public ActionResult Submit(UserViewModel model) { var firstName = model.FirstName; var lastName = model.LastName; // return ... } }
You can see that our Submit action has a UserViewModel parameter. This means that when the form gets submitted the Model Binding mechanism will automatically (dare I say magically?) create the model parameter with the respective properties containing submitted values. This is a simple one-to-one binding example but we can do a lot more. Suppose we want to add Address fields (Address, Address 2, Address 3). We could add three different properties in the same manner or we could add a list property. In order to bind to a list all binded inputs must have the same name attribute and same as the property.
<form action="/User/Submit" method="post"> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" name="FirstName"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" name="LastName"> </div> <div class="form-group"> <label for="address1">Address</label> <input type="text" class="form-control" id="address1" name="Address"> </div> <div class="form-group"> <label for="address2">Address 2</label> <input type="text" class="form-control" id="address2" name="Address"> </div> <div class="form-group"> <label for="address3">Address 3</label> <input type="text" class="form-control" id="address3" name="Address"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form>
Notice how all three addresses have the same name “Address”. And in the ViewModel we have an Address property like this:
public class UserViewModel { public string FirstName { get; set; } public string LastName { get; set; } public List string Address { get; set; } }
We can also bind to complex types. For instance we could have an Address type and a property in the ViewModel of type Address like this:
public class Address { public string Street { get; set; } public string ZipCode { get; set; } } public class UserViewModel { public string FirstName { get; set; } public string LastName { get; set; } public Address Address { get; set; } }
In order to bind to complex types the name of the html input must contain the chain of properties separated by a dot. like so:
<form action="/User/Submit" method="post"> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" name="FirstName"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" name="LastName"> </div> <div class="form-group"> <label for="street">Street</label> <input type="text" class="form-control" id="street" name="Address.Street"> </div> <div class="form-group"> <label for="zipCode">Zip Code</label> <input type="text" class="form-control" id="zipCode" name="Address.ZipCode"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form>
As you can see we have the name attributes “Address.Street” and “Address.ZipCode”. It is also possible to bind to a Dictionary type property and various other types or we could even create our custom Model Binder instead of using the default one if we want to by implementing the IModelBinder interface. Using the built-in Request and FormCollection properties to retrieve the values on the server is also an option but I find that Model Binding to a ViewModel class is much cleaner.
Conclusion
Model Binding is quite useful and makes our life easier when we want to pass values from the View to the Server while also maintaining a clean code base without any drawbacks that I can think of (except maybe a slight accommodation issue).
To understand more about Model Binding in ASP.NET MVC, please read the following article:
Photo source: https://images.pexels.com