نحوه سفارشی سازی Model Binding در MVC

شنبه 16 مرداد 1395

دراین مقاله ما با نحوه ی عملکرد Model Binding آشنا خواهید شد و همچنین در این مقاله یاد خواهید گرفت که چگونه Model Binding را سفارشی سازی کنید.

نحوه سفارشی سازی Model Binding در MVC

Model Binding یکی از بهترین ویژگی ها در فریم ورک ASP.NET MVC می باشد. ModelBinder درخواست های http را از view data به model مسیریابی می کند. MVC در حال اجرا از ModelBinder پیش فرض ،برای ساخت پارامترهای model استفاده می کند.این کار به صورت خودکار توسط Model Binder مربوط بهMVC ، انجام می شود.

به ما اجازه دهید تا با یک مثال ساده ، ببینیم که چگونه اطلاعات  model  به  Controller  توسط  model binding  از  view در mvc ، پاس داده شده است.

ابتدا action  ساده ی زیر را ببینید.

1.	public ActionResult Index()  
2.	     {  
3.	         return View();  
4.	     }  

ما یک model  به نام StudentViewModel به شکل زیر داریم.

 public class StudentViewModel
    {
        [DisplayName("شماره دانشجویی")]
        public int StudenId { get; set; }
        [DisplayName("نام")]
        public string Name { get; set; }
        [DisplayName("آدرس")]
        public string Address { get; set; }
        [DisplayName("شهر ")]
        public string City { get; set; }
        [DisplayName("ایالت")]
        public string State { get; set; }
        [DisplayName("کشور")]
        public string Country { get; set; }
        [DisplayName("گروه")]
        public string Department { get; set; }
        [DisplayName("نمره")]
        public int Marks { get; set; }
    }

در View های index برای ما  view مربوط به  Index را برمی گرداند، و ما Index.cshtmlرا مانند زیر داریم.

@model ModelBinding1.Models.StudentViewModel
<div dir="rtl">
    @{
        ViewBag.Title = "Index ";
    }

    <h2>صفحه ی اصلی</h2>


    @using (Html.BeginForm())
    {

        @Html.EditorForModel("StudentViewModel")
        <input type="submit" value="ذخیره" />
    }

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }

  
</div> 

ما یک دکمه ی submit داریم ، و زمانی که ما بر روی دکمه ی submit کلیک کنیم، action ی به نام Index را فراخوانی می‎کنیم .زمانی که ما Viewی Index را اجرا می کنیم ، صفحه ی زیر را خواهیم دید.

ما می توانیم داده ها را از راه های مختلفی پاس دهیم ، تعدادی از این راه ها در زیر آمده است.

راه 1: از طریق Collection

1.	[HttpPost]  
2.	 public ActionResult Index(FormCollection frm)  
3.	 {  
4.	     Var StudentId= studentformcollection["StudentId"].ToString();  
5.	     var studentName = studentformcollection["Name"].ToString();  
6.	     var studentAddress = studentformcollection["Address"].ToString();  
7.	  
8.	     var studentCity = studentformcollection["City"].ToString();  
9.	     var studentState = studentformcollection["State"].ToString();  
10.	  
11.	     var studentCountry = studentformcollection["Country"].ToString();  
12.	     var studentDepartment = studentformcollection["Department"].ToString();  
13.	  
14.	     var studentMarks = studentformcollection["Marks"].ToString();     
15.	       return View();  
16.	 }  


ما  همچنین می توانیم model  را به جای استفاده از FormCollection  ،  به صورت مستقیم پاس دهیم.

راه 2: از طریق QueryString

راه دیگری که برای گرفتن داده وجود دارد ، استفاده از   Request.querystring می باشد که  مانند زیر از نسخه های قبلی asp.net می باشد.

var studentName = Request.QueryString["Name"].ToString();

راه3 : دادن پارامتر به صورت مستقیم

