Model Binding in MVC : A Magical Mapper

This article describes various ways of model binding possible in MVC that has a magical power. This article is intended for the audience having at least a basic knowledge of request flow in MVC.

ASP.NET MVC model binding allows you to map and bind HTTP request data with a model. This is done automatically by MVC Model Binder. The mapping of the request with the model is done by comparison with the name attribute of controls.

MVC Model Binder

When we call any Action Method, two important components play a vital role behind the scene and does some magic.
  1. ValueProviderDictionary
  2. DefaultModelBinder

Suppose I am considering as an example the saving of a magazine article. The following is my Action Method that returns a View.

returning View

Once I request for action method: http://localhost:64640/Articles/SaveArticle

The ValueProviderDictionary pulls out the values from the HTTP request and stores them as strings. The fetching is done in the following order:

  • It checks for Request.Form["ArticleTitle"] where it finds for the control that is having name as ArticleTitle
  • If not available it checks in RouteData.Values["ArticleTitle"] that can be specified in URL itself.
  • If this too is not available then it checks for Request.QueryString["ArticleTitle"]
  • If it still finds nothing then it returns null

    returns null

Once this data is fetched from the HTTP request, the DefaultModelBinder class takes the responsibility of converting this string object to actual .Net object. This class implements an IModelBinder interface.

Let's consider each way to do model binding.

  1.  Binding using RouteData

    RouteData

    code
    As you can see, I had passed some value in the URL as a RouteData. This value is converted and made available to the parameter "ArticleTitle' in ActionMethod by ModelBinder.

    Note: I modified the routing table for a better understanding as shown below:

    routing table
     
  2. Binding using querystring data

    Binding using querystring

    The figure above shows how the querystring is converted to the required type and made available to the ActionMethod
     
  3. Binding form controls with string parameters

    string parameters

    code1

    The figure above shows how the HTML control's name attribute is matched with the ActionMethod parameter and the values are made available in the parameter.
     
  4. Binding form control with Complex type object

    Complex type object

    The figure above shows how HTML control names are matched with Class type and class properties are being set. If all HTML controls have the same name then all properties are set else the properties are set with default values.
     
  5. Binding with list of strings

    Binding with list

    In the figure above I considered 2 TextBoxes for each Article Title having the same name.

    name
    The figure above shows how the model binder makes the values of each TextBox available to a string array in the Action Method.
     
  6. Binding with list of complex objects

    complex objects

    In the figure above, I considered 2 TextBoxes for each Article Title and the name of the text boxes start with an Index. For example:

    [0].ArticleTitle & index [1].ArticleTitle

    Index
    The model binder automatically makes it available for the properties of the respective Article class in a list of Articles. 

  7. Binding with Custom Model Binder

    So far I showed you how a Default Model Binder maps the request with the model. Similarly we can create our own custom Model Binder and map the request with a model in the Action Method.

    For eg:

    Binding with Custom Binder

    In the figure above I am capturing ArticleName and Author in a TextBox, but I wish to have the values in the model with upper case before processing. So I have created my own custom binder that will convert my values to upper before the Action Method is able to access it.

Use the following procedure to create a Custom Binder.

  1. I need to create a class that implements the IModelBinder interface.
    1. public class CustomBinder : IModelBinder  
    2. {  
    3.     public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)  
    4.     {  
    5.         Article art = new Article();  
    6.         art.ArticleId = 1;  
    7.         art.ArticleTitle = controllerContext.HttpContext.Request.Form["ArticleTitle"].ToUpper();  
    8.         art.Author = controllerContext.HttpContext.Request.Form["Author"].ToUpper();  
    9.         return art;  
    10.     }  
  2. Register the custom binder in the global.asax file ModelBinders.
    1. Binders[typeof(Article)] = new CustomBinder();  
  3. Decorate the Action Result parameter with the Custom ModelBinder.
    1. public ActionResult SaveArticleToUpper([ModelBinder(typeof(CustomBinder))]Article art)  
    2. {   
    3.    return View("Index"); 

    That's it. Now I will be able to get the model properties in upper case.

Conclusion

This is how strongly the Model Binder is and helps to bind the request with the model. The builtin model binding capabilities automatically takes care of primitive types, class types and collections. I hope you liked this article. Please share your comments, it is valuable to me and keep sharing no matter what ;)

Reference


Similar Articles