X

Subscribe To Our Mailing List

P.S I will never spam you...100% GUARANTEED!

Tuesday, September 9, 2014

Custom Model Binder in MVC

Introduction

Model Binding is one of the fundamental feature of MVC and this is used to convert form values, route data values or any value from a datasource in Model objects. Defaultmodelbinder is internally used to bind the model when you post the data to server, which is derived from “IModelBinder” interface.

Custom Model Binder in MVC
How it Works

Lets create a sample to demonstrate how this works. And Obviously in our project we will get the data from database but during this exercise i will hardcode the data in controller itself because this article mainly focuses on Model Binding.
   1.Lets add a new MVC Project as below -
Custom Model Binder in MVC

2. Create a Controller called – “EmployeeController.cs” and view corresponding to this controller and call it as “Index.cshtml”.
3. Now lets create a class called “Employee.cs” and i will take arsenal club player names for Employee Names because i just love them :-)
 public class Employee
 {
    public int EmpID { get; set; }
    public string EmpFirstName { get; set; }
    public string EmpLastName { get; set; }
    public string EmpCountry { get; set; }

    public static List GetEmployees()
    {
       return new List
       {
           new Employee { EmpID = 1, EmpFirstName = "Alexis", EmpLastName = "Sanchez", EmpCountry= "Chile"},
           new Employee { EmpID = 2, EmpFirstName = "Jack", EmpLastName = "Wilshere", EmpCountry= "England"},
           new Employee { EmpID = 3, EmpFirstName = "Aaron", EmpLastName = "Ramsey", EmpCountry= "Wales"},
           new Employee { EmpID = 4, EmpFirstName = "Theo", EmpLastName = "Walcott", EmpCountry= "England"}
                           
        };
        
     }
 }
4. Now its time to create a viewmodel for our view. Lets call it as “EmpViewModel.cs
public class EmpViewModel
{
   public List Employees { get; set; }
}
5. So in my EmployeeController i will add 2 action methods one for “GET” and another for “POST”. 
public class EmployeeController : Controller
 {
    public ActionResult Index()
    {
        EmpViewModel vwModel = new EmpViewModel()
        {
            Employees = Employee.GetEmployees()
        };

        return View(vwModel);
     }

     [HttpPost]
     public ActionResult Index(EmpViewModel vwModel) 
     {
        return Content("Works !!");
     }

  }
6. In my Index.cshtml i will add the fields which are to be displayed or to be edited.
@model PartialViewsBinding.Models.EmpViewModel
           
@{
    ViewBag.Title = "Home Page";
}

@using (Html.BeginForm())
{
    for (int i = 0; i < Model.Employees.Count; i++)
    {
        @Html.HiddenFor(m => m.Employees[i].EmpID)

        @Html.TextBoxFor(m => m.Employees[i].EmpFirstName)
        @Html.TextBoxFor(m => m.Employees[i].EmpLastName)
        @Html.TextBoxFor(m => m.Employees[i].EmpCountry)

    }
    
   <input type="submit" value="Click Here" /> 

}
You can check the below screenshot of Index.cshtml during runtime -


Custom Model Binder in MVC

Now i will change the names and i will check in the action method whether i will be getting the same and  my model binding properly or not.


Custom Model Binder in MVC

In above figure i made sure the data binding properly to my action method. 

So now coming to the main topic "Custom Model Binder", for demonstrating this lets create a new property in Employee class and lets call it as  "EmpName". Intention behind adding this property would be just to bind this property from "FirstName" and "LastName"  of employee. (Please note : This is just for demonstration. This would not be the scenario in your live projects.)
Now i am going to add the custom binder for this -   
 public class FullNameModelBinder : DefaultModelBinder
  {
        public override object BindModel(ControllerContext controllerContext,
                             ModelBindingContext bindingContext)
        {
            int i = 0;
            List emps = new List();
            HttpRequestBase request = controllerContext.HttpContext.Request;

            while (!string.IsNullOrEmpty(request.Form["Employees[" + i + "].EmpID"]))
            {
                var emp = new Employee();
                emp.EmpID = int.Parse(request.Form["Employees[" + i + "].EmpID"]);
                emp.EmpName = request.Form["Employees[" + i + "].EmpFirstName"] + " " + request.Form["Employees[" + i + "].EmpLastName"];
                emp.EmpCountry = request.Form["Employees[" + i + "].EmpCountry"];

                emps.Add(emp);
                i++;
            }

            return new EmpViewModel()
            {
               Employees = emps
            };
        }
   }

Now add the entry in Global.asax file to intimate the compiler about custom binder.
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(EmpViewModel), new FullNameModelBinder());
  }

Now add the binder in the Post method to get the name based on firstname and lastname.

// ([ModelBinder(typeof(FullNameModelBinder))]EmpViewModel vwModel)

     [HttpPost]
    public ActionResult Index([ModelBinder(typeof(FullNameModelBinder))]EmpViewModel vwModel)
    {
        return RedirectToAction("Index");
    }

Done !!! now the property EmpName has been bound from FirstName and LastName.