همچنین ما می توانیم به وسیله  گرفتن پارامتر به صورت مستقیم، پاس بدهیم.

    [HttpPost]  
            public ActionResult Index(int StudentId, string Name, string Address, string City,      string State,string Country, string Department, int Marks)  
            {  
                return View();  

در فریم ورک MVC ، به صورت معمول ، model شامل همه ی فیلدهایی است که با viewها مطابقت داشته باشند.گاهی اوقات در برنامه،  property مربوط به کلاس ViewModel یا Propperty کلاس Entity  یا فیلد دیتابیس ، به درستی در هر صفحهی UI ، نگاشته نمی شوند.می خواهیم فیلد  آدرس را در دیتابیس در یک فیلد Single ، بررسی کنیم  اما در صفحه ی UI ، ترکیبی از سه فیلد می باشد : شماره پلاک ، شماره خیابان ، نام محل

 فیلد  Name در دیتابیس ، یک فیلد Single می باشد اما در صفحه UI  سه تا فیلد وجود دارد نام ، نام دوم ، نام خوانوادگی.

برخی از شما ممکن است این طور فکر کنید که برای الحاق فیلد ها در کنترلرلازم است آن ها را به  یک model property و entity class property  متصل کنید تا دقیقا با پایگاه داده مطابقت داشته باشند. انجام این کار ، راه مناسبی نمی باشد.MVC دارای binding  model سفارشی سازی شده  می باشد.که ما یک بار تعریف می کنیم ، و این منطق ، در هرجایی که ما می خواهیم برای اشاره به   Model، اعمال خواهد شد. 

اگر ما در بخش های زیادی نیاز داشته باشیم تا ازاین روش استفاده کنیم باید از ویژگی ای در MVC به نام Custom Model Binding استفاده کنیم. این ویژگی کار را برای ما آسان تر می کند.

به ما اجازه دهید تا یک مثال ساده را بررسی کنیم.

ما فیلدهای UI و کلاس ViewModel داریم که دارای نگاشت های مختلف می باشد اما ما باید آن را با استفاده از Model binding سفارشی سازی شده ، نگاشت کنیم و آن را در دیتابیس با استفاده از entity framework ذخیره کنیم.

به ما اجازه دهید یک دیتابیس به نام student و یک جدول به نام studentInfo ایجاد کنیم .

Query برای ایجاد یک جدول

SQL Query برای ایجاد یک جدول

1.	USE [Student]    
2.	GO    
3.	    
4.	    
5.	SET ANSI_NULLS ON    
6.	GO    
7.	    
8.	SET QUOTED_IDENTIFIER ON    
9.	GO    
10.	    
11.	CREATE TABLE [dbo].[StudentInfo](    
12.	    [StudentId] [int] NOT NULL,    
13.	    [Name] [nvarchar](50) NULL,    
14.	    [Address] [nvarchar](50) NULL,    
15.	    [City] [nvarchar](50) NULL,    
16.	    [State] [nvarchar](50) NULL,    
17.	    [Country] [nchar](10) NULL,    
18.	    [Department] [nchar](10) NULL,    
19.	    [Marks] [int] NULL,    
20.	 CONSTRAINT [PK_StudentInfo] PRIMARY KEY CLUSTERED     
21.	(    
22.	    [StudentId] ASC    
23.	)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]    
24.	) ON [PRIMARY]    
25.	    
26.	GO    

ما یک Stored Procedure برای قرار دادن اطلاعات  دانش آموزان ایجاد کرده ایم.

1.	USE [Student]  
2.	GO  
3.	/****** Object:  StoredProcedure [dbo].[InsertStudentInfo]    Script Date: 6/24/2016 10:40:58 AM ******/  
4.	SET ANSI_NULLS ON  
5.	GO  
6.	SET QUOTED_IDENTIFIER ON  
7.	GO  
8.	  
9.	CREATE PROCEDURE [dbo].[InsertStudentInfo]   
10.	     @StudentId [int],   
11.	      @Name   [nvarchar](50),  
12.	       @Address  [nvarchar](50),   
13.	       @City  [nvarchar](50),  
14.	       @State  [nvarchar](50),  
15.	       @Country  [nchar](10),  
16.	       @Department  [nchar](10),  
17.	       @Marks  [int]  
18.	AS  
19.	BEGIN  
20.	      
21.	    SET NOCOUNT ON;  
22.	  
23.	     INSERT INTO dbo.StudentInfo(StudentId, Name,Address,City,State,Country,Department,Marks )  
24.	    VALUES(@StudentId, @Name,@Address,@City,@State,@Country,@Department,@Marks)  
25.	  
26.	END  

