زمانی که درخواستی به سمت یک Action پارامتر دار ارسال میشود، قسمت ActionInvoker قبل از فراخوانی اکشن مربوطه، به دنبال Model Binder مناسبی برای دادههای پارامترها میگردد و در صورت یافت نشدن، از ModelBinder پیش فرض ASP.NET MVC استفاده میکند.
اما وظیفهی ModelBinder چیست ؟
ModelBinder دادههای ارسال شده از مرورگر را که توسط درخواستهای HTTP (کوئری استرینگها و یا دادههای همراه با فرمها ) ارسال شده است، تبدیل به دادههای قابل فهم برای پارامترها میکند.
به عبارتی ModelBinder وظیفه تبدیل دادههای ارسال شده از سمت مرورگر به اشیاء NET. را دارد.
فرض کنید ما مدلی به شکل زیر داریم :
public class CustomerInfo { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } }
فیلد آخر برای ذخیرهی تاریخ تولد مشتری استفاده میشود. که View مربوط به آن به شکل زیر خواهد بود :
همانطور که میبینید تایپ کردن تاریخ به این صورت (1/1/2009 12:00:00 AM) ، هم زیاد جالب نیست و هم کمی مشکل است. به همین دلیل برخی سایتها از سه قسمت جدا برای گرفتن روز ، ماه و سال استفاده میکنند و در نهایت آنها را با یکدیگر ترکیب میکنند.
در این مثال ما نیز میخواهیم تاریخ را به صورت زیر دریافت و پس از تبدیل آن به تاریخ میلادی، آن را به کاربر نمایش دهیم :
اما هنگام ارسال فرم به صورت بالا ، ModelBinder توانایی تبدیل این سه ورودی (روز ، ماه و سال) به فیلد BirthDate موجود در کلاس CustomerInfo را ندارد. به همین خاطر ما باید یک ModelBinder متناسب با نیاز خود را طراحی کنیم.
برای ایجاد یک ModelBinder سفارشی نیاز است که از کلاس IModelBinder ارثبری و متد BindModel آن را پیاده سازی کنیم.
ساختار این اینترفیس به شکل زیر است :
public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); }
متد BindModel حاوی 2 پارامتر است :
ControllerContext : حاوی اطلاعاتی در مورد درخواست http جاری
ModelBindingContext : این کلاس حاوی یک property به نام Model است که حاوی ارجاعی به مدلی که همکنون قصد پردازشش آن را دارد.
با توجه به موارد بالا کلاس ما به شکل زیر خواهد بود :
using System; using System.Web; using System.Web.Mvc; using ModelBinderExample.Models; using Persia; namespace ModelBinderExample.CustomModelBinder { // Article written for www.dotnettips.info public class CustomerInfoModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { HttpRequestBase request = controllerContext.HttpContext.Request; string firstName = request.Form.Get("FirstName"); string lastName = request.Form.Get("LastName"); DateTime birthDate = this.GetMiladiDate(request); return new CustomerInfo() { FirstName = firstName, LastName = lastName, BirthDate = birthDate }; } private DateTime GetMiladiDate(HttpRequestBase request) { int day = int.Parse(request.Form.Get("Day")); int month = int.Parse(request.Form.Get("Month")); int years = int.Parse(request.Form.Get("Years")); //Convert shamsi to miladi return Persia.Calendar.ConvertToGregorian(years, month, day, DateType.Gerigorian); } } }
در کد بالا ایتدا موارد ارسال شده را دریافت میکنیم و توسط متد ()GetMiladiDate تاریخ دریافتی از کاربر که به صورت روز، ماه و سال میباشد را تبدیل به میلادی میکنیم و سپس در قالب یک شی customerInfo آنها را برگشت میدهیم.
نکته : جهت تبدیل تاریخ شمسی به میلادی از کتابخانهی Persia کمک گرفته شده است که در فایل پیوستی قرار داده شده.
کار ایجاد یک ModelBinder سفارشی تمام شده و حال نیاز است کلاس را در فایل Global.asax در قسمت ()Application_start ثبت کنیم به شکل زیر :
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); //Register New ModelBinder ModelBinders.Binders.Add(typeof(CustomerInfo), new CustomerInfoModelBinder()); }
و برای استفاده از این ModelBinder ، ما باید به کنترلر اطلاع دهیم که میخواهیم از چه نوع Binding استفاده کنیم به همین دلیل از attribute زیر برای انجام این کار استفاده میکنیم:
[HttpPost] public ActionResult Create([ModelBinder(typeof (CustomerInfoModelBinder))] CustomerInfo customerInfo) { if (ModelState.IsValid) { ViewBag.FirstName = customerInfo.FirstName; ViewBag.LastName = customerInfo.LastName; ViewBag.BirthDate = customerInfo.BirthDate; } return View(); }
پروژه پیوستی : ModelBinder-Example.zip