
Model Binding در ASP.NET Core MVC مسئول انتقال داده ها از درخواست های Http به پارامترهای action هاست. پارامترها شاید مانند string، integer یا Float از نوع Simple ، و یا شاید از نوع Complex باشند. MVC این مشکل را با نادیده گرفتن Binding حل می کند. بنابراین توسعه دهندگان مجبور نخواهند بود یک نسخه ی مربوط به یک کد مشابه که فقط کمی تفاوت دارد را در هر برنامه ای دوباره بازنویسی کنند. نوشتن دوباره ی متن وتبدیل آن به نوع دیگر کار خسته کننده ای می باشد و ممکن است با خطا مواجه شود.
چطور کار می کند؟
زمانی که MVC یک درخواست HTTP دریافت می کند ، مسیر را برای یک action خاص مربوط به یک Controller تعیین می کند. این عمل تعیین می کند که کدام متد action براساس آنچه که در داده ی مسیر وجود دارد اجرا شود، سپس مقادیر را از درخواست HTTP به متد action مربوط به پارامترهای متصل (bind) می کند.
اولویت map شدن دیتا به Action های controller به شرح زیر است:
- Form Values
- Route Values
- Query Strings (در MVC به صورت خودکار مقادیر موجود در query String بر اساس Model Binding به Controller ها bind می شوند.)
به عنوان مثال فرض کنید که در Controller اکشن زیر وجود دارد:
1 2 3 4 5 |
//detail action in student controller public string Detail(int id,string name) { return $"ID: {id} and Name: {name}"; } |
با وارد کردن آدرس localhost/student/detail/1 در مرورگر، این نتیجه مشاهده می شود:
ID: 1 and Name:
همانطور که مشاهده می کنید مقدار name را در queryString وارد نکردیم، برای وارد کردن آن می توان به این شکل QueryString را نوشت:
localhost/student/detail/1?name=Arman
ID: 1 and Name: Arman
نیازی به نوشتن نام پارامتر ID نیست زیرا در تنظیمات Route آن را تنظیم کرده ایم:
1 2 3 4 5 6 7 8 |
//EndPoint app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } |
حال یک سوال مطرح می شود و آن این است که اگر در مرورگر آدرس زیر را وارد کنیم چه نتیجه ای مشاهده می کنیم؟
localhost/student/detail/1?name=Arman&id=6
ID: 1 and Name: Arman
چون همانطور که قبلا گفته شد، در Model Binding، اولویت با Route values است پس مقدار 6 اعمال نمی شود. اگر مقدار id در route را حذف کنیم چه اتفاقی می افتد؟
localhost/student/detail/?name=Arman&id=6
ID: 6 and Name: Arman
دیدیم که مقدار QueryString اعمال می شود. اما چه کاربردی دارد؟
اگر بخواهیم در متد Create اطلاعات یک دانش آموز را با فرم در حالت Post ایجاد کنیم می توانیم از آن استفاده کنیم.
مثال: در ادامه ی پروژه ای که در پست های قبلی برای Create نوشتیم میخواهیم با فشردن دکمه ی Create یک student اضافه شود.
در کنترلر Student اکشن زیر وجود دارد اما این اکشن برای متد get است که با رفتن به آدرس localhost/student/create به آن دست می یابیم:
1 2 3 4 5 |
[HttpGet] public IActionResult Create() { return View(); } |
یک اکشن دیگر احتیاج داریم تا در متد post از آن استفاده کنیم:
1 2 3 4 5 |
[HttpPost] public IActionResult Create(StudentModel student) { return View(); } |
حال باید در IStudentRepository یک متد برای افزودن دانش آموز بنویسیم:
1 2 3 4 5 |
public interface IStudentRepository { StudentModel GetStudent(int id); StudentModel Add(StudentModel student); } |
حال باید آن را در MockStudentRepository پیاده سازی کنیم:
1 2 3 4 5 |
public StudentModel Add(StudentModel student) { students.Add(student); return student; } |
یکی از property های student پارامتر ID می باشد که با هر بار Add شدن مقدار آن یکی اضافه می شود و نیازی نیست که حتما از کاربر گرفته شود. برای حل این مشکل از Lambda Expression استفاده می کنیم:
1 2 3 4 5 6 |
public StudentModel Add(StudentModel student) { student.Id = students.Max(x => x.Id) + 1; students.Add(student); return student; } |
و در کنترلر در اکشن create ای که متعلق به متد Post است، کد زیر را می نویسیم:
1 2 3 4 5 6 |
[HttpPost] public IActionResult Create(StudentModel student) { var newStudent = _studentRepository.Add(student); return RedirectToAction("Details",new { id=newStudent.Id}); } |
برای مشاهده ی کدهای مربوط به View مثال Create Student اینجا را کلیک کنید.