حال stored procedure ما آماده است و از این Stored Procedure برای قرار دادن رکوردها با استفاده از  entity framework   ، استفاده می کنیم.

حال ما یک ASP.NET MVC Web Application ساده ایجاد می کنیم.به Visual Studio  بروید و یک پروژه جدید ایجاد کنید.

در مرحله ی بعدی MVC را انتخاب کنید و روی دکمه ی OK کلیک کنید.

حال ما یک Item جدید برای آوردن داده با استفاده از entity framework ایجاد می کنیم.

به قسمت Project بروید و Add new Item را می زنیم.

ADO.NET Entity Data Model را انتخاب کنید و روی ADD کلیک کنید.در مرحله ی بعدی صفحه ی زیر را می بینیم.

Generate را انتخاب کنید و سپس روی Next کلیک کنید.

در این مرحله نام دیتابیس سرور خودتان  ونام  دیتابیس در این wizard را انتخاب کنید .

در اینجا در این مرحله گزینه ی Stored Procedure را انتخاب کنید و “InsertStudentInfo” را که ما برای قرار دادن در دیتابیس ایجاد کرده ایم ، انتخاب کنید.سپس روی Next کلیک کنید.

روی Next کلیک کنید تا به مرحله ی بعدی بروید.

حال ، ما خواهیم دید که  StudentEntities برای ما ایجاد شده است .در مرحله ی بعد روی Finish  کلیک کنید.حال ما model ایجاد خواهیم کرد .به پوشه Model بروید و یک Model جدید به نام StudentViewModel مانند زیر ،ایجاد کنید.

1.	using System;  
2.	using System.Collections.Generic;  
3.	using System.ComponentModel.DataAnnotations;  
4.	using System.Linq;  
5.	using System.Web;  
6.	  
7.	namespace CustomModelBinding.Models  
8.	{  
9.	    public class StudentViewModel  
10.	    {  
11.	       
12.	        public int StudentId { get; set; }  
13.	        public string Name { get; set; }  
14.	        public string Address { get; set; }  
15.	  
16.	        public string City { get; set; }  
17.	        public string State { get; set; }  
18.	  
19.	  
20.	        public string Country { get; set; }  
21.	        public string Department { get; set; }  
22.	  
23.	        public int Marks { get; set; }  
24.	    }  
25.	}  

برای ایجاد کردن model Binding سفارشی سازی شده ما باید یک کلاس که از DefaultModelBinder ارث بری کرده است و متد BindModel() را که در آنoverride  شده است ،بنویسیم. متد BindModel() از کلاس ، دوتا پارامتر ControllerContext و ModelBindingContext را  می گیرد ، که ControllerContext  اطلاعات درخواست را که از  view پاس داده شده،  نگهداری می کند.ما اطلاعات درخواست را از request query string میگیریم ، آن را به هم پیوسته می کند و به Model ما اختصاص می دهد مانند زیر:

1.	public class StudentModelBinder : DefaultModelBinder  
2.	    {  
3.	  
4.	        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)  
5.	        {  
6.	            if (bindingContext.ModelType == typeof(StudentUIModel))  
7.	            {  
8.	                HttpRequestBase request = controllerContext.HttpContext.Request;  
9.	  
10.	                 int frmStudentId = Convert.ToInt32(request.Form.Get("StudentId").ToString());  
11.	                 string frmAddress = request.Form.Get("Address");  
12.	                 string frmCity = request.Form.Get("City");  
13.	                 string frmState = request.Form.Get("State");  
14.	  
15.	                string frmFName = request.Form.Get("FName");  
16.	                string frmMName = request.Form.Get("MName");  
17.	                string frmLName = request.Form.Get("LName");  
18.	  
19.	                string frmDoorNo = request.Form.Get("DoorNo");  
20.	                string frmStreetNo = request.Form.Get("StreetNo");  
21.	                string frmAreaName = request.Form.Get("AreaName");  
22.	  
23.	                string frmCountry = request.Form.Get("Country");  
24.	                int frmMarks = Convert.ToInt32(request.Form.Get("Marks").ToString());  
25.	  
26.	                return new StudentUIModel  
27.	                {  
28.	                    StudentId = frmStudentId,  
29.	                    Address = frmDoorNo + " " + frmStreetNo + " " + frmAreaName,  
30.	  
31.	                    City = frmCity,  
32.	                    State = frmState,  
33.	                    Name = frmFName + " " + frmMName + " " + frmLName,  
34.	                    Country=frmCountry,  
35.	                    Marks= frmMarks  
36.	                };  
37.	  
38.	               
39.	            }  
40.	            else  
41.	            {  
42.	                return base.BindModel(controllerContext, bindingContext);  
43.	            }  
44.	        }  
45.	  
46.	    }  

