Introduction
ASP.NET MVC has many great features. I have been playing around with ASP.NET MVC, and gone through couple of interesting things as part of Model Binding. Here I am putting together all my findings, and explain with a simple example. I am sure this will save a lot of time for people who are out there, looking to understand, how exactly ASP.NET MVC Model binding works.In ASP.NET MVC, Model Binding is, mapping the HTTP request data directly to
Action method parameters and .NET objects (a Model). Using the Code
As this is going big, I am splitting this into parts. In this part, I am covering ASP.NET MVC object model binding, Parameter binding using Query String parameters, and controlling Model binding using Bind Attribute.Below is the code structure:
To make it simple, and to concentrate more on Model binding, I am taking a simple example, which is having Employee Model, and
EmployeeController Control, and two Views EmployeeView1, EmployeeView2. When we run the above code, it displays Employee Add/Edit page (Adding/Editing to database is out of scope for this article),
EmployeeView1 view, like below: 'Using Query Strings' link is to demonstrate model binding using Query String parameters, 'Control Model Binding' link is to demonstrate how we can control model binding. Controlling Model Binding gives control on what Model properties can bind with incoming HTTP request.
I have used VS 2008 SP1, ASP.NET MVC 2 for this sample, recommended to use the same version.
Here is how model binding works, for e.g., consider the below request:
 POST: Route Values, Query String Parameters
Route Values decide the controller and the Action method is 
responsible for handling the request and the Query String Parameters 
basically map to the Action method parameters, this is explained in 
detail below. Here is the Employee Model: public class Employee
{
    [DisplayName("Employee ID")]
    [Required(ErrorMessage = "ID Required")]
    public int EmpId { get; set; }
    [DisplayName("Employee Name")]
    [Required]
    public string EmpName { get; set; }
    [DisplayName("Designation")]
    [Required]
    public string EmpDesignation { get; set; }
    [DisplayName("Department")]
    [Required]
    public string EmpDepartment { get; set; }
    [DisplayName("Salary")]
    [Required]
    public float EmpSalary { get; set; }
}
The above model is decorated with Data Annotations to take care of 
simple validations. As part of this writing, we will not discuss much on
 validations. Binding Style 1: Query String Parameters
Query String Parameters can directly map to the Action method parameters. Consider the below request which corresponds to the action method in the sample.EmployeeController.cs
-------------------------
public ActionResult UpdateQueryString(int EmpId, string EmpName, 
   string EmpDepartment, string EmpDesignation)
{
    return View("EmployeeView1");
}
The above request directly maps each HTTP query string parameters EmpId, EmpName, EmpDepartment, EmpDesignation to Action method parameters respectively and updates the above EmployeeModel to contain these values. To observe this behavior, the attached sample renders the binded values in the EmployeeView1 view page, once you set the source code, run the application from Visual Studio, and click on the link Using Query Strings ; link. We will observe the updated fields on the view page. Have a look at the below snapshot. We can generate the above HTTP request by using the
HtmlHelper method like below. Observe the provided handy sample for more information. <%= Html.ActionLink("Using Query Strings", "UpdateQueryString", 
new { EmpId = 1, EmpName = "Nick", EmpDepartment = "IT",
 EmpDesignation = "Director" })%>
Binding Style 2: Object Binding
We see this type of binding in Action methods most of the times. From HTTP request values will be mapped to Model attributes behind the scenes, to make it work we need to follow certain thumb rules. For e.g., consider the below code:[HttpPost]
public ActionResult Update(Employee employee )
{
    if (!this.ModelState.IsValid)
    ModelState.AddModelError("Employee", "Model is Not Valid");
        return View("EmployeeView1");
}
and the View page contains the following strongly typed way of rendering the fields. For e.g.: <%= Html.TextBoxFor(model => model.EmpId) %>
 
The above code automatically binds the strongly typed 'EmpId' entered in the text box to the EmpId of the model (employee) and sends over this to Action method
 when we submit the form. Consider the below line, instead of strongly 
typed method like above, we can consider using the below method:   <%= Html.TextBox("employee.EmpId")%>
Parameter name and property name combination pulls the values from HTTP input. The above method follows the prefix.PropertyName standard. prefix generally
 if we don't specify, it will be Action parameter name. In the above 
example, employee is the parameter for action method. Values entered in 
the EmpId text box will be mapped to EmpId property of the Model. If we specify the prefix using
Bind attribute for the action method like below: [HttpPost]
public ActionResult UsingPrefix([Bind(Prefix = "emp")]Employee employee)
{
    if (!this.ModelState.IsValid)
    ModelState.AddModelError("Employee", "Employee Not Valid");
        return View("EmployeeView2");
}
then Helper method in the view page should look like below: <%= Html.TextBox("emp.EmpId")%>
Click the submit button to observe the Object Model binding. Controlling Model Binding
Sometimes, it may not be required to show all the fields in the View, but Model contains more properties than what a View shows. It is a potential candidate for injection attacks. To avoid this, we can control the Model binding from View to Model using theBind attribute. public ActionResult BindInclude
    ([Bind(Include = "EmpId,EmpName", Exclude = "EmpSalary")] Employee employee)
        {
            return View("EmployeeView1");
        }
Using the Bind attribute, we can white list Model Properties using Include param name, black list Model Properties using Exclude param name. In the above code, only EmpID, EmpName inputs
 from HTTP request will be mapped to employee model, if this results in 
invalid model state because of the validations set, then corresponding 
validations will fire automatically. I will write in the next part, 
about Collection binding, Collection binding objects, etc., how to do 
manual Model binding. I am sure this reading will save a lot of time for
 readers who are hunting for Model binding. 
No comments:
Post a Comment