
آموزش ASP.NET Core مقدماتی
در این آموزش، اولین قسمت از مجموعه آموزش ASP.NET Core را برای برنامهنویسان آغاز میکنیم.
این آموزش برای برنامهنویسانی است که فناوریهای تحت وب موجود Microsoft را میشناسند (مثل ASP.NET Web Forms، ASP.NET MVC، ASP.NET Web API و غیره) اما قصد دارند که ASP.NET Core جدید را از پایه یاد بگیرند.
در اینجا دربارهی مفاهیم پایه و ابتدایی صحبت خواهیم کرد و در ادامهی مطلب یادگیری ASP.Net Core، به مفاهیم کاربردیتر خواهیم پرداخت.
شما میتوانید سرفصل مدنظر خود برای یادگیری را از فهرست محتوای این مقاله انتخاب کنید تا به قسمت مربوطه هدایت شوید.
آموزش ASP.NET Core – از صفر تا صد یاد بگیرید!
ASP.NET Core 1.0 یا ASP.NET 5 – MVC6 نسخهی بازنویسیشدهی ASP.NET 4.6 با ویژگیهای کلیدی زیر است:
- ASP.NET Core متنباز است.
- فریمورکی چند پلتفرمی (کراسپلتفرم (Cross-Platform)) است، یعنی در لینوکس و MacOs نیز اجرا میشود. پیش از این فریمورک.NET (به صورت جامع) تنها قابلیت استفاده روی پلتفرم ویندوز را داشت. این ویژگی بهبودی بزرگ است.
- برای نوشتن اپلیکیشنهای تحت وب، Iot appها و بکاندِ برنامههای موبایل (mobile back-end) مناسب است.
- کانفیگریشن Cloud ready
- ASP.NET Core 1.0 اندازهی کوچکتری در مقایسه با فریمورک ASP.NET 4.6 دارد، چون روی نسخهی کوچکتر شدهی فریمورک.NET اجرا میشود (به عبارت دیگر .NET Core 1.0).
با دیدگاهی کلیتر، باید عنوان کنیم که:
- ASP.NET 5 به ASP.NET Core 1.0 تغییر نام داده است.
- .NET Framework 5 با نام.NET Core 1.0 شناخته خواهد شد.
- Entity Famework 7 به Entity Famework Core 1.0 تغییر نام خواهد داد.
مقایسهی ASP.NET Core و .NET Framework
همانطور که در تصویر زیر مشخص است، .NET Core تعدادی API مشترک با فریمورک .NET قبلی دارد.
تفاوتهای فریمورک .NET و .NET Core:
.NET Core | فریمورک .NET | |
مناسب برای اپلیکیشن |
|
|
میکروسرویسها | از میکروسرویسها پشتیبانی میکند. | از میکروسرویسها پشتیبانی نمیکند. |
داکر کانتینرها | از deployment در داکر کانتینرها پشتیبانی میکند. | از deployment در داکر کانتینرها پشتیبانی نمیکند. |
انجمن و منحنی یادگیری | یک فناوری نوپاست، به همین دلیل انجمن آن هنوز در حال رشد است و از انجمن فریمورک .NET کوچکتر است. در نتیجه، منحنی یادگیری آن بسیار بزرگ است و یادگیری آن زمان بیشتری میبرد. | به عنوان یک فناوری نسبتاً قدیمیتر، انجمن بزرگی دارد و منحنی یادگیری آن کوچک است. |
Deployment | Deployment از روشهای قبلی راحتتر است. | Deployment زمانبر است. |
تصویر زیر، معماری اکوسیستم Microsoft را نشان میدهد:
تفاوت اصلی .NET Core و فریمورک .NET این است که .NET Core جدید کراسپلتفرم است و به همین دلیل .NET Core فناوریای است که در آینده از آن استفاده خواهد شد.
دورههای مرتبط در فرانش
ویژگیهای کلیدی ASP.NET 5 یا ASP.NET Core 1.0:
پشتیبانی از کراسپلتفرم:
.NET Core یک فریمورک تحت وب کراسپلتفرم است که از ماژولاریتی بیشتری برخوردار است و به صورت بهینهتر از منابع ابری استفاده میکند. میتوان از آن برای نوشتن development stack ماژولار و اجرای آن در ویندوز، لینوکس و مَک استفاده کرد.
کتابخانهها ماژولار هستند و از طریق NuGet Package توزیع شدهاند. این فریمورک بهمنظور توسعهی اپلیکیشنهای تحت وب طراحی شده است که بتوان آنها را در یک سامانهی ابری مستقر کرد (deploy). کتابخانههای آن استاندارد هستند که تخصیص منابع و مصرف حافظهی کل سیستم را به حداقل میرسانند.
متنباز (Open Source)
.NET Core کاملاً متنباز است. انجمن، با همراهی Microsoft، آن را تولید کرده است. علاوه بر سورسکد (Source Code)، اسناد (Documentation) آن نیز متنباز هستند. سورسکد در github و اسناد در docs.asp.net قرار دارند.
برنامهنویسان میتوانند آنها را دانلود و بررسی کنند. تغییرشان بدهند و بهترشان کنند. هر تغییر مثبتی را، که به عنوان یک عضو انجمن .NET Core انجام میدهید، میتوانید برای تأیید به Microsoft بفرستید.
کارایی
کارایی همیشه یکی از مشکلات.NET بود. برای رفع این مشکل، شرکت Microsoft،manages web server جدیدی را به نام ‘kestrel’ در .NET Core معرفی کرد. این وبسرور (Web Server) به زبان c# نوشته شده و از پایه طراحی شده است تا سریعترین سرور موجود .NET باشد.
به این ترتیب این شرکت در رسیدن به هدف “کارایی بهتر” موفق عمل کرده است. در تصویر زیر مقایسهای از .NET Core با سایر فناوریها آورده شده است. همانطور که میبینید، .NET Core در بالای لیست قرار دارد.
Dependency Injection توکار:
Dependency Injection تکنیکی است که از آن برای رسیدن به loose coupling (اتصال سست) بین اشیاء و dependencyهایشان استفاده میشود. با استفاده از DI، میتوانیم بدون دانستن جزئیات زیادی از یک شئ، از آن در کنار سرویسهای دیگر استفاده کنیم.
حالا Dependency Injection با عنوان Dependency Injection service container و با حداقل امکانات به صورت توکار در فریمورک .NET Core قرار دارد.
تنها یک مدل برنامهنویسی برای MVC و Web API:
Microsoft با حذف همپوشانی موجود بین Web API و ASP.NET MVC، آنها را در یک فریمورک برنامهنویسی جمع کرده است. این فریمورک واحد، با معرفی یک namespace منحصر به فرد تحت عنوان Microsoft.AspNet.Mvc فرایند برنامهنویسی را آسانتر کرده است.
همچنین استفاده از فریمورکهای سمت کلاینت مانند Grunt/Bower و اضافه کردن cross-cutting concernها با controller راحتتر شده است.
ماژولاریتی:
وقتی روی پروژههای بسیار بزرگ کار میکنید، نگهداری کد نیز با بزرگتر شدن پروژه سختتر میشود. بنابراین، برنامهنویسی مبتنی بر پکیج (Package) نگهداری و بهروزرسانی پروژه را سادهتر میکند.
در حال حاضر، NuGet Package استاندارد پیشفرض برای افزودن عملکردهای جدید به اپلیکیشنهای .NET Core است. این عملکردها شامل افزودن فریمورکها، کتابخانهها و حتی ویژگیهای ASP.NET میشوند.
دورههای مرتبط در فرانش
Project.json:
در پروژههای .NET Core از فایل Project.json برای تعریف متادیتا (metadata)، اطلاعات کامپایل (compilation information) و dependencyها استفاده میشود.
در زیر برخی از propertyهای مهم Project.json آورده شده است:
نام | توضیحات | مثال |
name | نام پکیج است که در assembly name استفاده میشود. نوع داده رشته (string) است. | { “name”: “WebDevDemo” } |
version | نوع داده رشته (string) است. در NuGet package از آن استفاده میشود. | { “version”: “1.0.0-*” } |
description | برای داشتن توضیحات بیشتری دربارهی پروژه در assembly از آن استفاده میشود. | { “description”: “A Demo for my ASP.NET Core Project”} |
copyright | از این نیز در propertyهای assembly استفاده میشود. برای ثبت اطلاعات کپیرایت پروژه از آن استفاده میشود. | { “copyright” : “WebDevTutorial 2017” } |
title | اگر از property “name” استفاده شود، امکان استفاده از این property وجود ندارد. عنوان پروژه را مشخص میکند. | { “title” : “My Library” } |
entryPoint | متد آغازین در اجرای برنامه است (entrypoint method). این متد به صورت پیشفرض متد main برنامه است. | { “entryPoint” : “ADifferentMethod” } |
testRunner | Test Runner آن NUnit یا xUnit است. نوع دادهای testRunner رشته (string) است. | {“testRunner”: “NUnit”} |
authors | نوع دادهای authors به صورت string[] است. Authors، آرایهای از رشتهها در برنامه است. | {“authors”: [“Muhammad Ahmad”]} |
Appsettings.json:
در NET Core، به جای web.config از Appsettings.json برای نگهداری تمامی تنظیمات استفاده میشود. این تنظیمات شامل connection stringها، تنظیمات عمومی اپلیکیشن، اطلاعات logging و غیره میشوند. همچنین به جای فرمت XML، از فرمت JSON استفاده میشود.
قبلاً، تنظیمات را در فایل web.config با فرمت XML به صورت زیر نگه میداشتیم:
<appSettings> <add key="Logging-IncludeScopes" value="false" /> <add key="Logging-Level-Default" value="verbose" /> <add key="Logging-Level-System" value="Information" /> <add key="Logging-Level-Microsoft" value="Information" /> </appSettings>
حالا، فایل JSON زیر به صورت Appsettings.json جای آن را خواهد گرفت:
"Logging":{ "IncludeScopes": false, "LogLevel":{ "Default": "Verbose", "System": "Information", "Microsoft": "Information" } }
Startup.cs:
فایل Startup.cs اساساً جایگزینی برای فایل Global.asax در ASP.NET Core است. هر اپلیکیشن ASP.NET Core به یک کلاس Startup نیاز دارد اما این مسئله میتواند در محیطهای مختلف فرق داشته باشد. Startup.cs مناسب با محیط در زمان اجرا انتخاب میشود.
وقتی اپلیکشین شروع به اجرا کرد، متدهای زیر را فراخوانی میکند:
- متد اختیاری ConfigureServices برای افزودن سرویسهای فریمورک:
public void ConfigureServices(IServiceCollection services) { //Add framework services. services.AddMvc(); //Add more services. ..... }
متد Configure برای افزودن سرویسها به کانتینر (Container):
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { }
نگاهی به فایل کامل Startup.cs زیر بندازید:
public class Startup { public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; } // This method gets called by the runtime. // Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); // Add More services. //.... } // This method gets called by the runtime. // Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } }
Grunt، Gulp و Bower
Grunt و Gulp دو Task Runner برای جاوا اسکریپت (Javascript) هستند. Bower یکWeb Package Manager (ابزار مدیریت پکیجهای وب) است.
Grunt:
- یک Task Runner برای جاوا اسکریپت است.
- از آن برای خودکار کردن وظایفی مانند Bundling و Minification در فایلهای جاوا اسکریپت و CSS استفاده میشود.
- با استفاده از مدیر پروژههای نود (Node Project Manager (NMP)) میتوانیم آن را با دستور زیر نصب کنیم:
npm install grunt -g
- میتوانیم عمل کانفیگریشن آن را با نام Gruntfile.js (که نباید عوض شود)، با ASP.NET Core انجام دهیم.
Gulp:
- این هم یک Task Runner برای جاوا اسکریپت است.
- عملیاتها (operation) باید در فایلی با نام Gulpfile.js تعریف شوند.
- گالپ دیگر انتخاب پیشفرض اپلیکیشنهای ASP.NET Core نیست، چون به جای آن از BuilderMinifier استفاده میشود.
- باید با استفاده از دستور زیر، گالپ را به صورت سراسری نصب کرد:
npm install gulp -g
Bower:
- از Bower برای مدیریت پکیجهای front–end در اپلیکیشنهای ASP.NET Core استفاده میشود.
- باید با استفاده از دستور زیر Bower را نصب کنیم:
npm install browser -g
MVC Tag Helperها:
Tag Helperها روشی برای افزایش عملکرد HTML در موتور نمایش Razor (Razor View engine) هستند. با کمک Tag Helperها، عملکردهای مختلفی به Razor اضافه میشود که کار برنامهنویسی را سادهتر میکند.
آنها تنها سینتکس (syntax) را تغییر نمیدهند، بلکه خوانایی فرمهای Razor (Razor Form را نیز افزایش میدهند.
کد سادهی زیر را در نظر بگیرید که از HTML Helper استفاده کرده است.
@Html.ActionLink("Back Home", "Index", "Home")
خروجی HTML کد بالا به صورت زیر است:
<a href="/">Back Home</a>
حالا میتوانیم همین کار را به صورت زیر با استفاده از Tag Helper انجام دهیم:
<a asp-action="Index" asp-controller="Home">Back Home</a>
اگر سینتکس HTML Helper را با Tag Helper مقایسه کنید، میبینید که بیشک برنامه نویسها، طراحان وب و توسعهدهندگان فرانت-اند (Front-End) راحتتر میتوانند Tag Helper را بخوانند (چون دیگر لازم نیست کد c# را بفهمند).
مثالهای کاربردیتر استفاده از Tag Helper را بهجای HTML Helper در زیر میبینید:
@Html.LabelFor(m => m.StudentName, new { @class = "control-label" }) @Html.TextBoxFor(m => m.StudentName, new { @class = "form-control" })
سینتکس سادهتر شدهی Tag Helper به صورت زیر است:
<label asp-for="StudentName" class="control-label" /> <input asp-for="StudentName" class="form-control" />
فرایند راهاندازی ASP.NET Core:
- Startup.cs یک نقطهی شروع برای اجرای برنامه برای اپلیکیشن ارائه میکند.
- میتوانیم کلاسهای Startup مختلفی را برای محیطهای مختلف تعریف کنیم.
- سازندهی (Constructor) کلاس Startup، dependencyهای inject شده با استفاده از dependency injection را میپذیرد.
- با فراخوانی متد Startup() که درون متد Main اپلیکیشن (Program.Main()) قرار دارد، کلاس Startup فراخوانی میشود. این متد همچنین مسئول کانفیگر کردن سرویسهایی است که در اپلیکیشن مشخص شدهاند.
- متد Startup() همچنین اپلیکیشن را راهاندازی میکند. وقتی کلاس Startup مقداردهی اولیه و راهاندازی میشود، ConfigurationBuilder تنظیمات اپلیکیشن را از appsettings برمیدارد.
- وقتی ConfigurationBuilder تمامی کانفیگریشنهای لازم را بیلد (Build) کرد، متد ConfigureServices() فراخوانی میشود. این متد به سرویسها اجازه میدهد قبل از کانفیگریشن، از کانتینر dependency injection، resolve و ساخته شوند.
- متد ConfigureServices() به کانتینر سرویس اپلیکیشن (Application Service Container) سرویس اضافه میکند.
- سپس متد Configure() فراخوانی میشود. در اینجا تنظیمات اپلیکیشن اعمال میشوند و کامپوننتهای middlware در پایپلاین مدیریتکنندهی درخواستهای اپلیکیشن (Application Request handler Pipeline) رجیستر (Register) میشوند.
- از متد Configure() استفاده میشود تا مشخص شود که اپلیکیشنASP.NET چگونه به تکتک درخواستهای HTML (HTML Request) در قالب middleware پاسخ خواهد داد.
- middlewareها در ASP.NET Core از متدهای extension در IApplicationBuilder ، ساخته میشوند و به برنامهنویسان اجازهی دسترسی مستقیم را به درخواستهای HTML میدهند. *Action* middleware درخواستها و پاسخها را مدیریت میکند و درخواست را برای انجام actionهای آتی به کامپوننت بعدی در پایپلاین میدهد. بهعلاوه، از delegateهای Run and Map Middleware در سناریوهای غیرمعمولتر استفاده میشود. این delegateها پایپلاین درخواستها را terminate یا branch میکنند.
- سرویسهای دیگر مانند IHostingEnvironment و ILoggerFactory نیز ممکن است کانفیگر شوند. این سرویسها در متد ConfigureServices راهاندازی میشوند.

مدل کانفیگریشن جدید در ASP.NET Core 1.x.. کانفیگریشن جدید چه تفاوتی با روش قبلی دارد؟
بیایید در ادامهی این آموزش ASP.NET Core.، مدل جدید کانفیگریشن و تفاوتهایش را با مدل قبلی بررسی کنیم.
روش قدیمی کانفیگریشن:
کانفیگریشن به صورت زیر و در فایل web.config انجام میشد. این فایل در appsettings داشت:
<configuration> <appSettings> <add key="ApplicationName" value="Library" /> </appSettings> </configuration>
کانفیگریشن جدید در ASP.NET Core:
کانفیگریشنهای مختلفی به صورت زیر ارائه شدهاند:
- فرمتهای فایل (File Formats)- میتوانیم کانفیگریشنها را در فایل INI، JSON یا XML بیاوریم.
برای مثال، در زیر یک فایل json را میبینید که کاربر میتواند در آن configuration key را برای settings با هر فرمتی که سند json از آن پشتیبانی میکند، تعریف کند. مثلاً فرمت رشته (String)، آرایه (Array)، شئ (Object)، تاریخ (Date) و غیره.
{ "key1": " key1.value1 ", // string "key2": 2, //number "datekey": { "datOfBith": "2015-10-12" //date }, "students": [ //array object { "Name": "John", "class": "IX" }, { "Name": "Smith", "class": "X" } ] }
برای دسترسی به فایل json:
public class Startup { public Startup(IHostingEnvironment env) { // Set up configuration sources. var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; set; } public void ConfigureServices(IServiceCollection services) { // Adds services required for using options. services.AddOptions(); // Register the IConfiguration instance which AppOptions binds against. services.Configure<AppOptions>(Configuration); // Add framework services. services.AddMvc(); } }
فایل json باید قوانین نامگذاری (naming convention) را به صورت زیر رعایت کند:
-
- json
- appsetting.<EnvironmentName>.json
- آرگومانهای دستوری
مثال زیر نمونهای از استفاده از دستورات برای کانفیگریشن است:
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Configuration; var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .AddCommandLine(args) .Build();
آرگومانهای لازم برای کانفیگریشن دستوری
آرگومانهای کانفیگریشن دستوری باید به شکل یکی از فرمتهای نشاندادهشده در جدول زیر باشند. اگرچه، مقدار آنها میتواند null باشد.
فرمت آرگومان | مثال |
یک متغیر key و value آن که با یک = از هم جدا شدهاند. | key=value |
یک متغیر key و value آن که با فاصله (space) از هم جدا شدهاند. | /key value |
متغیر key میتواند پیشوند داشته باشد، مثلاً –key2=value2، –key3=value3 و /key4=value4
- متغیرهای محیطی (Environment Variable)
در اپلیکیشن ASP.NET Core، میتوانیم متغیر محیطی نیز اضافه کنیم.
روشهای دیگر کانفیگریشن به صورت زیرند:
-
- In-memory .NET objects
- یک encrypted user store
- Azure Key Vault
- Custom providerها که کاربر آنها را نصب یا ساخته است.
ASP.NET Core Middleware چیست؟ مقایسهی app.Use و app.Run در ASP.NET Core Middleware
ASP.NET Core Middleware تابعی از مجموعهای منطقی است که برای مدیریت درخواست و پاسخ مربوط به آن اجرا میشود. از Middlewareها برای اجرای عمل میانی (intermediate operation) متفاوتی استفاده میشود. این عمل میانی بهمنظور اجرای یک درخواست است.
در شکل بالا 4 Middleware مختلف دیده میشوند. وقتی Middleware اول درخواست را دریافت میکند، منطق خود را اعمال میکند و این منطق تجاری (Business Logic) مشخص میکند که نتیجه به Middleware یا کامپوننت بعدی فرستاده شود یا نه.
اگر عمل منطقی (Logic Operation) تعیین کند که نتیجه را به Middleware بعدی بفرستیم، نتیجه به کامپوننت یا Middleware بعدی در جریان برنامه (Flow) فرستاده میشود و این کار آنقدر تکرار میشود تا به آخرین Middleware (middleware-iv) در جریان برسیم.
وقتی آخرین Middleware عملیات خود را روی درخواست انجام میدهد، نتیجه را به Middleware قبلی برمیگرداند (middleware-iii) و middleware-iii نتیجه را با منطق قویتری بررسی میکند. البته بررسی مجدد درخواست و برگرداندن آن به Middleware قبلی (middleware-iii) اختیاری است.
این فرایند آنقدر تکرار میشود تا پاسخ حاصل به اولین Middleware در جریان برنامه برسد. Middleware اول میتواند پاسخ را مستقیماً به کلاینت بدهد یا اگر لازم بود، ابتدا مجدداً پاسخ را پردازش کند و سپس نتیجهی حاصل را به کلاینت بدهد.
Microsoft وظایف اصلی Middleware را به صورت زیر تعریف میکند:
- منطق تجاری را اعمال کند و تصمیم بگیرد که آیا نتیجه را به Middleware یا کامپوننت بعدی در جریان/پایپلاین بدهد یا نه.
- قبل و بعد از فراخوانی کامپوننت بعدی در پایپلاین عمل منطقی را اجرا کند.
Middlewareهای توکار در جدول زیر آورده شدهاند:
Authentication | پشتیبانی از احراز هویت (Authentication). |
CORS | کانفیگر کردن Cross-Origin Resource Sharing. |
Response Caching | پشتیبانی از کَش کردن پاسخ |
Response Compression | پشتیبانی از فشردهسازی پاسخ |
Routing | تعریف و constrain کردن درخواست روتینگ |
Session | پشتیبانی از مدیریت Sessionهای کاربر |
Static Files | پشتیبانی از ارائهی فایلهای استاتیک و جستوجو در دایرکتوری (Directory) |
URL Re-writing Middleware | پشتیبانی از ریرایت کردن (Rewrite) URLها و ریدایرکت کردن (Redirect) درخواستها |
مقایسهی app.Use و app.Run:
app.Use:
معروفترین بلوک سازندهی پایپلاین زنجیرهی middleware است. از آن برای اجرای Operation قبل و بعد از فرستادن درخواست به middleware بعدی در پایپلاین استفاده میشود. از طرفی میتواند مسیر درخواست را کوتاه کند.
به این ترتیب، به جای فرستادن درخواست به کامپوننت بعدی در پایپلاین، نتیجهای را به عنوان پاسخِ درخواست برمیگرداند.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.Use((context, next) => { //Do some work here context.Response.Headers.Add("X-Content-Type-Options", "nosniff"); //Pass the request on down to the next pipeline (Which is the MVC middleware) return next(); }); app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World!"); }); app.Use((context, next) => { context.Response.Headers.Add("X-Xss-Protection", "1"); return next(); }); }
app.Run:
app.Run، operation را اجرا میکند و به جای فرستادن درخواست به کامپوننت بعدی، آن را terminate میکند. معمولاً اگر بتوان به درخواستی تنها با یک middleware پاسخ داد، از app.Run استفاده میشود. همچنین از app.Run در آخرین middleware در پایپلاین استفاده میشود تا پایپلاین را terminate کند.

معمولاً از app.Run و app.Use در کنار هم برای بیلد (Build) پایپلاین استفاده میشود:
public class Startup { public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); } }
نکاتی که باید در استفاده از middlewareها درنظر بگیرید:
- بعد از فراخوانی یک متد write، next.Invoke را فراخوانی نکنید. یک کامپوننت middleware یا پاسخی تولید میکند یا next.Invoke را فراخوانی میکند. این دو کار را با هم انجام نمیدهد.
- بعد از فرستادن پاسخ به کلاینت next.Invoke را فراخوانی نکنید. بعد از شروع پاسخ، اگر تغییراتی در HttpResponse صورت گیرد، خطا رخ میدهد. برای مثال، تغییراتی در status code موجب بروز خطا میشود.
روتینگ (Routing) در ASP.NET Core
برای اینکه بتوانیم چرخهی حیات روتینگ (Routing lifecycle) را توصیف کنیم، باید ابتدا کامپوننتهای مختلف مورد استفاده در یک روتینگ کامل و ارتباط آنها را با هم بفهمیم. در این بخش دربارهی موضوعات زیر توضیحاتی خواهیم داد:
- روتینگ چیست؟
- کامپوننتهای استفاده شده در عملیاتهای روتینگ چه هستند؟
- روشهای مختلفِ بیلد (build) کردن روتینگ
روتینگ در ASP.NET Core چیست؟
در یک اپلیکیشن ASP.NET، عملکرد اصلی یک عمل روتینگ (routing operation) این است که هر درخواست ورودی را به یک routing handler، مَپ (map) کند. برای انجام این کار، یک route باید با شروع اپلیکیشن کانفیگر شود.
هر route به جای دنبال کردن جریان درخواست (request flow)، ویژگیهای اضافهای دارد. مثلاً میتواند پارامتر (parameter) یا اطلاعاتی را از URL بخواند. controller میتواند از این اطلاعات برای پردازش درخواست استفاده کند.
همچنین میتوان از عمل روتینگ برای ایجاد URL و مپ کردن آن به route handler استفاده کرد.
به طور خلاصه، عملکردهای کلیدی عمل روتینگ به صورت زیر است:
- مپ کردن هر درخواست ورودی به یک route handler
- پیدا کردن یک route handler بر اساس URL یا اطلاعاتی که در URL وجود دارد.
- ایجاد URLهای مورد استفاده در پاسخ
فرایند پیدا کردن یک route handler بر اساس URL یا اطلاعات موجود در آن، به صورت زیر است:
هر اپلیکیشن یک مجموعه ازroute ها دارد. وقتی درخواستی میرسد، اپلیکیشن با صدا زدن متد RouteAsync برای هر route در مجموعهی routeهای اپلیکیشن، routeای را که با URL مطابقت دارد، پیدا میکند.
Routing همچنین از طریق کلاس RouterMiddleware به پایپلاین middleware متصل است.
کامپوننتهای استفاده شده در عمل روتینگ
کامپوننتهای اصلی مورد استفاده در روتینگ عبارتاند از:
- RouteCollection
- RouterMiddleware
- Controller
روشهای مختلفِ بیلد (build) کردن روتینگ:
مراحل مختلف موجود در حلقهی حیات روتینگ به صورت زیر است:
- URL matching
- URL generation (تولید URL)
- ساخت روت (Creating route)
در تصویر زیر مراحل اولیهی بیلد کردن route آورده شده است.
URL matching
اولین مرحله در حلقهی حیات روتینگ URL matching است. مراحل این کار به صورت زیر است:
- همانطور که در شکل بالا میبینید، درخواست ورودی وارد RouteMiddleware میشود.
- RouteMiddleware بهترتیب و به ازای تمامی routeهای موجود در RouteCollection متد RouteAsync را فراخوانی میکند. متد IRouter تصمیم میگیرد که به درخواست رسیدگی یا فرایند متوقف شود.
- اگر متد IRouter، RouteContext.Handler را شروع کند، handler فراخوانی میشود و به درخواست رسیدگی میکند. با این حال، اگر هیچ RequestDelegatای که null نباشد، پیدا نشود، middleware، next را فراخوانی میکند و درخواست به middleware بعدی فرستاده میشود.
URL generation (تولید URL)
اگر روتینک بتواند با استفاده از اطلاعات موجود در URL یک URL تولید کند، تولید URL اتفاق میافتد. از متد GetVirtualPath در IRouter برای تولید URL استفاده میشود. این متد بهترتیب و به ازای تمامی routeهای موجود در RouteCollection فراخوانی میشود، تا زمانی که متد برای تمامی routeها مقدار null برگرداند.
public interface IRouter { Task RouteAsync(RouteContext context); VirtualPathData GetVirtualPath(VirtualPathContext context); }
شئ VirtualPathData که برگردانده میشود، دارای یک property به اسم VirtualPath است. VirtualPath یک مسیر مجازی است که route ایجاد کرده است و Router و DataTokens هم دارد. برای ارجاع به URL تازه ایجاد شده، از Router استفاده میشود.
به این ترتیب mapped URL برای درخواست ورودی تولید شده است.
ساخت روت (Creating route)
کلاس Route، implemention استانداردِ IRouter است. این کلاس متدی به نام MapRoute دارد که میتواند هر درخواست ورودی را به route مناسب مَپ کند.
با این حال، این متد برای request handler ورودی نمیگیرد و به همین دلیل، از route handler default استفاده میکند. default handler مسئول روابط بین controller پیداشده و action است.
routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");
راههای مختلفی برای ایجاد روتینگ در یک اپلیکیشن وجود دارد. یک route بعد از ایجاد شدن میتواند جریانهای کاری را بین middlewareهای مختلف دنبال کند.
Entity Framework Core
Entity Framework (EF) Core اولین گام برای داشتن EF Core آتی است و از همین جهت به نوعی طراحی شده است که نیازهای اپلیکیشنهای مدرن را پشتیبانی کند. سبک وزن بودن (lightweight)، قابلیت توسعه (Extensible) و کراسپلتفرمی، سه ویژگی اصلی آن هستند. در ادامه برخی از ویژگیهای مهم آورده شدهاند:
In-Memory Provider:
این ویژگی In-Memory database Provider را برای اپلیکیشنهای Entity Framework (EF) Core فراهم میکند. In-Memory database به دلایل مختلفی مثل caching، session context بین برنامهنویسان شهرت دارد.
اگرچه در اپلیکیشنهای Entity Framework (EF) Core، In-Memory database تنها از تست پشتیبانی میکند. نصب In-Memory database در اپلیکیشنهای Entity Framework (EF) Core بسیار ساده است. با استفاده از کد زیر در NuGet package میتوانید آن را نصب کنید.
PM> Install-Package Microsoft.EntityFrameworkCore.InMemory
Shadow Property:
یکی از ویژگیهای عالی موجود در Entity Framework (EF) Core است. این ویژگی در صورتی که برخی propertyهای مدل به گونهای کانفیگر شده باشند که دیده نشوند، از دیده شدن آنها جلوگیری میکند و به این ترتیب لایهای دیگر از انتزاع (abstraction) را امکانپذیر میسازد.
معمولاً identifierها و کلیدهای خارجی foreign key) property)هایی هستند که موجب نقضهای امنیتی میشوند و باید در اپلیکیشن کلاینت پنهان شوند. رسیدن به این ویژگی با استفاده از shadow property امکانپذیر است.
اگرچه، به دلایل داخلی مختلف، لازم است از این shadow propertyها در سرویسهای بکاند استفاده شود و به همین دلیل از ChangeTracker API برای خواندن مقادیر هر shadow property استفاده میشود.
context.Entry(myBlog).Property("updateTimestamp").CurrentValue = DateTime.Now;
برای override کردن متد OnModelCreating و مارک کردن (marking property)های مدل به صورت shadow property از Fluent API استفاده میشود.
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .Property<DateTime>("LastUpdated"); }
ویژگیهای جدید Entity Framework Core 2.0 چه هستند؟
MSDN، Entity Framework (EF) Core 2.0 را در آگوست 2017 معرفی کرد. ویژگیهای جدید آن در این ورژن به صورت زیر است:
- EF Core 2.0 از .NET Core 2.0 پشتیبانی میکند. تقریباً استفاده از 32000 API را برای .NET Framework، .NET Core، Mono، Xamarian و پلتفرم یونیورسال آتی ویندوز (Universal Windows Platform) امکانپذیر کرده است.
- تغییراتی پویا در queryها ایجاد کرده است. queryها سریعتر و برخی از queryهای موجود obsolete شدهاند. مدلهای جدیدی نیز معرفی شده است. برخی از LINQها نیز مستقیماً قابل تبدیل به الگوهای SQL هستند. مثلا، EF.Functions.Like() در LINQ را میتوان به LIKE در SQL تبدیل کرد.
- تعریف رابطه بین موجودیتها به صورت قابل ملاحظهای تغییر کرده است. مثلا، میتوان رابطهی owner (مالکیت) را بین دو موجودیت تعریف کرد. مثلا، یک دانشآموز تنها دارای یک آدرس خانه است.
public class Student { public string studentId { get; set; } public string name {get; set;} public HomeAddress Address { get; set; } }

به این ترتیب، رابطهی موجود بین کلاس Student و کلاس HomeAddress می تواند به صورت زیر باشد:
modelBuilder.Entity<Student>() .OwnsOne(c => c.Address);
- حالا میتوان از filter در مدل استفاده کرد. مثلا، در مثال زیر filterای به کلاس Student اضافه شده است تا بتوان دانشآموزانی را که نمرهی قبولی کسب نکردهاند، پیدا کرد.
modelBuilder.Entity<Student>() .HasQueryFilter(student => !student.IsPaased);
حالا اگر بخواهیم با استفاده از filter آرایهای از دانشآموزان را پیدا کنیم، لیستی از دانشآموزانی را که در آزمون نمرهی قبولی کسب نکردهاند، بهعنوان خروجی خواهیم داشت.
var blog = context.Students .Include(b => b.Student) .FirstOrDefault(b => b.Id == id);
- کارایی به صورت قابلملاحظهای بهتر شده است. دیگر لازم نیست بهازای هر درخواست، یک instac جدید برای سرویس درخواستی بسازیم. با استفاده از configuring در service registration موجود در DbContext، میتوانیم یک pool از instanceهای از پیش ساخته شده (pre–created instances) داشته باشیم.
- قابلیت مقیاسپذیری پایگاهداده (Database Scalablity) ویژگی دیگری است که میتوان در این نسخه به آن اشاره کرد.
بیش از این چه ویژگیهایی در EF6 قابل استفاده هستند که در EF Core 1.0 نمیتوانیم از آنها استفاده کنیم؟
در ادامه لیستی از ویژگیها را میبینید که در EF6 هستند اما در EF Core نه:
- (Inheritance: Table per type (TPT
- (Inheritance: Table per concrete class (TPC
- Many-to-many without join entity
- Spatial data
- امکانات نمایش گرافیکی مدل
- Graphical model editor
- Model format: EDMX (XML)
- Create model from database: VS wizard
- Update model from database
- Entity splitting
- Loading related data: Lazy
- Raw SQL queries: Non-model types
- Stored procedure
- Seed data
- Lifecycle hooks (events, interception)
- DB2 provider
در ادامه لیستی از ویژگیها را میبینید که در EF Core هستند اما در EF6 نه:
- Shadow state properties
- Alternate keys
- Key generation: Client
- Global query filters
- Field mapping
- Mixed client/server evaluation
- ویژگیهای بهتر Query
- Batching of statements
- DbContext pooling
- In-Memory Database Provider
- پشتیبانی از پلتفرمهای .NET Core (Console, ASP.NET Core)، Mono، Xamarian، و پلتفرم یونیورسال ویندوز (Universal Windows Platform)
ورژن بعدی Entity Framework درحال آمده شدن است و دارای تعداد زیادی ویژگی جدید است و برخی باگها در آن رفع شدهاند.
اولین اپلیکیشن ASP.NET Core شما
بیایید با یک روش گام به گام اولین اپلیکیشن ASP.NET Core MVC را بنویسیم:
گام 1:
- Visual Studio 2015 را باز کرده و مسیر روبهرو را دنبال کنید:
Select -> File -> New -> Project (این مسیر تمپلت پروژه را باز خواهد کرد)
- مسیر زیر را دنبال کرده و برای پروژه نامی انتخاب کنید:
- .NET Core -> ASP.NET Core Web Application (.NET Core)
- مثل قبل، مکانی را که میخواهید پروژه در آن ذخیره شود، انتخاب کنید و روی ok کلیک کنید.
- Project Template Wizard باز میشود. Empty template و برای View Engine گزینهی Razor را انتخاب کنید.
- روی ok کلیک کنید. Solution Explorer و working environment باز خواهند شد.
گام 2:
بیایید یک controller به اپلیکیشن اضافه کنیم. این فایل controller دقیقاً شبیه کلاسهای C# است که دارای چندین متد public است که به آنها متدهای action نیز میگویند. وظیفهی یک controller است که درخواست را پردازش کند، مدل مناسب را بیلد کند و کاربر را به یک view مشخص redirect کند. در این مثال، از یک مدل استفاده نمیکنیم و فقط از پاسخ متنی برای یک view رندر میگیریم.
- برای ساختن یک controller در Solution Explorer روی پوشهی controllers راست کلیک کنید و مسیر زیر را دنبال کنید:
Add -> New Item -> Controller
- controller را TestAssignment بنامید و روی add کلیک کنید.
- زیر فایل Controllers، کد زیر را به صورت پیشفرض دارید:
کد بالا یک متد public به نام Index را در TestAssignmentController میسازد و یک View Object را برمیگرداند.
گام 3:
- در کد پیشفرض روی متد View() کلیک کنید.
- addView را انتخاب کنید.
- آن را “Index” بنامید و برای View Engine گزینهی Razor (.cshtml) را انتخاب کنید. رویAdd کلیک کنید.
- بعد از کلیک رویAdd ، Solution explorer به صورت زیر بهروز رسانی میشود.
یک فایل .cshtml جدید در پوشهی Views/TestAssignement اضافه شده است که دارای کد زیر است:
- باید کدهای موجود در body، تگ HTML را به گونهای که میخواهیم، بهروزرسانی کنیم.
گام 4:
- با کلیک روی run، اپلیکیشن را اجرا کنید.
- خروجی زیر را در مرورگر خواهید دید. اپلیکیشن Controller را فراخوانی میکند و آن نیز در عوض، این View را فراخوانی میکند که خروجی موردانتظار زیر را میدهد.
هدف این آموزش پایهی ASP.NET Core، آشنا کردن شما با محیط آن بود.
دورههای مرتبط در فرانش
فیلم آموزش ASP.NET Core:
در صورتی که این آموزش مقدماتی asp.net core برایتان مفیده بوده:
میتوانید برای یادگیری بیشتر دوره های آموزش آنلاین ASP.Net را مشاهده نمایید.
سلام
خوبین وقت بخیر
ممنونم از آموزشهایی که قراردادید
شروع کردم به نگاه کردن و خیلی مفید هستند.
در خلال آموزشها توی یکی از سایتها web api رو دیدم در موردش هم رفتم کمی مطالعه کردم
دیدم خود سایت مایکروسافت هم از postman استفاده میکنه
اگر فقط از post man میشه برای post استفاده کرد پس بقیه برنامه ها یا صفحات وب چطوری استفاده میکنند؟
ایا اصلا لازمه که web api بنویسیم؟
وقتی عملیات های post نمیتونه از طریق مرور گر اجرا بشه پس کجا کاربرد داره؟
الان من یک صفحه ایجاد میکنم که همه چیزش web api هست ولی چطوری باید post رو فراخوانی کنم؟