Model Binding در MVC

در این مقاله راجع به Model Binding در MVC صحبت خواهیم کرد.در حین کار با MVC با کامپوننت های مختلفی مواجه هستیم از جمله کنترلر،view،action،application routes و model.بدون شک اینها کامپوننت های بسیار مهمی هستند ولی یک کامپوننت مهم دیگر هم هست به نام Model Binder. که پشت صحنه کار می کند .

Model Binding در MVC

در حین کار با MVC با کامپوننت های مختلفی مواجه هستیم از جمله کنترلر،view،action،application routes  و model.بدون شک اینها کامپوننت های بسیار مهمی هستند ولی یک کامپوننت مهم دیگر هم هست به نام Model Binder. که پشت صحنه کار می کند .

اگر بخواهیم واژه  Model Bindingرا تعریف کنیم به این صورت است که :روشی است که در آن پراپرتی های کلاس را با استفاده از داده هایی که از سمت کلاینت و در قسمت view می اید مقدار دهی می کنیم .

در پروژه ضمیمه این مقاله یک action  به صورت زیر در کنترلر تعریف می کنیم.

public ActionResult EmployeeDetails(int empId)
{
   //method body
    return View();
}

در متد بالا پارامتر empId  از نوع integer است این پارامتر وقتی به این متد یا action درخواستی وارد شود پر خواهد شد.یعنی ممکن است آن را توسط querystring به سمت action پاس دهیم و یا به عنوان قسمتی از یک فیلد ارسال کنیم به هر حال کار نگاشت این مقادیر پاس داده شده به پارامتر  empId  متد توسط Model binder. انجام میشود.

می توان روند model binding را توسط شکل زیر نشان داد

mvc model binding

وقتی پارامتر برای action  تعریف می کنیم مقادیر به صورت خودکار توسط Model binder به این پارامتر ها انتساب داده می شوند.دو نکته مهم در روند model binding وجود دارد.

نام فیلد تعریف شده در درخواست باید با نام پارامتر موجود در action  یکسان باشد.

مقدار درخواست باید قابل تبدیل به پارامتر action  باشد.

بنابراین اگر ما یک action  با پارامتری به نام empId  تعریف کرده ایم نام فیلد مورد نظر هم باید همین باشد.و همچنین مقدار این فیلد باید قابل تبدیل شدن به integer باشد.و به طور مثال نمی توانیم مقدار string برای این متد پاس دهیم.در غیر اینصورت یک exception  خواهیم گرفت .

منابع داده درخواستی مختلف

Model binder  با کمک value provider اطلاعات را از منابع داده ایی مختلفی جمع آوری می کند.این منابع داده ای شامل Form، Route، Querystring، Filesمی باشد.چیزی که در Model binder  مهم است این است که ما قادریم هر نوع دیتا ایی را به action پاس دهیم .

یک action دیگر مانند زیر تعریف می کنیم که تعداد پارامتر های آن زیاد باشدو شامل چندین نوع شود

public ActionResult Details(int empId,string name,string department,string address,DateTime dateOfJoining,string status)
{
return View();
}

ممکن است در آینده هم بخواهیم به تعداد این پارامتر ها ارسال کنیم .بنابراین روش معقول این است که یک کلاس تعریف کنیم با property های مشابه.و بعد به جای اینکه تعداد زیادی پارامتر بنویسیم از همین کلاس تعریف شده به عنوان پارامتر استفاده کنیم .

کلاسی که تعریف می کنیم مانند زیر است

public class Employee
{
    [Display(Name = "شناسه")]
public int empId { get; set; }
     [Display(Name = "نام")]
public string name { get; set; }
     [Display(Name = "دپارتمان")]
public string department { get; set; }
     [Display(Name = "آدرس")]
public string address { get; set; }
     [Display(Name = "تاریخ")]
public DateTime dateOfJoining { get; set; }
     [Display(Name = "وضعیت")]
public string status { get; set; }
  [Display(Name = "گزارش دهنده")]
public List<string> reportees { get; set; }
}

و action به این صورت تغییر خواهد کرد.

   public ActionResult Details(Employee emp)
        {
            return View();
        }

سپس برای اینکه مقادیر فیلد های این کلاس پر شود باید در صفحه view خود امکان پر کردن این فیلد ها را به کاربر بدهیم .صفحه view ما مانند زیر خواهد بود

@model ModelBinder.Models.Employee

@using (Html.BeginForm("Details", "Home"))
{
    <table>
        <tr>
         
            <td>@Html.LabelFor(x => x.name)</td>
            <td>@Html.TextBoxFor(x => x.name) </td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.department)</td>
            <td> @Html.TextBoxFor(x => x.department)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.address)</td>
            <td>@Html.TextBoxFor(x => x.address)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.dateOfJoining)</td>
            <td>@Html.TextBoxFor(x => x.dateOfJoining)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.status)</td>
            <td>@Html.TextBoxFor(x => x.status)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.reportees)</td>
            <td>
                <input type="text" name="reportees" />
                <input type="text" name="reportees" />
                <input type="text" name="reportees" />
            </td>
        </tr>
        <tr>
            <td><input type="submit" name="submit" /></td>
        </tr>
    </table>
}

بعد از اجرا صفحه ما به شکل زیر خواهد بود

بعد از اینکه اطلاعات را وارد کردیم و دکمه submit را کلیک کردیم اطلاعات به سمت action ارسال می شود این متد کار خاصی انجام نمی دهد ولی همان طور که در شکل زیر می بینید فیلدهای کلاس پارامتر ما به درستی پر شده اند.

برای سفارشی سازی عمل bind سه نوع different  وجود دارد:

1- Include     مشخص کننده property هایی است که باید به پارامتر انتساب شود

Exclude -2  مشخص کننده property هایی است که نمی خواهیم bind شود.

Prefix      -3  اجازه متفاوت بودن نام پارامتر با فیلدی که قرار است به آن منتسب شود را می دهد.

بعد از استفاده از Include در action نحوه انتساب به صورت زیر خواهد بود

        public ActionResult Details([Bind(Include = "name")] Employee emp)
        {
            return View();
        }

بعد از اجرا این کد شکل زیر را خواهید دید

بعد از استفاده از  Exclude نحوه انتساب به شکل زیر خواهد بود

        public ActionResult Details([Bind(Exclude = "name")] Employee emp)
        {
            return View();
        }

شکل انتساب به صورت زیر خواهد بود

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