Saturday, 16 April 2016

MVC Custom Model Binding using IModelBinder and DefaultModelBinder in ASP.NET MVC

Model binding is one of the magic things in MVC framework. Model binding is ASP.NET MVC's mechanism for mapping HTTP request data directly into action method parameters and custom. We know that if the model property matches exactly with view, then MVC architecture automatically takes care of the model binding process. This is very simple and straight forward.

But, if the model property is not matched exactly with the view? Then how do we bind model in time of data submission?
Then we will apply MVC Custom Model Binding using IModelBinder and DefaultModelBinder

Create database testdb
use testdb

-- create table Student….

create  table Student
(
RollNo int primary key,
Name varchar(50),
Gender varchar(50) constraint Gender_Constraint check(Gender in ('Male','Female')),
DOB DateTime
)


Prior to custom binder concept, MVC architecture used to automatically bind the data fields, when view and model design matches.
But in this scenario we can see that the values posted from the form are available in FormCollection as well as Request.Form to model, view has seven controls like(rollno,firstname,lastname,gender,day,month,year) and  model  has four  data fields like(RollNo,Name,Gender,Dob). So we have to use custom model binder to manually bind the data fields.


First we will take MvcApplication and  take  class which name is  StudentBinder.cs  in Model Folder

namespace WebApplication2.Models
{
public class StudentBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
int _rollno = Convert.ToInt32(request.Form.Get("RollNo"));
string _fname = request.Form.Get("FirstName");
string _lname = request.Form.Get("LastName");
string _gender = request.Form.Get("Gender");
int _day = Convert.ToInt32(request.Form.Get("Days"));
int _month =Convert.ToInt32( request.Form.Get("Months"));
int _year = Convert.ToInt32(request.Form.Get("Years"));
return new Student { RollNo = _rollno, Name = _fname+" "+_lname, Gender = _gender, DOB = new DateTime(_year,_month,_day) };

}
}
}


Then we can add Controller which name is  MyCollegeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
// using this namesapce
using System.Web.Mvc;
using WebApplication2.Models;


namespace WebApplication2.Controllers
{
public class MyCollegeController : Controller
{
// GET: MyCollege
// database ....
testdbEntities database = new testdbEntities();

List<SelectListItem> days = new List<SelectListItem>();
List<SelectListItem> years = new List<SelectListItem>();
List<SelectListItem> months = new List<SelectListItem>();
string[] mon = new string[12] { "Jan", "Feb", "March", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec" };



// this  method for how to bind day,month year  on View……

public void DayMonthYear()
{

// this code for month ………………

for (int i = 0; i < mon.Length; i++)
{
months.Add(new SelectListItem()
{
Value = (i + 1).ToString(),
Text = mon[i]
});
}
ViewBag.Months = months;

// this code for days ………………

for (int i = 0; i <= 31; i++)
{
days.Add(new SelectListItem()
{
Value = i.ToString(),
Text = i.ToString()
});
}
ViewBag.Days = days;

// this code for years ………………

for (int i = 1975; i <= DateTime.Now.Year; i++)
{
years.Add(new SelectListItem()
{
Value = i.ToString(),
Text = i.ToString()
});
}
ViewBag.Years = years;
}



[HttpGet]
public ActionResult Index()
{

DayMonthYear();

return View();
}


[HttpPost]

public ActionResult Index([ModelBinder(typeof(StudentBinder))] Student entity  )
{
try {
Student ss = new Student
{
RollNo = entity.RollNo,
Name = entity.Name,
Gender = entity.Gender,
DOB = entity.DOB

};
database.Students.Add(ss);
database.SaveChanges();
TempData["msg"] = "saved successfully";
DayMonthYear();

}
catch (Exception ex)
{
TempData["msg"] = ex.Message;
}
return View();
}
}
}

This code for Index.cshtml…………………………………..


@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
@using (Html.BeginForm())
{
<table width="50%" border="1">

<tr><td>RollNo</td><td>@Html.TextBox("RollNo")</td></tr>
<tr><td>First Name</td><td>@Html.TextBox("FirstName")</td></tr>
<tr><td>Last Name</td><td>@Html.TextBox("LastName")</td></tr>
<tr>
<td>Gender</td>
<td>
Male:@Html.RadioButton("Gender", "Male")
Female: @Html.RadioButton("Gender", "Female")
</td>
</tr>
<tr>
<td>Date Of Birth</td>
<td>
@Html.DropDownList("Days", "Day")
@Html.DropDownList("Months", "month")
@Html.DropDownList("Years", "year")
</td>
</tr>
<tr><td colspan="2"><input type="submit" value="Save" />@TempData["msg"]</td></tr>
</table>
}
</div>
</body>
</html>


If you want to use Custom Model Binding  in your  MvcApplication then you have to make some  changes in Global.asax   in  your  Application and  the  code  we  have  changed  is being  highlighted  below  by  yellow color

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using WebApplication2.Models;

namespace WebApplication2
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            ModelBinders.Binders.Add(typeof(Student), new StudentBinder());
        }
    }
}




Result


0 comments:

Post a Comment