Sunday, January 12, 2014

Model Binder in MVC

  Model Binder in MVC:
    http://msdn.microsoft.com/en-us/library/dd410405%28v=vs.100%29.aspx

"A model binder in MVC provides a simple way to map posted form values to a .NET Framework type and pass the type to an action method as a parameter. Binders also give you control over the deserialization of types that are passed to action methods. Model binders are like type converters, because they can convert HTTP requests into objects that are passed to an action method. However, they also have information about the current controller context."


One item I take for granted when I'm using ASP.NET MVC is the powerful feature that is model binding. Model binding is ASP.NET MVC's mechanism for mapping HTTP request data directly into action method parameters and custom .Net objects. Each time your application receives an HTTP request containing the form's data as a pair of key/value pairs, the ControllerActionInvoker invokes the DefaultModelBinder to transform that raw HTTP request into something more meaningful to you, which would be a .Net object. This just works and I love it. Sometimes you need to customize the default model binding to work a little differently. For example, if you were expecting a strongly typed collection of values posted from a multi select control, the default model binding won't work as expected. I'll demonstrate one workaround for this so your action can expect a strongly typed object, and not just an array of strings.
Open visual studio 2010 and create a new ASP.NET MVC 2 empty web application. The model for this will be simple as I want to illustrate the technique of model binding. Here's the model below:
public class Car
{
      public string Make { get; set; }
       public int Id { get; set; }
       public static List<Car> GetCars()
       {
            return new List<Car>
                           {
                               new Car { Id = 1, Make = "Ford"},
                               new Car { Id = 2, Make = "Holden"},
                               new Car { Id = 3, Make = "Chevrolet"}
                           };
       }
}
Now to fast track things. I've got an action that receives HTTP post request and its signature is below:
 [HttpPost]
public ActionResult PostCars(List<Car> cars)
{
      return Content("Ok");
}
The action's parameter is a generic list of Car objects. If you post the data using a multi select HTML control, the default model binding won't work as expected.
image_1
The model binder doesn’t know how to bind the incoming values to a generic list of cars. This is where you can create a custom model binder to do this for you. To create a custom model binder, all that’s required is a class that inherits the IModelBinder interface. From there you implement the BindModel method. Here’s the code below:
public class SelectListModelBinder : IModelBinder
{
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            // Get the raw attempted value from the value provider
            var incomingData = bindingContext.ValueProvider.GetValue("cars").AttemptedValue;
            return incomingData.Split(new char[1] { ',' }).Select(data => Car.GetCars().FirstOrDefault(o => o.Id == int.Parse(data))).ToList();
        }
}
The incoming data can be viewed thanks to the binding context parameter:
var incomingData = bindingContext.ValueProvider.GetValue("cars").AttemptedValue;
The cars values is being passed into the action through the Request.Forms["cars"] value. From there I return a Car object populated with the values from incoming data. Nice and easy.
To use this function I can either register the model binder in the global.asax file, which means it will available to any action that accept a list of cars:
protected void Application_Start()
{
      AreaRegistration.RegisterAllAreas();
       ModelBinders.Binders.Add(typeof (List<Car>), new SelectListModelBinder());
       RegisterRoutes(RouteTable.Routes);
}
If I wanted to target particular actions, I can prefix the model binder to the parameter:
public ActionResult PostCars([ModelBinder(typeof(SelectListModelBinder))] List<Car> cars)
{
      return Content("Ok");
}
Model binding is a powerful feature in ASP.NET MVC and it can help you out in sticky situations.
All the demo related with mvc please click here


Source of this post:http://www.dotnetcurry.com/showarticle.aspx?ID=584

No comments:

Post a Comment