How to use the ASP.NET MVC ModelBinder

One of the new features in the latest build of ASP.NET MVC is the ModelBinder, which is provided to allow Action methods to take complex types as their parameters. Previously, action methods were only able to take simple types such as strings and integers as their parameters. The new ModelBinder provides the facility to build complex types from component parts that (for example) may be part the result of submitting a form with several fields. To see an example of this in action, we will first need a fairly simple class to work with. The following class definition will typically be placed in the Models directory. I have left the using statements at the start of the file as an 'exercise for the reader'!

   1: public class MBTest
   2: {
   3:     public string Name { get; set; }
   4:  
   5:     public MBTest()
   6:     {
   7:     }
   8: }

All fairly standard stuff. Now let's create a form on our index page that we can use to have a play with one of these objects:

   1: <% using (Html.Form("Home", "About")) { %>
   2:     <input type="text" name="Name" />
   3:     <button type="submit">Submit</button>
   4: <% } %>

Again, just the relevant form supplied here, and kept as simple as possible for clarity. Nothing in the routing needs to change: that will all happen just fine. Now, the aim is to write an Action Method that looks like the following:

   1: public ActionResult About(MBTest testItem)
   2: {
   3:     ViewData["Title"] = "About Page";
   4:  
   5:     return View();
   6: }

Admittedly, this method doesn't actually do anything with the testItem object that it creates, but it could quite easily if it wanted to. What we want is that the Name property of testItem is populated with the contents of the text input field in our form. Previously, we would have done this by inserting code into the About method above to parse the results coming back. So here's the new bit. We create a helper class that will carry the knowledge of how to perform the translation from the form to the complex type. This class must implement the new interface IModelBinder.

   1: public class MBTestBinder : IModelBinder
   2: {
   3:     #region IModelBinder Members
   4:  
   5:     public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState)
   6:     {
   7:         MBTest instance = new MBTest();
   8:         instance.Name = controllerContext.HttpContext.Request["Name"];
   9:         return instance;
  10:     }
  11:  
  12:     #endregion
  13: }

Obviously this is a very simple example, and I haven't used most of the information passed to the GetValue method, but the intention of this post is primarily to be a starting point, just to get you 'up and running'. So the MBTestBinder class functions as a bridge, in a similar way to an ADO.NET DataAdapter. There's one final step to getting this all hooked up, and that's to tell the code to use MBTestBinder. This is done by applying the new ModelBinderAttribute to things. There are actually two different places you can use this attribute, with the same effect. The first is by decorating the model class:

   1: [ModelBinder(typeof(MBTestBinder))]
   2: public class MBTest

The second is decorating the parameter of your Action Method directly:

   1: public ActionResult About([ModelBinder(typeof(MBTestBinder))]MBTest testItem)

My guess is that they've left the choice in because the decision about exactly where bridge classes such as MBTestBinder actually lives is not a straightforward one. Others will no doubt contribute much more involved examples and discuss whether this solution to the problem is even the correct one, but hopefully this post explains enough to enable people to get started with experimenting with it and getting a feel for it.

7 Comments

  • I am not sure why they went this route when they had a great (IMO better) Castle Binder example in mvccontrib???

    Its much easier to use it?



    Cheers!

    Vladan

  • I've not actually had a try with CastleBinder yet. I'll have to have a look and see how it stacks up.

  • I don't like the approach to litter up my methods with attributes. MVC ModelBinders are great, and a much better approach if used correctly (registering your types with your builder).

    This is much better as MVC now knows how to reconstruct your objects natively.

    http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx

    Good post.

    Thanks,
    -Timothy Khouri

  • @Timothy,

    Reading your post made me realise that I'd missed one of the main methods of registering a ModelBinder - ModelBinders.Binders.Add(). Thinking about it, this is actually the place where it sits most naturally for me as well. Lumping it in with routing makes a lot of sense I think.

  • Thanks, Your post helped me a lot with figuring this ModelBinder thingy out!

  • @Soren,

    Thanks for the feedback! If there are any things that you'd like me to write further about, just shout and I'll try and put together an article and some examples.

  • Anyone have a Castle Binder example?

    I'm dying to try it - but the mvccontrib trunk doesn't have any samples?

Comments have been disabled for this content.