Model Binding in Asp.net MVC Razor with example


  1. Model binding is an interesting feature in Asp.net MVC.
  2. It allows you to map and bind the HTTP request data with a model.
  3. The Model Binding reduces the effort to get posted values from the request.
  4. In this article we will see why we need Model binding and how we can achieve it.


Demo

Why Model Binding ?
The first question came to your mind would be why to use Model binding ? How it will better or facilitate coding. We will understand this with an example.

We have an Employee Registeration form, the employee fill in details and clicks on submit button.
In order to save values enter by employee we post form to server on submit click, then by using Request object or by using FormCollection object we fetch values out of it as shown below:



As we can see in above screenshot we have to write so much of code to fetch 5 values from posted form. Suppose your form has 20 fields, then you have to write possibly 20 lines to get all values, which also involves type casting.
                                                     The Model binding makes it easier to get the form values. Lets see how. We must be using a Model in our View.

The left part in the screenshot is out ViewModel and we have referred this ViewModel on our View as shown on right. When the form is posted on submit click, we can accept object of this ViewModel as parameter.


So, as we have seen by just accepting a parameter of class which is reffered on View as ViewModel, all the properties are filled. This is magic of Model binding. It reduces the lines of code and associated TypeCasting and makes it very easy to get posted values.

How Model Binding works ?
The next question on your mind would be How this magic thing works? Lets discuss this.
When we have an action with parameter, the MVC runtime uses a model binder to build the parameter. The MVC runtime uses workhorse as DefaultModelBinder. The Asp.net MVC allows us to have multiple model binders registered in the MVC runtime for different types of model.
                                             In case of EmployeeViewModel object, the default model binder inspects the EmployeeViewModel and finds all the Employee properties available for binding. The default model binder can automatically convert and move values from the request into an EmployeeViewModel object. In simple words, when the model binder sees an EmployeeViewModel has a Name property, it looks for a parameter named "Name " in the request. The model binder uses components known as value providers to search for values in different areas of request. The model binder can look at route data, the query string, the form collection.

Whats more in Model Binding ?
Till now we saw example for complex type i.e. EmployeeViewModel which is a class. Similarly model binding also works with primitive types, collections and complex types. We will see example for each of them.

Lets start it !!

Primitive types:
Primitive types are the basic data types like int, short, long etc. We will also include example for string in this type. Lets have a complete new example. We have a simple form with two controls one accepting Name and other Age.

View:

@{
    ViewBag.Title = "Index3";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index3</h2>


@using (Html.BeginForm())
{
    <text>Name:</text>@Html.TextBox("Name")<br /><br />
    <text>Age: </text>@Html.TextBox("Age")<br /><br />

    <input type="submit" value="Submit" />
}
    

The above View will render two textboxs with Name and Age as their name attribute inside a form. When submit is clicked the form is posted to controller method.

Controller:

[HttpPost]
        public ActionResult Index3(string Name,int Age)
        {
            return View();
        }
    
At the action method we have accepted two parameters having name same as defined inside form on View. When the form is posted the model binder inspects the action method parameters, search them in the request and binds it with value in the request. If the parameter name at the action method and control's name property on view differs then model binding will not work to get the value.

The above screenshot from the Network section of Developer tool. Check the Form Data section, it shows two form values posted Name and Age.



Below screenshot shows how the parameters are send when form is posted. 


This sums up the model binding for primitive type. Lets start with collections.

Collections:

In order to demonstrate this example, we will render List of employees on View. The user can udpate values for all of them and on posting form we will bind the list of employees.

View:


@model List<ModelBindingDemo.ViewModel.EmployeeViewModel>
@{
    ViewBag.Title = "Index1";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index1</h2>


@using (Html.BeginForm())
{
    if (Model != null)
    {
        for (int i = 0; i < Model.Count; i++)
        {
        
    <div>
    <table>
    <tr>
    <td>@Html.LabelFor(m => m[i].Name)</td>
    <td>
    @Html.EditorFor(m => m[i].Name)</td>
    </tr>
    <tr>
    <td>@Html.LabelFor(m => m[i].Designation)</td>
    <td>@Html.EditorFor(m => m[i].Designation)</td>
    </tr>
    <tr>
    <td>@Html.LabelFor(m => m[i].City)</td>
    <td>@Html.EditorFor(m => m[i].City)</td>
    </tr>
    </table>
    </div>    
        }
    }   
    <input type="submit" value="Submit" />
    }
    
As we are rendering list of employees, we need to refer model of type List in the View. We have referred Model of type List of EmployeeViewModel as you can see in above code.

Controller:

public ActionResult Index1()
        {
            List<EmployeeViewModel> list = new List<EmployeeViewModel>();
            list.Add(new EmployeeViewModel { City = "City1", Designation = "Sw 1", Name = "Name 1" });
            list.Add(new EmployeeViewModel { City = "City2", Designation = "Sw 2", Name = "Name 2" });
            list.Add(new EmployeeViewModel { City = "City3", Designation = "Sw 3", Name = "Name 3" });
            return View(list);
        }

        [HttpPost]
        public ActionResult Index1(List<EmployeeViewModel> listEmp)
        {
            return View();
        }
    
The first action method prepares a List of employees and send list to View. The second action method is one to which form will be posted. In this action method we are accepting object of  List of type EmpoyeeViewModel. When the form is posted by us after making changes everything will be captured in the list object at client side.

In case of collection the form is posted in above manner with respect to the controls rendered on View. The Model binder detects properties with [0] belongs to same object and [1] belongs to other. So, using the count the model binder is able to bind the collection types.

Instead of using default Model binder, we can create and register multiple model binders for multiple models as per the requirement. We will discuss about Custom Model binding in other article.

Interesting Facts about Model Binding

  1. ASP.NET MVC Model binding allows you to map HTTP request data to a model.
  2. The MVC runtime uses DefaultModelBinder named workhorse to build the parameters.
  3. Model binding implicitly goes to work when an action method has parameter.
  4. Model binding can be explicitly invoked using UpdateModel and TryUpdateModel method.
  5. The by-product of Model binding is ModelState.


So, we came to the end of this article for Model binding. We hope this article proved useful for you. Please share your feedback in comments section.

0 comments:

Post a Comment