Introduction
In this article we try to understand what is ASP.NET MVC Model Binding. We will look at some code samples to understand Model binding and why it is a very useful and essential for ASP.NET MVC application development.
Background
Whenever I talk to experiences ASP.NET Web Forms' developers(who recently started using ASP.NET MVC), I get one question quite often i.e. “How the values from HTML form(view) gets converted to the Model class when it reaches the Action method of the Controller class?”.
The answer to this question is that all this magic is being done by ASP.NET model binder. What Model binder does is that it takes the values coming from an HTML page and map it to a corresponding model. This is a very useful since it relieves the developers from writing all the “type casting” and “HTML-Model mapping” code. The Model binder is capable of retrieving the data from HTML form variables, POSTed variables and files, query string parameters and the values added in the routes.
It might seem a very simple task that we could have done ourselves without the need of Model Binder but in fact this mapping, if done manually, can become very time consuming, cumbersome and error prone. In this article, we will try to implement a simple solution without utilizing the Model binding and then we will try to see how Model binding saves us from writing a lot of mundane code.
Using the code
Let us first look at the example where we will extract all the values form the Request and then populate our model manually. So first we need to create a Model. Let us create a simple Model class for Student
.
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public string FathersName { get; set; }
public string MothersName { get; set; }
}
Now lets create a simple View which will contain a form to populate the Student
details.
Now let us create simple Action methods in the StudentController
to see how we get these values in the controller.
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Now to let us fill some data in the HTML form and debug our Action method.
We can see that the values posted from the form are available in FormCollection
as well as Request.Form
. We can use any of these values to populate our Student
Model. Let us go ahead and write some code to create the Student
Model from the posted. Let us use FormCollection
for this but we could have used Request.Form
too.
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
Student student = new Student();
student.FirstName = collection["FirstName"];
student.LastName = collection["LastName"];
DateTime suppliedDate;
DateTime.TryParse(collection["DOB"], out suppliedDate);
student.DOB = suppliedDate;
student.FathersName = collection["FathersName"];
student.MothersName = collection["MothersName"];
studentsList.Add(student);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Now in the above code snippet, we are extracting all the data from the HTML form's posted values and then mapping the values to the Student
properties and assigning them. We are also doing the type casting where ever the supplied values are not of the same format as of the Model property. Now this doesn't look so bad. So Why do we need Model binder?
Consider following scenarios:
- Our Model contains a lot of properties and we need to manually map all of them.
- Our Model contains a lot of properties and we most of them need to type casting to be able to be assigned to Model properties.
- Our View is strongly typed to a View Model. We need to figure out which value goes to which Model(of ViewModel) and assign them manually.
- Our Model contains other Model object, The contained Model objects can in turn contain other model objects.
- The Model is a self referencing Model i.e. the Model contains an object of its own type.
Now the above mentioned scenarios are not that hypothetical that one might think. These are the scenarios that most deelopers encounter. Now imagine that in all these scenarios, if we need to perform the model binding manually. This is exactly where we can utilize the power and ease of use of ASP.NET MVC Model binding.
ASP.NET MVC Model all the data coming from HTTP world and use the DefaultModelBinder
class which magically does all the type conversion and mapping of all these values to the Model properties. If we use Model binders then we dont have to write the conversion and mapping code which will lead to much cleaner code in our Controller class. Our Controller will then only need to worry about WHAT needs to be done to this received Model rather than HOW to create this Model.
Let us go ahead and use the Model Binder to perform the same operation we did earlier. What we need to do to use the Model Binder? We just need to change the papameter of Create
Method to accept the Student
Model object rather than FormCollection
.
[HttpPost]
public ActionResult Create(Student student)
{
try
{
if (ModelState.IsValid)
{
studentsList.Add(student);
return RedirectToAction("Index");
}
}
catch
{
return View("Create");
}
return View("Create");
}
Now the magic of Model Binding depends on the id of HTML variables that are supplying the values. For our student Model the id of the HTML input fields should be same as the Property names of the Student Model. The mapping will be based on the Property name by default. This is where we will find HTML helper methods very hepful because these helper methods will generate the HTML which will have proper Names
for the Model Binding to work.
So to create the HTML input field for the Student FirstName property:
@Html.EditorFor(model => model.FirstName)
And this will ensure that the generated HTML will have the proper Name
so that the Model binder can understand it while retrieving the values.
And thus we can see how using Model Binding and HTML helpers relieves us from writing a lot of mundane type conversion and model mapping code. If the default Model Binder is not working for us then we can implement our own custom Model Binder too. Also, One more thing to note is that if we need to get the values from some other provide than the default providers for instance we need to get some values from LocalStorage
then we can also implement a custom value provider too.
Point of interest
In this article, we have only discussed about what is ASP.NET Model Binding and saw a basic introduction to the Model Binder. The model binding process can be customized by implementing the custom model binder and value providers. But since this article is meant for the ASP.NET MVC absolute beginner's, these topics were not described in details here. I hope this article has been somewhat informative.
History
- 15 January 2014: First version