ما این کلاس را  برای global.asax.cs  مانند زیر ، برای پاسخ به این model binding  در هرجای برنامه ، ثبت می کنیم.

1.	public class MvcApplication : System.Web.HttpApplication  
2.	 {  
3.	     protected void Application_Start()  
4.	     {  
5.	         AreaRegistration.RegisterAllAreas();  
6.	         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
7.	         RouteConfig.RegisterRoutes(RouteTable.Routes);  
8.	         BundleConfig.RegisterBundles(BundleTable.Bundles);  
9.	         ModelBinders.Binders.Add(typeof(StudentUIModel), new StudentModelBinder());  
10.	     }  
11.	 }  

به ما اجازه دهید به Controller برویم و این model Binding را که از Controller به نام Action فراخوانی شده است ، را بگیریم.

ابتدا ، زمانی که صفحه لود شده است ما action به نام Index را فراخوانی می کنیم.

1.	public ActionResult Index()  
2.	  
3.	{  
4.	  
5.	return View(new StudentUIModel());  
6.	  
7.	}  

زمانی که action  به نام Index اجرا شد view به نام  Index  به صورت زیر render می شود.

زمانی که ما اطلاعات را پر می کنیم  و داده را ارسال می کنیم ، در Home Controller ما action به نام StudentInformation داریم و زمانی که view پست شد ،درخواست را می گیرد .

  actionبه نام   StudentInformation ،  Model را به ModelBinder پاس می دهد که ModelBinding را سفارشی سازی می کند.

1.	[HttpPost]  
2.	        public ActionResult StudentInformation([ModelBinder(typeof(StudentModelBinder))] StudentUIModel studentmodel)  
3.	        {  
4.	  
5.	            try  
6.	            {  
7.	                var name = studentmodel.Name;  
8.	  
9.	                StudentEntities s = new StudentEntities();  
10.	                s.InsertStudentInfo(studentmodel.StudentId, studentmodel.Name, studentmodel.Address,  
11.	                    studentmodel.City, studentmodel.State, studentmodel.Country, studentmodel.Department, studentmodel.Marks);  
12.	  
13.	                ViewBag.InsertMessage = " اطلاعات وارد شده با موفقیت ذخیره شده است";  
14.	            }  
15.	            catch(Exception ex)  
16.	            {  
17.	  
18.	            }  
19.	  
20.	            return View("Index");  
21.	  
22.	        }  

حال متد  ()InsertStudentInfo را فراخوانی کنید از StudentEntities که داده را در جدول StudentInfo با استفاده از Stored Procedure خودمان ، وارد می کند.

ما میبینیم که رکورد ما در دیتابیس قرار گرفته است .به فیلدهای Name و Address نگاه کنید. که شامل همه ی داده هایی می باشد که به  وسیله model Binder اضافه کرده ایم.

در برخی موارد ما می خواهیم فیلدهای متفاوتی را برای وارد کردن روز، ماه ، سال و زمان در نظر بگیریم در حالی که  در پایگاه داده فقط یک فیلد برای ذخیره این مقادیر وجود دارد. در برخی موارد نیز ما می خواهیم متنی را قبل از قرار دادن فیلد ها در پایگاه داده به  فیلد جاری اضافه کنیم .

آموزش asp.net mvc

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید