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