معرفی Best Practice ها در Asp.Net Core : پیاده سازی Response

اگر با متدهای HTTP آشنایی ندارید ابتدا این مقاله را مطالعه کنید.این مجموعه با نگاهی به ویدیوی آموزشی Best Practice در Pluralsight که توسط Steve Smith تهیه شده، گردآوری شده است.این مجموعه مقالات به شکل ویدیویی هم در کانال تلگرامم قرار میگیره. خوشحال میشم برای با خبر شدن از مقالات و نوشته ها و ویدیوهای آموزشی در این کانال حضور داشته باشید و نظراتتون رو بنویسید.https://t.me/mediapub_channelفهرست مقالات مجموعه معرفی Best Practice های دات نت :مقدمه : آشنایی با REST و پیاده سازی GET/POST/PUT/DELETEبخش اول : پیاده سازی Response (همین مقاله)بخش دوم : مدل های apiبخش سوم : پیاده سازی apiبخش چهارم : امنیتبه کمک Asp.Net Core میتوان سه مدل خروجی برای Action ها داشته باشیم :1. Specific Types - Primitive types(int,string,...)- Complex types(Author,Customre,Order,...)- Collection (List<T>,Dictionary<T>)- IEnumerable<T>,IAsyncEnumerable<T>2. IActionResult3. ActionResult<T>حالت اول Specefic Typesحالت اول ساده است و به راحتی و بدون اضافه کاری توسط Swagger شناخته و نوع خروجی نمایش داده میشود. مشکل این روش مشکل در ساختن خروجی با تایپ دیگر است. نکته در مورد IAsyncEnumerable : در این روش بدون عملیات buffering به محض دریافت یک رکورد از یک ریسورس (مثل سرویس یا دیتابیس) آن را به سمت ریسپانس هدایت میکنیم و در حقیقت جریان اطلاعات داریم.اولا خود اکشن به شکل async باید باشد و خروجی آن یک به شکل individual Instance و به روش yield باشد. خروجی ما در این حالت آبجکت پروداکت به شکل one by one است، یعنی به محض رسیدن اطلاعات آن از سمت یک دیتاسورس، آبجکت را به بیرون انتقال میدهد. یکی از مثال هایی که با این روش قابل پیاده سازی است فیلترینگ in-memory است. بطور نرمال بهتر است فیلترینگ در نزدیکی دیتاسورس انجام شود اما بعضی اوقات مجبوریم آن را در برنامه خودمان انجام دهیم و این روش راهی را فراهم میکند که بدون buffering کردن نتیجه در یک کالکشن پیش از ریترن، بتوانیم دیتا را آناً به بیرون پاس دهیم. این موضوع برای پرفورمنس اهمیت دارد و اینکه کمترین فشار به حافظه آورده شود.حالت دوم IActionResultانعطاف پذیر است و زمانی که از BaseController ارث بری میکنید متدهایش مثل OK و NotFound و BadRequest قابل دسترس است. حالت استاندارد شده خروجی و یک پاسخ یکپارچه برای همه متدها از ویژگی های مثبت این روش است. اینکه این نوع پاسخ به شکل Strongly Type نیست میتواند هم نکته مثبت و هم منفی باشد. نکته مثبت به دلیل اینکه مجبور نیستیم تایپ خاصی را هر بار به آن پاس دهیم و نکته منفی به دلیل اینکه ابزارهایی مثل Swagger نمیتوانند تایپ خروجی را حدس بزنند و در صفحه نشان دهند.در کد فوق میبینید که چون خروجی از نوع IActionResult است مجبوریم از اتریبیوت ProduceResponseType استفاده کنیم تا تایپ خروجی برای Swagger قابل نمایش باشد.حالت سوم ActionResult<T>Iاین حالت شبیه حالت دوم است با این تفاوت که Strongly Type است. فواید این روش مجموعه ای از فواید دو حالت اول است ولی هنوز هم در این روش شما برای استفاده سوئگر نیاز به اتریبیوت ProducesResponseType دارید.همانطور که میبینید برای اتریبیوت ProducesResponseType کافیست کد را معرفی کنید و تایپ خروجی نیازی نیست.نکته : رفتار ریسپانس ها در Minimal Api متفاوت است. سه نوع خروجی IResult (معادل actionResult) و Object و Json دارند.مثال زیر را ببینید: https://gist.github.com/51025816983b3629e65d69bc2a147b6b هر endpoint یک نام بر اساس نوع ریترن دارد. مثلا getObject یک آبجکت بر میگرداند.سوئگر به شکل زیر است.نوع ریزالت مشخص نیست.نوع ریزالت مشخص است اگر از اکشن ریزالت جنریک استفاده کنیم. برخلاف حالت قبل.با اجرای getObject به شکل جیسون خروجی را خواهیم دید و کانتنت تایپ جیسون است.با اجرای متد getObjectNull در خروجی چیزی نداریم و استتوس 204 یعنی No Content میگیریم. در این حالت کانتنت تایپ مشخص نشده است. بعضی از کلاینت ها انتظار دارند همیشه در خروجی جیسون داشته باشند. در حالتی که getObjectNull را تعریف کردیم این انتظار برآورده نمیشود.در متد getString با اینکه خروجی سریالایز شده یک آبجکت است ولی کانتنت تایپ Text نشان داده میشود. یعنی اگر استرینگ را به بیرون بفرستید کانتنت تایپ Text میشود.در حالت getJson خروجی همان چیزیست که انتظار داریم و کانتنت تایپ آن نیز جیسون است.در حالت ActionResult هم خروجی با استتوس کد و کانتنت تایپ منطبق است ولی سوئگر تایپ خروجی را نمیداند و از قبل نمایش نمیدهد.در حالت IActionResult هم خروجی با استتوس کد و کانتنت تایپ منطبق است و تفاوتش با حالت قبل این است که سوئگر تایپ خروجی را میداند و قبل از اجرای متد نمایش میدهد.در تمپلیت minimal api برای شلوغ نشدن program.cs میتوانیم از کتابخانه های جانبی استفاده کنیم. یکی از آنها MinimalApi.Endpoint است. که میتوان با آن endpoint ها را به کلاس های جدا منتقل کرد.مثلا برای Create کردن به شکل فوق باید کلاسی از IEndpoint ارث بری کرد. دو متد AddRoute و HandleAsync را باید پیاده سازی کرد. خروجی ما Task از تایپ IResult است و برای minimal Api پیشنهاد میشود. در خروجی از Results.Create استفاده میشد که در آرگومان اولی به آدرسی اشاره میکنیم که ریسورس ساخته شده از طریق آن قابل دسترسی است و در پارامتر دوم آنچیزی که در بدنه قرار است نمایش داده شود (یعنی ریسورس جدید که الان ساخته شده) قرار داده میشود.میخواهیم خروجی این api را با ورودی های فوق بررسی کنیم.آبجکت ساخته شده در body نمایش داده شده و همچنین در هدر ریسپانس ما برای کلید location ،آدرسی معادل مسیر دسترسی به این ریسورس را میبینیم.جمع بندی : - با مطالعه این نوشته و مقاله قبلی باید بتوانیم مفهوم Rest و HyperMedia را توضیح دهیم.- باید با مفهوم Resource ها آشنا شده باشیم که هر چیزیست که یک کد شناسنده یا معرف دارد و میتوانیم api های خود را با توجه به همین مفهوم سازمان دهیم و ایجاد و خواندن و حذف و تغییر ریسورس ها را به عهده بگیریم.- با متد ها یا verb ها آشنا شدیم. اینکه هر کدام در چه حالتی استفاده میشود و امنیت آن چگونه است.- با Http Status Code ها آشنا شدیم. اینکه کدامیک بیشتر استفاده میشوند.- با تایپ های Response در Asp.net Core آشنا شدیم.