Click here to Skip to main content
15,881,852 members
Articles / Web Development / ASP.NET

ASP.NET MVC Custom Model Binder

Rate me:
Please Sign up or sign in to vote.
4.94/5 (44 votes)
22 Jun 2013CPOL2 min read 246.2K   62   18
MVC custom binding.

Introduction

In the example below I would like to break up the date into three fields: Day, Month, and Year, on my view, but I would like my model to have just one property that can store the combination of these fields.

Background

Recently I was looking at an unusual problem where we had to add custom fields to a view on an ad hoc basis. Not really a problem if it was an MVC app talking directly to a data source. But mine was over several REST based services that were talking to a CRM dynamics backend, spread across multiple domains. Which meant we had to change the data models through out the system. That's when it occurred to  me that we can have one dedicated field  that can store all the ad hoc field data using JASON or xml and we append it to one of the existing fields. Probably not the ideal solution, but that's when I came across custom binding for MVC. I would like to share with you how simple and easy it is to use custom binding to solve similar issues.

Using the Code

View 

In my view I am going to provision three fields for the date within my form.

HTML
<form id="Home" action="" method="POST">
    Day     <input id="Day" name="Day" value="" type="text" />
    Month   <input id="Month" name="Month" value="" type="text" />
    Year    <input id="Year" name="Year" value="" type="text" />    
            <input id="Submit" type="Submit" value="Submit" />
</form>

Model 

In my model I will only have one property for the three fields called a Date:

C#
public class HomePageModels
{
    public string Title { get; set; }
    public string Date { get; set; }
}

Custom Binding  

The custom binding class needs to inherit form IModelBinder. Here we capture the current request and extract the Form fields individually. Then we can manipulate these fields any way we like. In this example as you can see I am adding them to a single property called Date.

C#
public class HomeCustomBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, 
                            ModelBindingContext bindingContext)
    {
        HttpRequestBase request = controllerContext.HttpContext.Request;

        string title = request.Form.Get("Title");
        string day = request.Form.Get("Day");
        string month = request.Form.Get("Month");
        string year = request.Form.Get("Year");

        return new HomePageModels
                   {
                       Title = title,
                       Date = day +"/"+ month +"/"+ year
                   };
    }
} 

Alternatively if we do not want to implement  custom binding for each and every Model and Property in our application we can inherit from the DefaultModelBinder and override the BindModel method  as below

C#
public class HomeCustomDataBinder : DefaultModelBinder
    {

        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(HomePageModels))
            {
                HttpRequestBase request = controllerContext.HttpContext.Request;

                string title = request.Form.Get("Title");
                string day = request.Form.Get("Day");
                string month = request.Form.Get("Month");
                string year = request.Form.Get("Year");

                return new HomePageModels
                {
                    Title = title,
                    Date = day + "/" + month + "/" + year
                };

                //// call the default model binder this new binding context
                //return base.BindModel(controllerContext, newBindingContext);
            }
            else
            {
                return base.BindModel(controllerContext, bindingContext);
            }
        }

    } 

Once we have completed coding our custom class we will need to register the class which I do in the Global.asax under Application_Start().

C#
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    AuthConfig.RegisterAuth();
    ModelBinders.Binders.Add(typeof(HomePageModels), new HomeCustomBinder());
}

Controller

Finally we need to inform the controller as to the binding we want it to use. This we can specify using attributes [ModelBinder(typeof(HomeCustomBinder))] as below:

C#
[HttpPost]
public ActionResult Index([ModelBinder(typeof(HomeCustomBinder))] HomePageModels home)
{
    if (ModelState.IsValid)
    {
        ViewBag.Title = home.Title;
        ViewBag.Date = home.Date;
    }
    return View();
}

Points of Interest 

While you could argue that we can achieve the same by manually capturing the requests inside the controller and manipulating how the property is populated, the idea behind using custom binding is to facilitate reuse and thus avoid manually wiring up views and models. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Infosolvex Solutions Inc
Australia Australia
Ritesh is an IT consultant with over ten years of experience in the IT industry varying from consultation, architecture, design, development to technical management. He has a strong background in solutions and applications architecture with a focus on Microsoft’s .Net platform. His area of expertise spans design and implementation of client/server, database and web-based systems. He has worked with C#, ASP.NET 1.1 and 2.0, ADO.NET, Web Services and SQL technology on several enterprise class projects.




Freedom is not worth having if it does not include the freedom to make mistakes.
Mahatma Gandhi

Comments and Discussions

 
QuestionIt is useful Pin
Xie Xie15-Aug-17 7:03
Xie Xie15-Aug-17 7:03 
QuestionMy vote 5 Pin
vatsa_gaurav12-Jun-17 2:36
vatsa_gaurav12-Jun-17 2:36 
QuestionAmbiguous references Pin
Member 1053581122-Jan-16 0:01
Member 1053581122-Jan-16 0:01 
AnswerRe: Ambiguous references Pin
Member 1053581122-Jan-16 0:25
Member 1053581122-Jan-16 0:25 
QuestionThanks.......... I have one question. Pin
Rohan Kishor Garud23-Nov-15 2:49
professionalRohan Kishor Garud23-Nov-15 2:49 
QuestionThank you Pin
ryancjames127-Jan-15 6:19
ryancjames127-Jan-15 6:19 
GeneralMy vote of 5 Pin
Gyozo Kudor15-Jan-15 21:42
Gyozo Kudor15-Jan-15 21:42 
QuestionNice and easy to follow Pin
Ziaur Rahman24-Dec-14 22:09
professionalZiaur Rahman24-Dec-14 22:09 
QuestionVery nice example..keeps the good work Pin
Jameel VM20-Feb-14 17:55
Jameel VM20-Feb-14 17:55 
QuestionASP.NET MVC Custom Model Binder Pin
rajacsharp527-Nov-13 22:15
rajacsharp527-Nov-13 22:15 
Questionnice one Pin
diouf_zyj15-Oct-13 10:03
diouf_zyj15-Oct-13 10:03 
GeneralMy vote of 4 Pin
Jhonathan Izquierdo24-Jun-13 3:39
Jhonathan Izquierdo24-Jun-13 3:39 
SuggestionPretty Good Pin
DeliberateGeek18-Jun-13 5:51
professionalDeliberateGeek18-Jun-13 5:51 
GeneralRe: Pretty Good Pin
Ritesh Ramesh18-Jun-13 15:09
Ritesh Ramesh18-Jun-13 15:09 
GeneralRe: Pretty Good Pin
DeliberateGeek19-Jun-13 3:24
professionalDeliberateGeek19-Jun-13 3:24 
GeneralMy vote of 5 Pin
SERokon13-Jun-13 19:23
SERokon13-Jun-13 19:23 
good one
QuestionArticle title Pin
Karthik. A12-Jun-13 3:15
Karthik. A12-Jun-13 3:15 
AnswerRe: Article title Pin
Ritesh Ramesh12-Jun-13 12:37
Ritesh Ramesh12-Jun-13 12:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.