کلاس آموزش ASP.NET Core دارای سرفصل بسیار کاملی برای پیاده سازی یک Web Application به صورت MVC و همچنین Web API می باشد.شما با یادگیری مطالب این دوره می توانید تسلط بسیار خوبی روی ASP.NET Core بدست آورید و می توانید از صفر تا صد یک پروژه را به صورت کامل پیاده سازی کنید.
دوره آموزش ASP.NET Core و Web API - به صورت کامل ASP.NET Core را یاد بگیرید.
آموزش ASP.NET Core MVC
آموزش Web API
آموزش Razor Page
آموزش Blazor
آموزش SignalR
آموزش EF Core
آموزش Dapper
آموزش Token Authentication
دانلود فیلم آموزش ASP.NET Core
دانلود فیلم آموزش Web API
دوره آموزش ASP.NET Core با هدف آموزش صفر تا صد پیاده سازی Web Application های شما به روش های MVC و Web API آماده و ضبط شده است. شما با مشاهده کامل و تمرین مطالب گفته شده باید در آخر دوره بتوانید براحتی Web Application های خود را با ASP.NET Core پیاده سازی کنید.
در ابتدا باید بدانیم برای شروع این دوره به چه پیش نیازهای علمی نیاز داریم
پیش نیازهای عملی آموزش ASP.NET Core چیست ؟
در ابتدا باید تسلط خوبی روی زبان برنامه نویسی سی شارپ داشته باشید و بتوانید در آن نحوه تعریف کردن کلاس ها، متد و دستورات دیگیری مانند دستورات مقایسه ای، حلقه ها و سایر مطالب پایه ای سی شارپ را به خوبی انجام دهید.
پیش نیاز دوم دوره تسلط نسبی روی MS SQL Server و توانایی نوشتن کوئری CRUD خود می باشد. باید بتوانید کوئری های 4 عمل اصلی create – read – update – delete را به کمک sql بنویسید و توانایی ایجاد دیتابیس و جداول مورد نیاز را داشته باشید.
در سمت پیاده سازی ظاهر Web Application خود باید به html و css تسلط خوبی داشته باشید و همچنین زبان java script را هم بلد باشید.
موارد گفته شده پیش نیازهای دوره ASP.NET Core می باشند که شما با داشتن این پیش نیازهای می توانید در نهایت حرفه ای تر و با تسلط بسیار بیشتری پروژه های را انجام دهید.
برای شروع کار نیاز به نرم افزارهایی داریم که باید روی سیستم خود نصب کنیم.
پیش نیازهای نرم افزاری شروع کار با ASP.NET Core چیست ؟
اولین نرم افزار مورد نیاز Visual Studio یا Visual Studio Code می باشد. حالا بین این دو کدام را انتخاب کنیم. محتوای دوره با VS Code آموزش داده شده است. اگر شما هم به محیط VS Code عادت کنید خیلی بهتر است. در حال حاظر فایل نصب Visual Studio 2019 حدود 20 GB می باشد که حجم خیلی زیادی است. پس از نصب هم به صورت عادی حدود 4 تا 5 گیگ فضا نیاز دارد. در حالیکه فایل نصب VS Code حدود 70 MB می باشد که براحتی از سایت ماکروسافت قابل دانلود شدن می باشد و سبک تر و سریع تر از Visual Studio می باشد. شما در VS Code دیگر Wizard و پنجره هایی برای ایجاد بخش های مختلف ندارد و باید این کار را به صورت دستی و کد زدن ایجاد کنید که در ابتدای کار سختی است ولی در ادامه به آن عادت می کنید و برای شما لذت بخش خواهد بود.
در کنار VS Code اگر نیاز دارید که با دیتابیس کار کنید بهتر است یکی از نسخه های MS SQL Server را نصب کنید. می توانید از نسخه Express استفاده کنید که نسخه رایگانی است و می تواند نیازهای شما را در ایجاد و کار با دیتابیس برطرف کند.
پس از نصب SQL دیگر نیاز به نصب نرم افزار خاصی ندارید و ابزار برنامه نویسی شما تقریبا کامل شده است.
حالا به سراغ ASP.NET Core می رویم. در ابتدا باید یک تعریف از ASP.NET Core داشته باشیم و سپس نسخه های مختلف آن را مقایسه کنیم.
ASP.NET Core چیست ؟
بستری برای توسعه Web Application ها که توسط ماکروسافت ارائه شده است.
در ابتدا با نام ASP.NET شناخته میشد و از سال 2016 ماکروسافت شروع به بازنویسی و ارائه نسخه جدید با نام ASP.NET Core کرد. در ASP.NET ما می توانستیم Web Application های خود را به دو مدل Webform و MVC توسعه دهیم که مدل Webform از روش های موجود حذف شد و روش های دیگری جایگزین شد.
در Framework برنامه نویسی ماکروسافت .NET Framework بسیار شناخته شده و معروف است و اکثر برنامه نویسان C# یا VB از آن استفاده کرده ایم. شما با زبان C# روی بستر .NET Framework برنامه نویسی می کنید. نسخه .NET Framework دارای نقص ها و مشکلاتی بود که ماکروسافت تصمیم گرفت آن را بازنویسی کند و نسخه بهینه تر و بهتری را ارائه کند. آن شد که از سال 2016 نسخه ای بازنویسی شده و اصلاح شده با نام .NET Core 1 عرضه شد. هدف اصلی از این بازنویسی این بود که برنامه هایی که در بستر .NET Core نوشته می شوند ویژگی Cross Platform داشته باشند، یعنی روی سیستم عامل های غیر ویندوز قابل اجرا باشند. این بازنویسی فقط به خود .NET Framework نبود و بخش هایی مانند ASP.NET نیز همزمان بازنویسی شدند. از سال 2016 نسخه هایی بهینه تر و بهتری به ترتیب نسخه های 2 و 3 آماده و عرضه شد.
همزمان با توسعه دات نت کور ماکروسافت باید دات نت فریم ورک را هم توسعه میداد و این کار سخت و هزینه بری بود. از اواخر سال 2020 و با اعلام قبلی ماکروسافت .NET 5 را عرضه کرد که اتفاق بسیار مهمی بود. اول اینکه نامگذاری از .NET Core به .NET تغییر کرده بود و نسخه از 3 به 5 یکباره تغییر کرده بود و عدد 4 برای نسخه بعدی در نظر گرفته نشده بود. هدف از این تغییر این بود که دیگر .NET Framework توسعه داده نخواهد شد و همه باید با .NET 5 و نسخه های جدید کار کنند. همینطور از نسخه 4 برای ورژن بعدی استفاده نشده بود که برنامه نویسان دچار اشتباه و شباهت اسم بین .NET Framework نشوند.
پس ما از این به بعد یک نسخه واحد با نام .NET خواهیم داشت که نسخه فعلی آن 5 می باشد. توضیحات بالا مروری کوتاه در تاریخچه تغییرات نسخه های مختلف تا نسخه .NET 5 بود.
حالا برای شروع کار با .NET 5 باید ابتدا نسخه .NET 5 SDK را نصب کنید. برای برنامه نویسی باید نسخه SDK را نصب کنیم و برای اجرای نهایی پروژه ها در سرور باید نسخه Runtime را نصب کنیم. پس از آدرس زیر می توانید نسخه SDK را دانلود و نصب کنید.
الان می توانیم اولین پروژه ASP.NET خود را از طریق vs code یا command prompt ایجاد کنیم. برای این کار داخل پوشه ی پروژه های خود مثلا در درایو D یک پوشه My Projects ایجاد کنید و سپس در داخل آن یک پوشه برای پروژه ای که می خواهید ایجاد کنید بسازید مثلا DevTubeProject.
حالا برای ایجاد پروژه command prompt یا همان cmd را در مسیر DevTubeProject باز کنید. برای این کار می توانید بر روی آدرس بار داخل explorer پوشه DevTubeProject کلیک کنید و عبارت cmd را تایپ کرده و enter را بزنید.
حالا می خواهیم به کمک دستوارت dotnet cli پروژه خود را ایجاد کنیم. برای ایجاد پروژه ابتدا باید انواع Project Template های معروف و پرکاربرد در ASP.NET را بشناسیم.
پروژه های پرکاربرد در ASP.NET شامل موارد زیر می باشند :
یک مدل پروژه دیگر داریم که ماکروسافت در حال توسعه دادن و معرفی آن به برنامه نویسان وب می باشد. نام این مدل Blazor می باشد که در طول یک فصل درباره آن صحبت خواهیم کرد که چه ویژگی هایی دارد. شما می توانید با دستور dotnet new blazorwasm یک پروژه از مدل Blazor ایجاد کنید.
تا اینجا با انواع پروژه های ASP.NET Core آشنا شدیم و دیدیم که چطور می توانیم از طریق dotnet cli پروژه مورد نظر خود را ایجاد کنیم.
حالا می خواهیم ساختار یک پروژه ASP.NET Core را با یکدیگر بررسی کنیم.
بررسی ساختار پروژه و فایل های ASP.NET Core :
بعد از ایجاد پروژه می توانید آن را به روش های مختلفی توسط vs code باز کنید. مثلا روی فولدر پروژه کلیک راست کنید و open with code را کلیک کنید. یا اینکه vs code را اجرا کنید و از منوی فایل و در ادامه منوی open folder را انتخاب کنید و فولدر اصلی پروژه را برای باز شدن در vs code انتخاب کنید.
در تصویر بالا ساختار اولیه یک پروژه MVC را مشاهده می کنید.
در این مرحله با فولدر های مربوط به MVC که Model، Views و Controllers می باشند کاری نداریم و آنها را در بخش MVC به صورت کامل توضیح داد.
فایل ها و پوشه های پروژه ASP.NET Core :
بخش های معرفی شده به صورت پیش فرض در پروژه های ASP.NET Core وجود دارند که باید کاربرد و نحوه استفاده از هر کدام از این بخش ها را در ادامه یاد بگیریم.
تا همین جا می خواهیم بتوانیم پروژه را اجرا کنیم. برای اجرای پروژه می توانید یا در محیط vs code از روی کیبورد F5 را بزنید و پروژه را اجرا کنید یا اینکه از منوی vs code روی Terminal و New Terminal کلیک کنید و دستور dotnet run را اجرا کنید که پروژه را روی پورت های 5000 و 5001 می توانید در مرورگر خود مشاهده کنید.
حالا می خواهیم به صورت دقیق تر بخش های مهم پروژه ASP.NET Core را بررسی کنیم.
معرفی فایل Startup.cs در پروژه ASP.NET Core :
مهم ترین فایل در پروژه های ASP.NET Core، فایل Startup.cs می باشد که در ابتدای پروژه یکبار کدهای داخل آن اجرا می شود و باعث تغییرات در روند اجرا می شود. فایل Startup.cs دارای دارای دو متد زیر می باشد :
در تعریف و توضیح متد Configure با عبات Dependency Injection یا تزریق وابستگی ها آشنا شدیم. می خواهیم بیشتر درباره DI بدانیم و کاربرد و مزیت استفاده از آن در برنامه های ASP.NET Core آشنا شویم.
در حالت عادی زمانیکه که شما نیاز به استفاده از یک کلاس مانند ProductService را در داخل کلاس جاری خود دارید باید یک نمونه به صورت var productService = new ProductService(); ایجاد کنید و سپس از نمونه ایجاد شده که productService می باشد استفاده و متدهای مورد نیاز خود را فراخوانی کنید.
حالا کاربر ما یک درخواست دارد که در خلال این درخواست باید کدهای چندین کلاس اجرا شود و در اجرای هرکلاس باید یک نمونه از ProductService ایجاد شود و از آن استفاده شود. حالا می خواهیم بحث نمونه سازی را به صورت مستقیم انجام ندهیم و از DI کمک بگیریم. علاوه بر بحث مدیریت نمونه سازی، مزایای دیگری هم به کمک DI ما به دست می آوریم. در تزریق وابستگی ها ما دو مرحله داریم : ابتدا باید کلاس مورد نظر در متد ConfigureServices در داخل Startup.cs، Register شود. عملیات رجیستر کردن به سه شکل زیر می تواند انجام شود :
پس از بررسی Dependency Injection سراغ Middleware های متد Configure می رویم :
Middleware هایی که بررسی کردیم به صورت پیش فرض در پروژه ASP.NET Core MVC وجود دارد. به این موارد در صورت نیاز Middleware های دیگری هم افزوده می شود. باید توجه داشته باشید که الویت ها و محل نوشتن Middleware ها در ASP.NET Core مهم می باشند. در تصویر زیر نحوه درگیر شدن Middleware ها را در یک Request ارسالی از سمت Client و در زمان برگشت Response مشاهده می کنید.
برای درک بهتر الویت و نحوه اجرای Middleware ها تصویر دیگری در ادامه مشاهده می کنید که علاوه بر Middleware های موجود می توانیم Middleware های سفارشی نیز نوشته و در مسیر Request و Response قرار دهیم.
محتوای فایل Startup را مشاهده کردید. شما باید درک درستی از متدهای ConfigureServices و Configure داشته باشید و این تسلط به مرور و با درگیر شدن با بخش های مختلف پروژه در شما بیشتر خواهد شد.
حالا نوبت بررسی پروژه ها از نوع MVC می باشد. با اینکه با حضور SPA ها در زمنیه ساخت بخش Front روش هایی مثل MVC کم رنگ تر شده اند ولی باز بسیاری از پروژه ها با MVC پیاده سازی شده اند و یا در حال پیاده سازی هستند.
ASP.NET Core MVC چیست ؟
روشی است که می توانیم به صورت یکپارچه یک Web Application را پیاده سازی کنیم. از backend تا front را می توانیم به کمک MVC پیاده سازی نماییم که این مدل هم مزیت هایی دارد و هم معایبی که باید به آنها دقت کنیم.
در مدل MVC سه بخش مرتبط با یکدیگر داریم که هر کدام وظیفه ای دارند :
در تصویر زیر مشاهده می کنید که چرخه کار در MVC به چه شکلی است.
در نوشتن Controller و Action ها که مهم ترین بخش MVC می باشد پیچیدگی خاصی وجود ندارد. یک سری کار باید انجام شود که به ازای هر یک از آنها یک Action ایجاد می کنیم و در داخل آن ها شروع به کد نویسی می کنیم. باید دقت کنیم که بهتر است داخل بدنه متد Action خود متدهایی را فراخوانی کنیم و به اصطلاح Action های خود را لاغر و کوچک نگه داریم. مثلا کلاس های Service داشته باشیم و کدهای مربوط به منطق فرایندها و کدهای ارتباط با دیتابیس را داخل آن کلاس ها پیاده سازی کنیم و آنها را در داخل Controller و Action خود فراخوانی کنیم.
در تصویر زیر HomeController را مشاهده می کنید که به صورت پیش فرض در پروژه ASP.NET Core MVC ما ایجاد می شود. در خط تعریف کلاس HomeController مشاهده می کنید که از کلاس Controller ارث بری شده است. در خط 14 یک نمونه فقط از ILogger ایجاد شده است. سپس در خط 16 یک سازنده نوشته شده است که در ورودی خود یک نمونه از ILogger را دریافت می کند و در بدنه خود سازنده نمونه دریافتی logger داخل نمونه _logger قرار داده می شود.
این روند مرحله دوم تزریق وابستگی یا همان Dependency Injection می باشد. یعنی ما در کلاس HomeController نیاز به استفاده از کلاس Logger داریم. در حالت عادی باید یک instance به صورت دستی از Logger ایجاد می کردیم. ولی می دانیم یکی از ویژگی های مهم در ASP.NET Core استفاده از DI می باشد و بهتر است ما هم در سرویس ها و کلاس هایی که خودمان می نویسیم از امکان تزریق وابستگی استفاده کنیم. در اصول تزریق وابستگی ها بهتر است از interface ها برای مرحله دوم یا همان نمونه سازی در زمان مورد نیاز استفاده کنیم تا در آینده در صورت نیاز بتوانیم کلاس A را به جای کلاس B در کل پروژه یا در برخی شرایط معرفی کنیم.
فعلا در این مرحله فقط نیاز است در این حد موضوع را درک کنیم که دیگر کار نمونه سازی به کمک new برای کلاس هایی که شامل متد می باشند را دستی انجام نمی دهیم و به کمک تزریق وابستگی این کار را انجام می دهیم. در تزریق وابستگی دو مرحله داریم که اول باید register کردن در کلاس Startup و متد ConfigureServices انجام شود و سپس در زمان استفاده از طریق Constructor آن کلاس را به کلاس جاری تزریق و از آن استفاده کنیم.
در خط 21 تصویر بالا ما یک Action با نام Index داریم که خروجی آن از نوع IActionResult می باشد و در بدنه آن یک return View(); را مشاهده می کنید. در ASP.NET Core اکثر خروجی Action ها را از نوع IActionResult قرار می دهیم. اگر درخواستی برای این Action ارسال شود، View مرتبط با آن از مسیر Views و Home و Index پیدا شده و محتوای داخل آن برای کاربر درخواست دهنده ارسال می شود.
در ادامه می خواهیم روش های ارسال داده از Action به View را با هم بررسی کنیم. ما باید در داخل Action داده را آماده کنیم و به سمت View ارسال کنیم.
روش های ارسال داده از Action به View
ما در مدل MVC باید در صورت نیاز بتوانیم داده مورد نیاز View را از طریق Action تامین کنیم. برای ارسال داده از Action به View دو راه داریم :
الان می دانیم که برای ارسال داده از Action به View دو راه معمول و پراستفاده داریم که می توانیم از آنها استفاده کنیم. همپنین در یک Action می توانیم فقط یک model را از طریق return View ارسال کنیم ولی می توانیم در عوض چندین ViewData یا ViewBag تعریف کنیم.
در تصویر بالا مشاهده می کنید که از طریق ViewBag یا ViewData می توانیم داده را از سطح Controller به View مورد نظر ارسال کنیم. در تصویر بالا عبارت TempData را مشاهده می کنید که به وسیله آن می توانیم داده ای را از یک Controller به Controller دیگری ارسال کنیم.
می خواهیم کاربرد TempData را با هم بررسی کنیم.
TempData در ASP.NET Core چیست و چه کاربردی دارد ؟
TempData یک فضای ذخیره سازی داده است که در پشت صحنه در داخل Session نگهداری می شود. در گذشته در پروژه های ASP.NET Webform ما به تعداد زیاد به صورت مستقیم از Session استفاده می کردیم. شاید بعضی از دوستان با Session آشنایی نداشته باشند.
Session یک متغیر و یک فضای نگهداری موقت در حافظه می باشد که به ازای هر Client ایجاد می شود و دارای طول عمر می باشد. برای مثال کاربر A به سیستم ما وصل شده است. یک Session برای این کاربر A ایجاد شده است. اگر کاربر B نیز به نرم افزار وب ما وصل شود یک Session رو حافظه سرور به ازای کاربر B ایجاد می شود که می توانیم مقادیر خاص هر کاربر را به صورت موقت داخل Session نگهداری کنیم که در صورت نیاز از همان Session سریع خوانده و نیازی نباشد از دیتابیس این اطلاعات را دریافت کنیم. طول عمر Session هم به صورتی است که کاربر اگر درخواست های جدید داشته باشد این مدت زمان تمدید می شود و مثلا اگر کل طول عمر 20 دقیقه بوده باشد و الان 14 دقیقه از این زمان گذشته باشد، با درخواست جدید این زمان مجدد صفر خواهد شد.
مشکلی که در استفاده از Session پیش می آمد این بود که برنامه نویسان رفته رفته همه اطلاعات را در داخل Session نگهداری می کردند و این اتفاق باعث می شد که Web Application ما با زیاد شدن کاربران، استفاده از RAM بسیار بالایی داشته باشد. شاید شنیده باشید که نرم افزار فلان شرکت نرم افزاری برای اجرا شدن نیاز به سرور با مقدار RAM، 128 گیگ دارد. در حالیکه نسخه اولیه Web Applicaiton اصلا نیازی به این فضاها ندارد ولی به خاطر اشتباه در استفاده از Session در نگهداری داده ها، باعث می شود که این اتفاق رخ دهد.
در ASP.NET Core از همان ابتدا سخت گیری زیادی بر روی استفاده از Session شد و به صورت پیش فرض استفاده از آن در پروژه به صورت مستقیم فعال نمی باشد و اگر نیاز به Session ها دارید باید Middleware آن را که useSession می باشد را در Startup.cs قرار دهید.
پس بهتر است عادت به Session نداشته باشیم و اگر داریم آن را محدود و در ادامه قطع کنیم. برای ارائه راه حل بهتر و سبک تر TempData ارائه شده که در پشت صحنه روی Session نگهداری می شود ولی ویژگی های خاص خود را دارد.
TempData یک ویژگی خیلی مهم دارد که یکبار خواندنی می باشد. یعنی به صورت پیش فرض با یکبار خواندن مقدار آن، از بین می رود و اگر نیاز به نگه داشتن آن داشته باشیم باید توسط تابع TempData.Keep(); مقدار آن را حفظ کنیم.
در تصویر زیر نحوه تعریف و خواندن مقدار آن را مشاهده می کنید.
در ابتدا داخل Action Index مقدار 101 را داخل TempData[“Code”] قرار داده ایم و سپس در داخل Action Privacy ابتدا چک کرده ایم که آیا همچنین مقداری داخل TempData وجود دارد یا نه و سپس مقدار آن را خوانده و در داخل متغیر Code قرار داده ایم.
توصیه می کنم که سعی کنید تا در حد امکان از ویژگی TempData استفاده نکنید تا پروژه خود را رفته رفته دچار پیچیدگی نکنید. وقتی از TempData استفاده می کنید Controller ها و Action ها را به هم وابسته می کنید و این اصل مستقل بودن Action ها را رفته رفته از بین می برد.
حالا نوبت به View ها میرسد که ببینیم View ها چه نقشی دارند و انواع مختلف آن را در ASP.NET Core MVC بشناسیم.
View چیست و چه مدل هایی در ASP.NET Core MVC دارد ؟
بخشی است که در آن می توانیم کدهای html خود را بنویسیم و خروجی مورد نظر خود را برای صفحات ایجاد کنیم. در داخل View ما کدهای خود را به کمک Razor می نویسیم که این امکان را فراهم می کند که از کدهای C# در داخل کدهای html استفاده کنیم.
پسوند فایل های View در C# به صورت cshtml می باشد. محل نگهداری View در پوشه Views می باشد. در پوشه Views به صورت پیش فرض یک پوشه Home و یک پوشه Shared وجود دارد.
پوشه Home که مربوط به HomeController می باشد و View های مربوط به Action های این Controller را در داخل خود دارد.
پوشه Shared برای نگهداری Layout ها و همچنین Partial ها می باشد که در ادامه با هر دو اینها آشنا خواهیم شد.
در پوشه Shared دو فایل مهم دیگر وجود دارد که می خواهیم با آنها آشنا شویم :
حالا باید بدانیم چه نوع View هایی در ASP.NET Core MVC داریم.
انواع View ها :
در تصویر بالا مشاهده می کنید @RenderBody() و RenderSection تعریف شده است. ما می توانیم در یک Layout چندین RenderSection در جاهای مختلف Layout برحسب نیاز تعریف کنیم.
با هم انواع View ها در ASP.NET Core MVC را بررسی کردیم و کاربرد هر یک را به صورت تعریف به همراه نکات مهم دیدیم. حالا باید شما در پروژه ها رفته رفته این مهارت را در خود تقویت کنید که در چه بخشی از Partial یا ViewComponent به درستی استفاده کنید. باید دقت داشته باشیم که استفاده درست از Partial و ViewComponent باعث جلوگیری از تکرار یک تکه کد در بخش های مختلف می شود و پروژه شما هم ساختار بهتر و حرفه ای تری خواهد داشت.
علاوه بر این مدل View ها ما یک سری Razor Page هم داریم که به صورت کامل مستقل و بدون وابستگی به مدل MVC کار می کنند. می توانیم یک پروژه تنها به کمک Razor Page ها طراحی کنیم یا در کنار پروژه MVC خود بخش هایی را به کمک Razor Page ها پیاده سازی کنیم. در ادامه به Razor Page خواهیم پرداخت.
در این بخش می خواهیم بدانیم که نحوه مسیریابی در پروژه های ASP.NET Core MVC به چه شکل است.
Routing چیست و چه نقشی دارد ؟
Routing یا مسیریابی در پروژه ها به ما کمک می کنند که بتوانیم آدرس های مورد نظر خود را تعریف کنیم و آنها را به بخش های مورد نظر در پروژه متصل کنیم. برای مثال کاربر آدرس DevTube.ir/article را وارد می کند. در پروژه ما همچین مسیر فیزیکی نداریم ولی به کمک Routing می توانیم مشخص کنیم که این درخواست به چه Controller و چه Action ای ارسال شود.
نقطه شروع Routing از فایل Startup و متد Configure با فراخوانی Middleware با نام app.UseRouting که ویژگی Routing را به پروژه مورد نظر اضافه می کند. سپس در ادامه در همین بخش یک Middleware دیگر داریم که Endpoint های خود را در داخل آن تعریف می کنیم که به صورت پیش فرض یک آدرس در آن طبق تصویر زیر تعریف شده است.
در این endpoint که با نام default می باشد یک pattern تعریف شده که در آدرس درخواستی از سمت Client ابتدا نام controller می باشد و سپس action و در نهایت هم می تواند یک پارامتر اختیاری با نام id داشته باشیم. در controller ما مقدار home را به صورت مقدار پیش فرض داریم و سپس در action هم مقدار Index را داریم. اگر کاربر مقداری برای آنها وارد نکند، این مقادیر پیش فرض استفاده می شود. علامت سوال انتهای id? هم می گوید که ارسال مقدار برای id اختیاری می باشد.
ما می توانیم endpoint های دیگری در فایل Startup تعریف کنیم که بیشتر در مواقعی که از Area ها استفاده می کنیم استفاده می شود.
در Routing امکانی با نام Attribute Routing معرفی شد که بسیار کاربردی و پراستفاده می باشد. به کمک این ویژگی ما می توانیم بالای سر Controller و Action ها آدرس های مورد نظر خود را برای آن Controller و Action تعریف کنیم.
نحوه استفاده از Attribute Routing به شکل های مختلفی می باشد که در ادامه چند مدل از آن را با هم مشاهده می کنیم.
در تصویر بالا مشاهده می کنید که سه Route برای Index تعریف شده است. باید دقت داشته باشید که با تعریف Attribute Route برای یک Controller یا Action آدرس های قبلی و پیش فرض آنها دیگر کارایی ندارند و عمل نخواهند کرد و فقط آدرس های تعریف شده توسط Attribute Routing کاربرد دارند و کار می کنند.
توصیه می شود که تا حد ممکن نامگذاری Controller و Action ها را صحیح انجام دهید و کمتر از Attribute Routing استفاده کنیم. مگر اینکه نیاز داریم در یک Action چندین مدل آدرس دهی به یک Action ارجاع شود که در آن موقع می توانیم از Attribute Routing استفاده کنیم.
نوبت به بخش بسیار مهم و کاربردی نحوه ارتباط با دیتابیس در ASP.NET Core میرسد. باید روش های ارتباط با دیتابیس را بلد باشیم و بتوانیم نرم افزار خود را به دیتابیس مورد نظر متصل کنیم.
روش های ارتباط با دیتابیس در ASP.NET Core ؟
ما باید نسبت به نوع و اهمیت پروژه از روش بهینه تر استفاده کنیم و به این شکل نباشد که یک روش ارتباط با دیتابیس را برای هر مدل پروژه استفاده کنیم.
ما برای ارتباط با دیتابیس ها دو نوع کلی زیر را داریم :
کدام روش بهتر است ؟ این سوالی است که همیشه پرسیده می شود و جواب صحیح این است که بستگی به پروژه و همچنین سطح توانایی شما در هر کدام از مدل ها دارد. اینکه شما می توانید با کدام یک از مدل ها سرعت بهتری برای کوئری ها داشته باشید.
Dapper چیست و چه کاربردی در ASP.NET Core دارد ؟
Dapper یک کتابخانه بسیار خوب برای ایجاد ارتباط با دیتابیس به روش DB First می باشد که توانسته محبوبیت خوبی در ASP.NET Core بدست آورد. در گذشته از ADO.NET استفاده میشد که برای انجام یک عملیات ساده باید کد زیادی نوشته میشد. Dapper همه این بخش ها را خلاصه کرده است و نحوه عملکرد و سرعت اجرا نیز در آن مانند ADO.NET بالا می باشد.
برای استفاده از Dapper ابتدا با پکیج آن را از سایت NuGet نصب کنیم.
شاید از قبل با NuGet آشنایی زیادی نداشته باشید. NuGet وب سایتی برای دانلود پکیج های مربوط به پروژه های ماکروسافتی می باشد که براحتی می توانیم از طریق wizard یا دستور پکیج مورد نظر را نصب، بروزرسانی یا حذف کنیم.
در تصویر بالا صفحه اول سایت NuGet.org را مشاهده می کنید که تعداد پکیج ها و میزان دانلود را نشان می دهد که عدد بسیار بزرگی می باشد.
ما Dapper را از طریق همین سایت نصب و در پروژه خود استفاده می کنیم.
در تصویر بالا مشاهده می کنید که برای نصب از طریق .net cli باید چه دستوری را اجرا کنیم تا Dapper رو پروژه ما نصب شود.
سپس باید کدهای مربوط به Dapper برای اتصال به دیتابیس و اجرای دستورات را نوشته و اجرا کنیم. در زمان کار با Dapper می توانید دستورات SQL خود را یا در داخل کدهای C# خود در پروژه بنویسید و یا در سمت دیتابیس Stored Procedure تعریف کنید و نام SP ها را در داخل Dapper فراخوانی کنید و نتیجه را دریافت کنید.
در اجرای کوئری های SQL ما دو مدل کوئری داریم. یک مدل که داده ای را برمی گرداند که همان دستور Select است و دسته دوم که شامل Insert، Update و Delete می باشد که داده ای را برنمی گرداند و به اصطلاح ExecuteNonQuery شناخته می شوند.
برای همه این موارد در Dapper توابعی در نظر گرفته شده است. تفاوت اصلی Dapper و مزیت آن نسبت به ADO.NET این است که Dapper دارای سیستم داخلی Mapping می باشد که می تواند یک کلاس Model را گرفته و نتیجه اجرای یک query را در داخل کلاس مورد نظر قرار دهد و نیازی نیست به صورت دستی ستون به ستون این map کردن انجام شود. فقط باید نام Property های کلاس Model با نام ستون های کوئری یکسان باشد که کار Mapping به درستی انجام شود.
در مدل DB First همچنان شما باید کوئری های SQL بنویسید حالا یا به صورت مستقیم در ASP.NET Core که پیشنهاد نمی شود یا اینکه به صورت Stored Procedure در سمت دیتابیس و استفاده از نام SP ها در داخل کدهای ASP.NET Core استفاده کنیم.
حالا روش دوم برای ارتباط با دیتابیس در ASP.NET Core را ببرسی کنیم.
Entity Framework Core چه کاربردی در ASP.NET Core دارد ؟
EF Core یک ORM می باشد که وظیفه ایجاد ارتباط و اجرای درخواست های ما روی دیتابیس را دارد. دارای یک کلاس DbContext می باشد که وظیفه ارتباط و مدیریت دستورات را دارد.
ORM یا Object-relational mapping که یه شبیه سازی از دیتابیس و جداول آن در سمت محیط برنامه نویسی ایجاد می کند که بتوانیم براحتی عملیات مورد نظر خود را روی آن مدل ایجاد شده اجرا کنیم و ORM آن دستور درخواستی را ترجمه کرده و روی دیتابیس اصلی اجرا می کند.
در برنامه نویسی .NET ماکروسافت در سال های گذشته تلاش کرده که EF Core را بهینه تر کند و سرعت اجرا کوئری ها در آن افزایش پیدا کند، که تا حد زیادی موفق بوده است و سرعت اجرای کوئری ها خیلی بهتر شده است ولی همچنان روش هایی مثل Dapper سرعت اجرا بهتری دارند چون خود برنامه نویس کوئری را می نویسید و آن را برای اجرا به Dapper می دهد. ولی در EF Core کوئری ها به زبان Linq نوشته می شود و سپس Provider مربوطه دستور Linq را به دستوارت sql ترجمه می کند. مانند Google Translate که شما وقتی یک جمله انگلیسی را به آن می دهید، ترجمه فارسی آن همیشه خوب نیست و نیاز به اصلاح دارد.
در EF Core همچنان مشکل اصلی در نوشتن کوئری های Linq توسط برنامه نویسان است که در زمان استفاده از Linq دقت زیادی روی خروجی و بهینه بودن کوئری نمی شود.
پس برای کارکردن با EF Core شما باید به زبان کوئری نویسی Linq هم مسلط باشید.
در EF Core ما دو مدل برای کار کردن داریم که بسته به نیاز یکی از این دو روش را انتخاب می کنیم. این دو روش عبارتند از :
دستورات مهم در Migration، این دستورات می باشند :
شما باید با هر دو روش DB First و Code First بتوانید با دیتابیس کار کنید. نکته مهم این است که این دو روش مدل های ایجاد کردن دیتابیس می باشند و در ادامه برای انجام عملیات CRUD هیچ تفاوتی با یکدیگر ندارند. یعنی بعد از ایجاد دیتابیس یا DbContext به یکی از دو روش بالا، برای ادامه و اجرای دستورات، دیگر هیچ تفاوتی با یکدیگر ندارند و براحتی می توانید با دستورات Linq درخواست های خود را روی DbContext اجرا کنید.
باید توجه داشته باشید که با هم کدام از روش های DB First یا Code First در EF Core کار کنیم باید برای استفاده از DbContext در Controller ها یا سایر کلاس ها به صورت تزریق وابستگی، ابتدا باید DbContext را در کلاس Startup و در بخش ConfigureServices به صورت زیر register کنیم و در زمان Register کردن باید Connection String آن را مقداردهی کنیم. عموما مقدار Connection String را در فایل appsettings.json قرار می دهیم و به کمک Configuration مقدار آن را می خوانیم.
در تصاویر بالا مشاهده می کنید که ابتدا چگونه DbContext را در رجیستر کرده ایم و سپس در فایل appsetting ویژگی Connection String را تعریف کرده ایم.
با این کانفیگ می توانید براحتی در کلاس های پروژه، DbContext را از طریق Constructor تزریق کنید و از آن استفاده کنید.
می خواهیم پس از آشنایی با نحوه کار با دیتابیس، به سراغ بحث امنیت در نرم افزاری های ASP.NET Core برویم و نکات مهمی را بررسی کنیم.
انواع روش های Authentication در ASP.NET Core چیست ؟
Authentication یا احراز هویت در اکثر نرم افزارها مورد نیاز است. می خواهیم هویت کاربر را شناسایی کنیم و سوال شما کی هستی ؟ را از کاربر بپرسیم. به این کار Authentication گفته می شود. حالا این عملیات احراز هویت در ASP.NET Core می تواند به روش های مختلفی انجام شود.
طبق تصویر بالا می توانید در ابتدا ایجاد پروژه تیک Individual User Accounts را انتخاب کنید.
هر دو روش گفته شده در پشت صحنه از Cookie برای Authentication استفاده می کنند. یک روش دیگر Authentication به کمک Token داریم که آن را در بخش Web API کار خواهیم کرد.
روش های دیگر Authenticate هم در ASP.NET Core مثلا به کمک Microsoft Azure وجود دارد که در کشور ما به دلیل تحریم ها، براحتی نمی توانیم از این روش ها استفاده کنیم.
پس از احراز هویت کاربر، حالا کاربر وارد نرم افزار شده است. نوبت به کنترل و اعمال دسترسی ها می رسد.
چک کردن و محدود سازی دسترسی ها در ASP.NET Core :
برای انجام این کار ابتدا باید ساختار دیتابیسی و جداول مورد نیاز را ایجاد کنیم. در نرم افزار خود یک سری کاربر داریم، یک تعداد نقش و تعدادی دسترسی داریم. باید کاربر پس از Login به Application براساس دسترسی هایی که دارد، Application برای وی از نظر منوها و نمایش صفحات محدود شود.
در اعمال دسترسی ها دو مدل بسته به نیازی که داریم می توانیم طراحی خود را انجام بدهیم. اول اینکه به صورت Role Base کار کنیم و ابتدا نقش هایی را تعریف کرده و دسترسی ها را به Role ها بدهیم و سپس نقش ها را به User مورد نظر متصل کنیم. در حالت دوم دسترسی ها را مستقیم به خود User متصل کنیم که در این حالت اگر تعداد کاربران زیاد باشد مدیریت آن بسیار سخت می شود و دسترسی های کاربران یک سطح می تواند متفاوت باشد.
اینکه چگونه پیاده سازی دسترسی ها را داشته باشید می تواند در پروژه ها مختلف متفاوت باشد. نکته مهم این است که چگونه پس از Login و Authenticate شدن کاربر، دسترسی ها را چک کنیم. برای این کار در ASP.NET Core MVC از فیلترها استفاده می کنیم.
در تصویر بالا یک ActionFilter را مشاهده می کنید که IActionFilter را implement کرده است که دارای دو متد مهم OnActionExecuting و OnActionExecuted می باشد. ما بیشتر با OnActionExecuting کار داریم و در داخل آن چک می کنیم که کاربر چه درخواستی داشته است یعنی به چه Controller و Action ای را کاربر می خواهد مشاهده کند. ما این نام های درخواستی کاربر را با لیست دسترسی های کاربر مشاهده می کنیم و در صورت نداشتن دسترسی، View مربوط به عدم دسترسی ها را به کاربر نمایش می دهیم.
سپس باید Filter نوشته شده را به صورت Attribute بالای سر Controller های مورد نظر که می خواهیم دسترسی در آن چک شود قرار دهیم یا اینکه یک Controller با نام BaseController تعریف کنیم و در داخل آن قرار دهیم و سپس Controller ها همگی از BaseController ارث بری داشته باشند.
در ویدئوهای دوره همه این سرفصل ها به صورت کامل همراه با پیاده سازی آموزش داده شده اند. ما در این نوشته ها فقط یک مروری بر مطالب دوره داریم که شما بتوانید یک دید کلی از محتوای دوره داشته باشید.
حالا نوبت به بررسی Cache در ASP.NET Core داشته باشیم
نحوه استفاده از Cache در ASP.NET Core
Cache را زمان هایی استفاده می کنیم که به یک مدل داده، مدام نیاز داریم. مثلا لیست استان ها را برای همه کاربران باید از دیتابیس گرفته و در یک DropDown نمایش دهیم. خوب اینجا بهترین موقعیت برای استفاده از Cache می باشد که لیست استان ها را یکبار از دیتابیس گرفته و داخل حافظه به کمک Cache نگهداری کنیم و دفعات بعدی به راحتی از حافظه خوانده و به کاربر نمایش دهیم.
استفاده صحیح و به موقع از Cache می تواند سرعت نرم افزار شما را بسیار افزایش دهد. ولی نباید برای بهتر شدن سرعت همه داده ها را Cache کنیم چون باعث استفاده خیلی زیاد RAM می شود و نرم افزار شما نیاز به منابع RAM زیادی خواهد داشت. باید داده هایی که مدام استفاده می شوند و زیاد تغییر نمی کنند را Cache کنید.
ما انواع مختلف Cache داریم. مثلا Static Content ها مانند css file یا js file به صورت پیش فرض در مرورگر کاربر Cache می شوند. اگر شما محتوای یک css file را تغییر دهید، روی سیستم کاربر این تغییر لحاظ نمی شود مگر اینکه کاربر Cache مرورگر خود را خالی کند یا اینکه Ctrl + F5 را همزمان فشار دهد.
در ASP.NET Core برای حل این مشکل می توانید روی css file و js file هایی که مدام محتوای آنها در زمان توسعه تغییر میکند، version را فعال کنید تا در هر publish و عرضه نسخه جدید، آدرس این فایل ها نیز تغییر کند تا در مرورگر کاربر مجدد دریافت شوند. در تصویر زیر امکان version را با افزودن asp-append-version="true" مشاهده می کنید.
در این قسمت می خواهیم Cache روی داده ها در ASP.NET Core را با یکدیگر بررسی کنیم. ما در ASP.NET Core از IMemoryCache برای Cache کردن اطلاعات استفاده می کنیم.
در نسخه ASP.NET Core 5 دیگر نیازی نیست که در Startup و ConfigureServices عبارت AddMemoryCache نوشته و register شود. می توانیم به صورت مستقیم و به صورت زیر از امکان IMemoryCache استفاده کنیم.
در کد بالا مشاهده می کنید که ابتدا IMemoryCache از طریق سازنده کلاس تزریق شده و سپس در Action Index یک Cache با نام SAMPLE-DATE نامگذاری شده که مقدار زمان جاری در آن قرار داده شده است. طول عمر cache نیز 10 ثانیه تنظیم شده است. اینجا برای نمونه هست و بیشتر ما داده هایی که از دیتابیس دریافت می کنیم را Cache می کنیم که آن هم به همین روال اتفاق می افتد. در متد GetOrCreate ابتدا چک می کند که با کلید مورد نظر آیا مقداری در Cache وجود دارد یا نه و اگر وجود داشت مقدار را برمی گرداند و اگر مقداری نبود آن را set می کند و سپس برمی گرداند.
یک روش دیگر استفاده از دستور TryGetValue می باشد که به شکل زیر استفاده می شود.
بهتر است که کلیدهای نگهداری مقادیر در Cache را به صورت بالا استفاده نکنیم (“SAMPLE-DATE”) و آنها را در داخل یک کلاس Static تعریف کنیم که بتوانیم براحتی در جاهای مختلف از آن استفاده کنیم و به صورت hard-code نگهداری نکنیم.مانند تصویر زیر :
نحوه نوشتن و خواندن از Cache را مشاهده کردید. حالا در نظر بگیرید در لیستی که Cache کرده اید یک آیتم حذف شده یا مقداری بروزرسانی شده است. باید چطور عمل کنیم؟ دیتا در دیتابیس تغییر کرده ولی همچنان مقدار Cache، مربوط به داده های قبلی می باشد. باید این را خودمان مدیریت کنیم. مثلا در Action Delete که مربوط به حذف آیتم می باشد، باید پس از حذف آیتم از دیتابیس مقدار Cache آن را نیز حذف کنیم تا اگر درخواست جدیدی داشتیم مقادیر جدید از دیتابیس دریافت و مجدد Cache شوند.
براحتی با دستور cache.Remove("SAMPLE-DATE") می توانیم مقدار مورد نظر را از Cache حذف کنیم. مشاهده کردید که کار کردن با Cache پیچیدگی خاصی ندارید و فقط باید ما تشخیص درست و به موقع برای استفاده از Cache داشته باشیم تا بتوانیم سرعت اجرا درخواست ها را افزایش دهیم.
روش دیگر استفاده از ResponseCache می باشد که می توانیم نتیجه اجرای کل یک Action را Cache کنیم که به صورت Attribute استفاده می شود.
تا این بخش نحوه استفاده از IMemoryCache در سطح Controller و Action را مشاهده کردیم. حالا می خواهیم ببینیم که چطور می توانیم از Cache در سطح View استفاده کنیم.
برای استفاده از امکان Cache در سطح View از تگ cache به شکل زیر استفاده می کنیم.
در تصویر بالا یک ViewComponent را به مدت یک ساعت به ازای هر کاربر Cache کرده ایم.
نحوه مدیریت خطاها در ASP.NET Core و نوشتن اطلاعات خطا در Log File :
ما در برنامه نویسی 3 نوع خطا داریم که شامل :
در این بخش بیشتر هدف کنترل و مدیریت Runtime Error ها می باشد. در زمان Runtime Error ها ابتدا یک نمونه از کلاس Exception مربوطه در کد اجرا می شود و سپس اطلاعات مربوط به خطا توسط .NET Core جمع آوری می شود. در نهایت Exception ساخته throw می شود(به هوا پرتاپ می شود). شما Exception را یک ظرف شیشه ای در نظر بگیرید که اگر آن را کنترل نکنید پس از زمین خوردن شکسته و درخواست ارسالی کاربر و عملیات در حال انجام از بین می رود.
به کنترل Exception ها در برنامه نویسی Exception Handling گفته می شود. پس ما باید بتوانیم Exception را Handle کنیم و اگر Handle کردن آن برایمان اهمیتی ندارد، باید نگذاریم اطلاعات خطا به کاربر نمایش داده شود و یک پیغام مناسب به کاربر نمایش دهیم.
هر Exception به همراه خود اطلاعات مهمی دارد که نمایش آن به کاربر می تواند امنیت سیستم ما را کاهش دهد و کدهای برنامه را در دید کاربر که می تواند یک هکر باشد، قرار دهد.
در ASP.NET Core کنترل خطاها و نمایش صفحه مورد نظر در زمان وقوع Exception در فایل Startup و در داخل متد Configure به شکل زیر در نظر گرفته شده است.
در کد بالا مشاهده می کنید که ابتدا در دستور if چک شده که در محیط Development هستیم یا نه. اگر محیط Development بود اطلاعات خطا به صورت کامل نمایش داده شود تا بتوانیم علت و محل وقوع خطا را مشاهده کنیم. ولی اگر محیط Production بود صفحه Error رو از HomeController به کاربر نمایش دهد. پس در نمایش پیام ها فقط کافی است به View مربوط به Error برویم و پیام مناسب فارسی را در آن تایپ کنیم.
حالا دو مسئله مهم دیگر باقی می ماند. اول اینکه چطور در برخی بخش های Exception Handling داشته باشیم و دوم اینکه اطلاعات کامل خطا را در یک Log File ذخیره کنیم که به صورت دوره ای روزانه یکبار یا چندبار فایل لاگ را چک کنیم و از عملکرد صحیح سیستم نرم افزاری خود مطمئن شویم.
برای handle کردن Exception ها از همان روش try-catch استفاده می کنیم و نسبت به خطایی که اتفاق افتاده تصمیم می گیریم که در بخش catch چه کاری انجام دهیم.
برای نوشتن اطلاعات خطا در Log File دو کار می توانیم انجام دهیم.
اول اینکه در روت پروژه یک فولدر Logs ایجاد می کنیم و سپس در فایل web.config که در زمان publish کردن پروژه ایجاد می شود مقدار ویژگی stdOutLogEnabled را true می کنیم. این کار باعث می شود لاگ همه درخواست ها و همه اتفاقات به صورت روزانه یک فایل در پوشه Logs ثبت شود.
این کار باعث می شود که لاگ نوشتن در فایل فعال شود. اما در این حالت ما نمی توانیم به لاگ دسترسی مستقیم داشته باشیم و در داخل کدهای خود در زمان مورد نیاز به فایل لاگ چیزی اضافه کنیم. مثلا فلان کد با فلان مقادیر توسط فلان کاربر در چه زمانی فراخوانی شد.
برای این کار نیاز است که یک nuget package را به صورت dotnet add package Serilog.Filters.File نصب کنیم. البته پکیج های دیگری هم باید از serilog نصب کنیم.
سپس برای نوشتن در فایل باید در فایل appsettings.json کانفیگ مربوط را مانند تصویر زیر اضافه کنیم.
می توانید در صورت نیاز لاگ مربوط به Serilog را به جای فایل در دیتابیس بنویسید که همین کانفیگ تصویر بالا به جای فایل باید به دیتابیس و ConnectionString تغییر کند.
این هم از Exception Handling و نحوه نوشتن Log ها در ASP.NET Core که مشاهده کردید.
حالا می خواهیم با SignalR و کاربرد آن در ASP.NET Core آشنا شویم.
SignalR چیست و چه کاربردی دارد ؟
کتابخانه ای برای اطلاع رسانی اتفاقات از سمت Server به Client که با عنوان Push Notification شناخته می شود.
برای مثال شما یک سایت طراحی کرده اید. داده های این سایت مدام در حال تغییر است مانند نرخ ارز یا طلا. دو روش برای پیاده سازی این مدل از سایت ها دارید. اول اینکه مثلا هر 5 ثانیه یکبار صفحات خود به خود Refresh شوند و راه حل دوم اینکه اگر قیمت ها تغییر کردند به کاربران اطلاع بدهد.
یک مثال دیگر را بررسی کنیم. یک نرم افزار چت باید بنویسید. برای اینکه چک کنید برای کاربر پیام جدیدی ارسال شده است باید یا براساس یک Timer مثلا یک ثانیه ای مدام درخواستی به سمت سرور ارسال کنید که آیا برای کاربر پیام جدیدی ارسال شده است و یا از روش دوم که Push Notification می باشد استفاده کنید و در صورت دریافت پیام جدید برای کاربر، سرور به کاربر خاص پیام را ارسال کند.
اگر به روش Timer عمل کنیم سرور ما همیشه زیر بار درخواست های پی در پی از سمت کاربرها می باشد که شاید 99 درصد آنها بی مورد باشد و اتفاق جدیدی رخ نداده باشد. ولی استفاده از Push Notification باعث می شود فقط در زمان رخ دادن اتفاقی که نیاز به اطلاع رسانی برای کاربر دارد، برای کاربر خاص یا گروهی از کاربران یا همه کاربران یک پیام از سمت سرور به سمت کلاینت ارسال شود.
در ASP.NET Core عملیات Push Notification از طریق SignalR انجام می شود. به صورت پیش فرض SignalR در پروژه نصب شده می باشد و می توانیم براحتی از آن استفاده کنیم.
در SignalR ما باید ابتدا در فایل Startup.cs در متدهای ConfigureServices و Configure کانفیگ هایی را انجام دهیم. سپس باید یک فایل Hub مثلا ChatHub بسازیم که وظیفه دریافت و ارسال پیام ها را برعهده دارد را بسازیم و این Hub ساخته شده را در Configure، کانفیگ کنیم.
در سمت Client که می تواند MVC یا React یا Angular باشد باید library مربوطه را نصب کنیم و کدهای جاوا اسکریپت مربوط به ارسال و دریافت پیام ها از طریق SignalR را اضافه کنیم. در این لینک می توانید مرحله به مرحله را مشاهده و در پروژه خود انجام دهید.
استفاده درست از SignalR در پروژه ها می تواند هم کیفیت پروژه شما را افزایش دهد و هم اینکه بار و درخواست اضافه به سرور شما تحمیل نکند.
از SignalR برای پروژه هایی شامل GPS، مانیتورینگ، چت، نرم افزارهای آموزش آنلاین، بازی های آنلاین و مواردی که نیاز به تعامل پی در پی داریم استفاده می شود.
حالا می خواهیم یک بخش خیلی مهم را با هم بررسی کنیم.
Web API چیست و چطور در ASP.NET Core یک پروژه Web API ایجاد کنیم ؟
یکی از پراستفاده ترین نوع پروژه هایی که در حال ایجاد و توسعه در تیم های نرم افزاری می باشد. این روزها خیلی هامون با Web API سرکار داریم. یا API می نویسیم و به دیگران می دهیم و یا از API های نوشته شده دیگران استفاده می کنیم.
Web API در راستای وب سرویس و برای تعامل سیستم های نرم افزاری با یکدیگر ارائه شد. دیگر شاید کسی نباشد که با WebService ها یا همان asmx ها سرویس جدید بنویسد و اگر سرویسی هنوز روی asmx وجود دارد از قبل نوشته شده و بازنویسی نشده است.
در Web API تبادل داده براساس فرمت JSON می باشد و ما بر روی بستر http سرویس خود را عرضه می کنیم. سرویس ها در یک آدرس endpoint عرضه می شوند و دیگران براحتی می توانند بدون نیاز به Register کردن یا افزودن سرویس به Application خود، api مربوطه را فراخوانی و از آن استفاده کنند.
نوع احراز هویت در اکثر API ها به صورت Token Authentication می باشد.
ما می خواهیم بعد از این تعاریف بدانیم به چه شکل پروژه از نوع ASP.NET Core Web API ایجاد کنیم و آن را توسعه دهیم.
برای ایجاد پروژه از نوع Web API در VS Code و به کمک dotnet CLI ابتدا یک فولدر به نام پروژه خود ایجاد کنید. سپس CMD را در مسیر فولدر ایجاد شده باز کنید. حالا فقط کافی است دستور dotnet new webapi را نوشته و اجرا کنید.
پس از ایجاد پروژه می توانید فولدر پروژه را با VS Code باز کنید تا ساختار پروژه Web API را با یکدیگر بررسی کنیم.
ابتدا اینکه پوشه ای با نام Views دیگر نداریم و فقط پوشه Controllers را دارم که صورت نیاز پوشه Models نیز ساخته می شود.
در فایل Startup تغییراتی داریم که هم در متد ConfigureServices و هم در متد Configure این تغییرات وجود دارد.
کدهای مربوط به متد ConfigureServices را در تصویر زیر مشاهده می کنید.
که به صورت پیش فرض مشاهده می کنید که Swagger به پروژه های ASP.NET Core Web API افزوده شده است که برای بحث داکومنت کردن و تست web api ها استفاده می شود.
در تابع Configure هم تغییراتی را داریم که در تصویر زیر مشاهده می کنید.
افزوده شدن کانفیگ های مربوط به Swagger را مشاهده می کنید و دوم اینکه در قسمت useEndpoints دیگر Pattern پیش فرض تعریف شده نداریم.
حالا کدهای مربوط به یک Controller از نوع Web API را با هم بررسی کنیم.
در خط تعریف Controller شما دو Attribute مشاهده می کنید. اولی ApiController که نشان می دهد این یک ApiController است و دومی یک Attribute Route که تعریف شده است. در نهایت هم مشاهده می کنید که Contoller از یک کلاس ControllerBase ارث بری کرده است.
تفاوت دوم در Action ها می باشد. بالای سر تمام Action ها با HttpVerb Attribute ها نوشته شود که شامل HttpGet، HttpPost، HttpPut و HttpDelete می باشد که کاربرد Attribute Routing هم می تواند داشته باشد.
خروجی Action همان IActionResult می باشد و در return از تابع Ok بر برگرداندن مقادیر و Model ها استفاده می کنیم. پس در Web API تغییر خیلی زیادی نسبت به MVC Controller نداریم. نکته مهم در نوشته Action های Web API این است که بر پایه معماری Restful نوشته شده باشد. در این معماری ما در درخواست های ارسالی نام Action ها را درگیر نمی کنیم و از روی Request Method آنها در سمت Controller تشخیص داده می شود که با کدام Action کار داریم. مثلا DevTube.ir/Products/1 یعنی با Action Get مربوط به برگرداندن اطلاعات یک Product کار داریم.
با اجرای پروژه با دستور dotnet run از طریق Terminal و تایپ عبارت Swagger در انتهای آدرس، صفحه زیر را مشاهده خواهید کرد.
این صفحه همان Swagger است که برای معرفی و تست api به صورت پیش فرض در پروژه های ASP.NET Core ورژن جدید گذاشته شده است. هر Contoller و هر Action دیگری که به پروژه اضافه کنیم در این صفحه نیز افزوده خواهد شد.
ما همانند MVC می توانیم از Dapper یا EF Core برای وصل شدن به دیتابیس استفاده کنیم و کارهای خود را انجام دهیم.
تفاوت اصلی در بخش Authentication می باشد که به جای استفاده از Cookie Authentication از Token Authentication استفاده می کنیم.
در Cookie Authentication به ازای هر Cookie مقداری در سمت Server و به صورت Session نگهداری می شود. خود Cookie هم در سمت Client در مرورگر کاربر ذخیره می شود.
در Token Authentication که حالت State Less می باشد به صورت پیش فرض در سمت سرور هیچ چیزی از Token نگهداری نمی شود و در سمت کلاینت باید به صورت دستی و در صورت نیاز Token ذخیره شود.
در WebAPI ها ما از Token Authentication برای احراز هویت کاربر استفاده می کنیم.
Token چه ویژگی هایی دارد ؟
Token یک عبارت Decode شده است که دارای یک expire time می باشد که قابلیت تمدید ندارد و با تمام شدن طول عمر، Token دیگر Valid نمی باشد.
Token به همراه خود می تواند یک سری اطلاعات داشته باشد که به این اطلاعات Claims گفته می شود که می توانیم اطلاعات مورد نیاز مانند نام کاربر، نقش کاربر و دیگر اطلاعات پرکاربرد را نگهداری کنیم.
برای شروع ابتدا باید در متد ConfigureServices ویژگی AddAuthentication را به صورت زیر بنویسید و مقدار دهی کنید.
برای ساخت Token ها نیاز به یک کلید وجود دارد که آن را در appsettings.json قرار می دهیم.
پس از این کار باید در متد Configure هم ویژگی useAuthentication را قبل از useAuthorization اضافه کنید.
حالا باید یک Controller مثلا با نام AuthenticateController ایجاد کنیم که دارای یک متد برای Login کردن و در اصل Authenticate شدن و دریافت Token داشته باشد.
سپس در داخل این Controller یک Action با نام Post داریم که از سمت استفاده کننده فراخوانی میشود و نام کاربری و رمز عبور را گرفته و بررسی می کنیم و در نهایت اگر اطلاعات درست بود یک Token ایجاد شده و به سمت درخواست دهنده ارسال می شود.
سپس درخواست دهنده باید مقدار Token را در درخواست های بعدی به سمت سرور از طریق Request Headers و با ویژگی Authorizaton به صورت Authorization: “bearer token” ارسال کند. مقدار bearer ثابت است و نشان دهنده فرمت و استاندارد مورد استفاده در ساخت توکن می باشد و مقدار token هم باید همان مقدار token دریافتی از سرور باشد که در همه Request ها باید به سمت سرور ارسال شود.
در Web API یک محدودیت مهم و اذیت کننده داریم که شاید شما هم با آن درگیر شده باشید. Cross Allow Origin که به صورت پیش فرض فقط می تواند api را از آدرسی که در آن عرضه شده فراخوانی کرد. به طور مثال ما نمی توانیم به صورت پیش فرض از دامنه Derambakht.com یک api را از روی دامنه DevTube.ir فراخوانی کنیم. اگر فراخوانی کنیم خطای Cross Allow Origin دریافت می کنیم.
فعال سازی Cors در ASP.NET Core Web API :
برای فعال سازی و امکان فراخوانی api ها از آدرس یا آدرس های دیگر باید ابتدا دو کانفیگ در فایل Startup داشته باشیم. ابتدا باید کد زیر را در متد ConfigureServices اضافه کنیم.
توسط کد بالا ابتدا یک نام برای Policy خود انتخاب می کنیم، چون باید در بخش های دیگر از این نام استفاده کنیم. سپس در بخش builder می توانیم فقط به دامنه، یا درخواست یا درخواست روی متدهای خاصی دسترسی بدهیم. مقدار ستاره یا * یعنی همه بتوانند api ما را فراخوانی کنند که این برای api هایی که عمومی نیستند تنظیم خوبی نمی باشد و بهتر است فقط آدرس دامنه یا IP مورد نظر ثبت شد.
پس از این بخش باید در متد Configure نیز قطعه کد زیر را با نام Policy وارد شده بنویسیم.
به کمک UseCors مشخص می کنیم که با چه ویژگی هایی که در بخش بالا مشخص کردیم، اجازه استفاده داشته باشند.
کار تمام نشده است. باید یک Attribute با نام EnableCors هم در بالای سر Controller هایی که می خواهیم از آدرس دیگری قابل فراخوانی باشند، قرار می دهیم.
من این Attribute را در BaseController قرار داده ام که نیاز نباشد که بالای سر هر Controller تکرار کنم و Controller ها از BaseController ارث بری می کنند.
این هم از بحث Cross Allow Origin که باید برای api های خود حتما انجام دهید.
پیاده سازی Token Auth و Refresh Token
تا این جای کار توانستیم Web APIبنویسم و مشکل Cross Allow Origin رو هم حل کنیم. حالا می خواهیم یاد بگیریم که چطور Authentication و احراز هویت کاربران را در Web API ها انجام دهیم.
ما در MVC از Cookie Authentication برای احراز هویت استفاده می کردیم. کوکی ها روی مرورگر کاربر ذخیره می شدند و در هر Request به سمت سرور ارسال می شدند و هویت کاربر به کمک این کوکی ها سنجیده میشد.
اما در Web API امکان استفاده از Cookie Authentication نمی باشد چون Web API امکان دارد توسط یک نرم افزار موبایل مثلا Android فراخوانی شود که در آن Cookie معنی ندارد و امکان استفاده از آن وجود ندارد.
به همین دلیل که به آن Stateless نیز گفته می شود از Token ها در احراز هویت Web API ها استفاده می شود. ساز و کار به این شکل است که ما در ابتدا به عنوان مصرف کننده Web API یک سرویس Authentication را با نام کاربری و رمز عبور وارد شده توسط کاربر فراخوانی می کنیم و در صورت صحیح بودن اطلاعات یک Token که دارای زمان مصرف ثابت یا همان ExpireTime است تولید شده و در Response به سمت ما ارسال می شود. حالا باید این Token را در جایی ذخیره کنیم و در درخواست های بعدی که نیاز به Authenticate شدن دارند در Request Headers با ویژگی Authorization ارسال کنیم. در سمت Web API توکن ارسالی در Request Header چک می شود که آیا توکن صحیحی از نظر فرمت و زمان می باشد یا نه ؟
اگر درست بود که درخواست شما پاسخ داده می شود و در غیر این خطای 401 با عنوان Unauthorized در پاسخ به درخواست شما برگردانده می شود. اگر فرمت توکن صحیح نباشد یا زمان آن گذشته باشد یا حتی اگر توکنی ارسال نشود باز همین خطا را دریافت خواهید کرد.
روند کار در Token Auth به چه شکلی می باشد؟
نحوه راه اندازی Token Auth روی Web API :
var secretKey = Configuration.GetValue<string>("TokenKey");
var tokenTimeOut = Configuration.GetValue<int>("TokenTimeOut");
var key = Encoding.UTF8.GetBytes(secretKey);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
//برای کنترل زمان توکن
ClockSkew = TimeSpan.FromMinutes(tokenTimeOut),
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
"TokenKey": "THIS OK ABCD OL TEST AND AERIFY ABC AAKENS, REPLACE IT WITH YOUN PLK SECRET, IT CAN BE ANY STRING",
"TokenTimeOut": "1",
app.UseAuthentication();
private string GenerateNewToken(Guid userId)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(_configuration.GetValue<string>("TokenKey"));
var tokenTimeOut = _configuration.GetValue<int>("TokenTimeOut");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("userGuid", userId.ToString()),
}),
Expires = DateTime.UtcNow.AddMinutes(tokenTimeOut),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
[HttpPost]
public async Task<IActionResult> Post(LoginViewModel model)
{
//1-check username & password
//2-generate new token
var userId = Guid.NewGuid();
var fullName = "Mohsen Derambakht";
var token = GenerateNewToken(userId);
var info = new AuthenticateViewModel
{
FullName = fullName,
UserId = userId,
Token = token
};
return Ok(info);
}
به کمک مراحل بالا ما در پروژه خود Token Authentication را داریم. ولی یک مشکل بزرگ در Token Authentication داریم که باید فکری برای آن داشته باشیم.
مشکل ثابت بودن طول عمر Token :
برخلاف Cookie که با هر بار ارسال درخواست جدید طول عمر آن Reset می شود و از ابتدا آغاز می شود، Token همچین ویژگی ندارد. یعنی اگر صدبار هم درخواست به سمت سرور ارسال کنیم طول عمر Token ما به خودی خود تغییری نمی کند و مثلا بعد از 5 دقیقه اعتبار خود را از دست می دهد.
حالا برای حل این مشکل راه حل های مختلفی وجود دارد که با هم بررسی می کنیم :
استفاده از Refresh Token : باعث می شود که در تولید توکن جدید نیازی به ارسال نام کاربری و رمز عبور کاربر نباشد و به کمک Refresh Token در صورتیکه خود Refresh Token همچنان Valid باشد، توکن جدید تولید و به سمت درخواست دهنده ارسال شود.
Refresh Token یک کد غیرتکرای مثلا یک GUID می باشد که همراه با User Id در یک جدول داخل دیتابیس نگهداری می شود. در زمان Authenticate کردن به کمک نام کاربری و رمز عبور، یک Token و یک Refresh Token تولید می شود. ما Refresh Token را به همراه User Id و زمان تولید Token در دیتابیس نگهداری می کنیم.
حالا کاربر به کار خود ادامه می دهد. در زمانی که Token اصلی زمانش تمام شد و کاربر خطای 401 دریافت کرد، باید api مربوط به صدور Token جدید از روی Refresh Token را فراخوانی کند و یک جفت توکن جدید دریافت کند بدون اینکه نیازی به ارسال نام کاربری و رمز عبور باشد.
در زمانی نیاز به ارسال نام کاربری و رمز عبور می باشد که طول عمر Refresh Token هم به اتمام رسیده باشد و در این حالت باید نام کاربری و رمز عبور مجدد ارسال شود.
همه این بخش ها در دوره پیاده سازی شده اند و مرحله به مرحله کد آنها نوشته شده و اجرا شده است.
در این آموزش ASP.NET Core 5 آموزش داده شده است.
در این دوره آموزش ASP.NET Core 5 همه بخش های به صورت مفصل و به همراه پیاده سازی آموزش داده شده است.
ASP.NET Core یکی از بهترین روش های تولید نرم افزار در شرکت های ایرانی می باشد و به همین دلیل بازار کار آن همیشه خوب و جذب نیرو در آن زیاد می باشد.
بله در این دوره به صورت کامل Web API به همراه Token Authentication آموزش داده شده است.
دو فصل اول دوره ASP.NET Core رایگان می باشد و شما می توانید با تماشای این دو فصل از کیفیت و نحوه تدریس مدرس دوره مطمئن شده و سپس دوره را تهیه کنید.
مروری بر مطالب ارائه شده در دوره ASP.NET Core تا ابتدای فصل پانزدهم.