Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is an MVP ASP.NET and is currently employed as .NET Software Engineer at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP.
More about me More about me
Send mail E-mail me


Microsoft Most Valuable Professional - MVP - ASP.NET

Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn RealDolmen - Rock-solid passion for ICT
I'm a speaker at TechDays Belgium and TechDays Finland

Search

Latest Twitter

    Follow me on Twitter...

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Using the ASP.NET MVC ModelBinder attribute

    ASP.NET MVC action methods can be developed using regular method parameters. In earlier versions of the ASP.NET MVC framework, these parameters were all simple types like integers, strings, booleans, … When required, a method parameter can be a complex type like a Contact with Name, Email and Message properties. It is, however, required to add a ModelBinder attribute in this case.

    Here’s how a controller action method could look like:

    public ActionResult Contact([ModelBinder(typeof(ContactBinder))]Contact contact)
    {
        // Add data to view
        ViewData["name"] = contact.Name;
        ViewData["email"] = contact.Email;
        ViewData["message"] = contact.Message;
        ViewData["title"] = "Succes!";

        // Done!
        return View();
    }

    Notice the ModelBinder attribute on the action method’s contact parameter. It also references the ContactBinder type, which is an implementation of IModelBinder that also has to be created in order to allow complex parameters:

    public class ContactBinder : IModelBinder
    {
        #region IModelBinder Members

        public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState)
        {
            if (modelType == typeof(Contact))
            {
                return new Contact
                {
                    Name = controllerContext.HttpContext.Request.Form["name"] ?? "",
                    Email = controllerContext.HttpContext.Request.Form["email"] ?? "",
                    Message = controllerContext.HttpContext.Request.Form["message"] ?? ""
                };
            }

            return null;
        }

        #endregion
    }

    UPDATE: Also check Timothy's blog post on this one.
    UPDATE: And my follow-up blog post.

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | ICT | Internet | MVC

    Comments

    Cameron Singe Australia |

    Monday, September 01, 2008 1:25 PM

    Cameron Singe

    Excellent, thanks for that.

    I was wondering if I could pass a Guid in as an ID, if it doesn't work out of the box, at least I know I can resort to this.  For more complex types I prob rather keep the logic in the actual method not in the binding part, however thats more personal preference.

    maartenba Belgium |

    Monday, September 01, 2008 1:43 PM

    maartenba

    Guids are supported out of the box, so that should work nicely.

    alvinashcraft.com |

    Monday, September 01, 2008 4:24 PM

    pingback

    Pingback from alvinashcraft.com

    Dew Drop - September 1, 2008 | Alvin Ashcraft's Morning Dew

    Nathan Stott United States |

    Monday, September 01, 2008 11:04 PM

    Nathan Stott

    Nice.  I didn't know about model binders.  I wrote about something similar here though: nathan.whiteboard-it.com/.../...th-validation.aspx

    Simone Italy |

    Tuesday, September 02, 2008 10:37 AM

    Simone

    I don't like Timothy's approach:
    I think that using the ModelBinder to get the id of the object, retrieve the object from the DB and then return it as action parameter is not what the ModelBinder was developed for.

    Maybe it's just a personal feeling, but I think it's a bad idea because one of the key concept of having such an MVC framework is to have separation of concerns, and IMHO the ModelBinding should only be focused on binding the form values to action parameters.

    Maybe in a simple view that shows only the details of a product this might seem a good fit, but what if the view must show more complex data? Like the list of all the products that have an color option in Red? Would you get red from the form value return, do the search in the ModelBinder and send the list of products as action parameter?  And what if your action should operate on a more than one model object? or if the data retrieval is conditional to some other logic? Will you put that logic in the ModelBinder?
    Will you have two approach to the same data retrieval problem based on the complexity of the action?

    Furthermore, in this approach I also see a threat to testability: how do you inject the mock repository inside the ModelBinder? It's instantiated directly by the framework, you have no control on how it is instantiated. Maybe during testing you can test it as unit, but how in the production code? How to you inject the dependency on the real repository since you are not the one that is instantiating it?

    I know you didn't write that blog post, but Timothy's blog requires a user registration to write a comment, and I'm not willing to do so.

    emadibrahim.com |

    Wednesday, September 03, 2008 7:53 PM

    pingback

    Pingback from emadibrahim.com

    Use ModelBinder to Generically Bind Complex Types | Emad Ibrahim

    Comments are closed