این قابلیت به این شکل انجام میشه که میاد دیتایی که از سمت client میاد به سمت سرور رو که به شکل string هستش رو میگیره و میتونه دسته بندی روش انجام بده یا convert اش کنه و اون مدل data type که میخوایم رو بهمون میده
دقت داشته باشید که model binding میاد و درخواست ما رو میگیره تحلیل میکنه و میگرده و بعد وصلش میکنه به جایی که باید کار کنه
خوب model binding asp .net میاد در 5 جای مختلف میگرده دنبال دیتای ما
اگر کاربر دیتا رو به یکی از این مکان ها ارسال کرده باشه اون رو میگیره و میبره توی اون متغییر ها میزاره تا ازشون استفاده کنیم
خوب اگر درخواستمون get باشه از 1 و 2 استفاده میشه اگر post باشه توی 1 و 2 و 3 میگرده ولی برای دو مورد آخر باید خودمون بیایم ستاپ کنیم که بره دیتا رو چجوری بخونه و چی کار کنه
خوب اینجا میبینید که پارامتر name خالی و null هستش ، چرا؟ چون که خوده فریمورک رفته گشته توی اون مورد های 1 و 2 و 3 ولی پیدا نکردتش درسته که ما با پستمن دیتا رو داریم توی هدر میفرستیم ولی فریمورک توی هدر رو نگاه نمیکنه و ما باید خودمون براش تعیین کنیم
ولی اینجا وقتی که با کوئری استرینگ میفرستیم دریافتش میکنه
خوب ما اینجا داریم توی 3 مکان مختلف name رو ارسال میکنیم یکی توی route هستش که babei یکی توی query string هستس که ehsan یکی هم توی header هستش
اول route چک میشه و اگر پیدا نکرد میره توی query string حالا اگر بخوایم دیتا رو از header بخویم میام این کار رو میکنیم :
اینجا باگتو رو دریافت میکنیم میتونیم هم برای این که سریع تر پیدا ککنده خوده model binding دات نت اینطوری بنویسیم اینطوری دیگه route چک نمیشه
خوب در این حالت هر دو نام ها باید با هم یکسان باشند ولی اگر قراره متفاوت باشند این کار رو میکنیم :
اینجا از سمت client با person name میاد و بعد میاد توی full name در سمت بک اند قرار میگیره
حالا میخوایم طبق چیزهایی که توی این کلاس تعریف شده بیایم و از client دیتا رو بگیریم
خوب اینجا چرا user id صفر هستش؟ دلیلش اینه که وقتی که دیتا رو از سمت client میفرستیم سمت سرور ، توی سرور میاد و اگر نتونه پیداش کنه مقدار دیفالت براش میزاره چون ما اومدیم user id رو در header گذاشتیم و بهش نگفتیم که user id توی header هستش پس در نتیجه صفر به ما میده
حالا میایم و توی route براش userid رو میفرستیم
حالا نکته ای که هست اینه که اگر ما بفرستیم ولی نتونه convert اش کنه باز هم مقدار دیفالت براش میزاره
اینجا به جای این که به user id که از نوع عددی هستش بهش string دادیم و فرستادم و سمت سرور چون نمیتونه که convert اش کنه میاد مقدار دیفالت میزاره که میشه همون صفر
وقتی که دیتایی رو از سمت کلاینت به سرور میفرستیم به صورت string دریافت میشه و وقتی که model binding اون رو دریافت میکنه بر اساس اون دیتا تایپ ها که براشون تعیین کردیم میاد و تبدیل رو انجام میده به صورت مثال میاد 20 رو که به صورت string هستش رو به int تبدیل میکنه
خوب حالا با استفاده از attribute میتونیم براش مشخص کنیم که کجا بره دنبالش
اینجوری ارسالش میکنیم
خوب حالا این رو در نظر بگیرید که client میتونه user و user id رو اگر بتونه خودش بفرسته سمت سرور و بعد بتونه اطلاعات اون یوزر رو ویرایش میتونه بکنه که این قابل قبول نیست روش برای جلوگیری اینه که dto های مختلف بنویسیم
توی home controller خوب حالا این رو در نظر بگیرید که client میتونه user و user id رو اگر بتونه خودش بفرسته سمت سرور و بعد بتونه اطلاعات اون رو یوزر رو ویرایش میتونه بکنه که این قابل قبول نیست روش برای جلوگیری اینه که dto های مختلف بنویسیم
توی home controller
بعد همونجا میایم و برای اکشنش از اون کلاسی که تعریف کردیم که میاد اطلاعات رو بر اساس UserInfoDto میگیره نکته این که ما اومدیم اینجا اون کلاس رو new کردیم ولی در صورتی که درستش اینه که از di استفاده کنیم
ولی این کار هایی که در بالا کردیم درست نیست و باید یه dto برای دریافت دیتا از سمت کلاینت درست کنیم یکی برای دریافت اطلاعات در سمت سرور درست کنیم - به این شکل :
خوب میدونیم که userInfoDto توی سرویسمون داره استفاده میشه
و user info Client Dto رو هم میبریم سمت user و اینتطوری ازش استفاده میکنیم :
اینطوری user فقط میتونه name و last name و token رو ارسال کنه و نمیتونه دیگه user id رو ارسال کنه
حالا اگر در سمت کلاینت و سرور بخوایم از یک DTO استفاده کنیم :
حالا یه راهی که بتونیم جلوی این که کلاینت نتونه userid رو بفرسته اینه که این کار رو کنیم :
یا این کار رو کنیم :
خوب در نظر بگیرید که اگر برای متدی که post هستش بیایم و get بزنیم
این ارور رو میگیریم
حالا اگر از post استفاده کنیم خالی ارسال کنیم
حالا همین قضیه رو توی api میریم تست کنیم اگر برای یه Route بیایم و اطلاعاتی غیر از اون چیزی که میخواد رو ارسال کنیم چی میشه ؟
توی query string میزنیم
خوب حالا میایم به صورت json دیتا براش میفرستیم
اینجا درست انجام میشه و ارور نمیده
این رو یادمون باشه که در جاهایی که از اتریبیوت api Controller داره استفاده میشه اگر هم دیتا رو به صورت کامل از اون چیزی که میخواد ارسال کنیم باز هم کار میکنه :
حالا اگر بیایم و بگیم دیتا رو از query فقط دریافت کن جی؟
باز هم دریافت میکنه وقتی که به شکل json در body ارسالش میکنیم
حالا توی این حالت هم از query بفرستیم و هم از json اینجا میاد اونی که توی query هستش رو دریافت میکنه
اگر چیزی رو بفرستیم و نتونه convert اش کنه اگر اون تای
مقدار دیفالت داشته باشه اون رو میزاره و اگر نداشته باشه nulll میزاره
این دیتا تایپ ها رو asp ساپورت میکنه
همه ی این ها به صوت string ارسال میشن اگر هم نخوایم model bonding بخواد کاری برامون انجام بده ، میتونیم اون دیتاتای رو براش غیر فعال کنیم خوب حالا با این دستور دیگه bool تبدیل روش انجام نمیشه :
خوب میایم توی home controller این ها رو درست میکنیم
خوب اینجا اومدیم با استفاده از tag helper ها اون چیزی که قراره توی model binding فریم ورک اون رو بگیره رو تعیین کردیم :
مثلا user . name
اولویت برای پیدا کردن دیتا ها با اون اسمی هستش که براش تعیین کردیم که در اینجا میشه user
خوب حالا فکر کنید که میخوایم دو تا اطلاعات متفاوت رو ارسال کنیم :
اینجا میبینید که null هستش info برای همین قضیه باید اینطوری عمل کنیم :
اینطوری به صورت nested میتونیم بهش دسترسی پیدا کنیم
خوب حالا یه راه دیگه :
اینطوری هم میتونیم بهش دسترسی پیدا کنیم
یه راه دیگه هم داریم :
خوب فرض کنید که 3 تا چک باکس داریم
میخوایم اطلاعاتی که یوزر توی این 3 تا میزنه رو بفرستیم سمت سرور
برای این کار name تمامی کنترلر هامون باید یکی باشه
اسم همه رو گذاشتیم ch
حالا میریم توی home controller و این کار رو میکنیم :
حالا دوتاش رو تیک میزنیم
اینجا نمیتونیم تشخیص بدیک که کدومشون تیک خورده ، تنها چیزی که متوجه میشیم اینه که دوتاشون تیک خورده
این هم یه راه دیگه :
خوب حالا میایم و براش اندیس تعیین میکنیم :
از طریق IFormCollection هم میتونیم :
میایم به اون فرم های که قبلا نوشتیم این رو هم اضافه میکنیم :
همه ی اطلاعاتی که داخل فرم ها هستش برای ما ارسال میشه
یه راه دیگه هم استفاده از IFormFile استفاده میکنیم :
یه تغییر دیگه رو هم باید اعمال کنیم
بیایم و enctype رو بزاریم روی multipart/form-data
اگر چند تا هم فایل داشتیم از این استفاده میکنیم :
خوب حالا اگر ما یه سرویس داشته باشیم، اول اومدیم اینترفیسش رو تعریف کردیم و بعد اومدیم یه کلاس دیگه تعریف کردیم که از این اینترفیس ارث بری میکنه بنابراین باید اون متدی که داخل اینترفیس هستش رو پیاده سازی کنیم
بعد میریم توی فایل Starup میایم و از AddTransient استفاده میکنیم و به سرویس هامون اضافه اش میکنیم
و به جای تزریق وابستگی میتونیم ازش اینطوری استفاده کنیم ، با استفاده از FromService
با استفاده از model binding میتونیم تزریق وابستگی رو هم انجام بدیم
تمامی دیتاهایی که از سمت کلاینت به سمت سرور میره با فرمت json ارسال میشه و ما میتونیم این فرمت رو تغییر بدیم :
برای تغییر اول باید پکیج اون فرمت دلخواهمون رو از ناگت بگیریم اینجا از json میخوایم تغییر بدیم به xml
میریم در فایل startup و این کارو میکنیم :
در کنترلر هم میام از این attribute استفاده میکنیم
در مواقعی که بخوایم model binder رو به صورت اتختصاصی برای خودمون درست کنیم این کاراها رو میکنه :
به طور مثال میخوایم با این فرمت دیتا رو دریافت کنیم
خوب حالا اگر بخوایم این کارو بکنیم باید بیایم یه کلاس جدا درست کنیم و بعد بیایم از اینترفیس IModelBinder ارث بری کنیم
برای پارامتر ورودی میاد اون دیتایی که از ورودی میاد رو توی bindingContext میگیره یا از سمت کلاینت براش ارسال میکنیم
بعد میایم کلاس یوزر رو مینویسیم:
public class UserCustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var values =bindingContext.ValueProvider.GetValue("User");
if (values.Length == 0)
{
return Task.CompletedTask;
}
var splitData = values.FirstValue.Split('|');
if (splitData.Length >= 3)
{
User user = new User()
{
Id = int.Parse(splitData[0]),
Name = splitData[1],
LastName = splitData[2],
};
bindingContext.Result = ModelBindingResult.Success(user);
}
return Task.CompletedTask;
}
}
برای توضیح کد بالا :
مورد بعدی
اینجا ما key رو user در نظر گرفتیم ، این یعنی این که از سمت کلاینت باید با کلید user اون string رو دریافت کنیم :
اگر تغییرش بدیم به UserN باید از سمت کلاینت هم با همین کلید ارسالش کنیم
مورد بعدی
public IActionResult NewUser([ModelBinder(binderType:typeof(UserCustomModelBinder))]User newUser)
{
return View();
}
برای استفاده ازش در controller هم اینطوری ازش استفاده میکنیم
https://www.dotnetcurry.com/aspnet-mvc/1368/aspnet-core-mvc-custom-model-binding