本文翻譯自:http://www.tutorialsteacher.com/core/aspnet-core-middleware
基本概念
ASP.NET Core引入了中間件的概念,中間件是在ASP.NET Core應用的每次請求時執行的部分。在經典的ASP.NET 中,HttpHandlers和HttpModules時請求管道的一部分。中間件和HttpHandlers和HttpModules相似,都需要在每次的請求中配置和執行。
通常,在ASP.NET Core應用中會存在很多的中間件,可以使框架提供的中間件,通過NuGet添加或者自定義的中間件。可以設置在每次請求管道中中間件的執行順序,每一個中間件都可以添加或者修改http請求並且選擇是否傳遞控制權限。
下圖說明中間件的執行過程:
中間件創建請求的管道,下圖說明ASP.NET Core請求的處理過程。
配置中間件
中間件可以在Startup的Configure方法中使用 IApplicationBuilder的實例進行配置。下面的例子中,使用Run方法添加了一個中間件,作用是在每次請求中返回“Hello World”字符串。
1 public class Startup 2 { 3 public Startup() 4 { 5 } 6 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 7 { 8 //configure middleware using IApplicationBuilder here..
9
10 app.Run(async (context) =>
11 { 12 await context.Response.WriteAsync("Hello World!"); 13
14 }); 15
16 // other code removed for clarity..
17 } 18 }
在上面的例子中,Run()是 IApplicationBuilder實例的擴展方法,在應用請求的管道上添加了中間件。上面配置的中間件在每次請求返回了一個字符串“Hello World”。
解析Run方法
這里使用擴展方法Run添加中間件,下面是Run方法的簽名:
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
Run是IApplicationBuilder中的一個擴展方法,可以接受參數RequestDelegate。RequestDelegate是處理請求的委托方法,下面是RequestDelegate的簽名:
public delegate Task RequestDelegate(HttpContext context);
如上所示,Run方法可以接收一個方法作為參數,這個接收的方法簽名應該和RequestDelegate一致。因此,方法可以接收HttpContext參數然后返回Task。
在Run方法中可以指定Lambda表達式或者一個函數,Lambda可以和下面的實例類似:
1 public class Startup 2 { 3 public Startup() 4 { 5 } 6
7 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 8 { 9 app.Run(MyMiddleware); 10 } 11
12 private Task MyMiddleware(HttpContext context) 13 { 14 return context.Response.WriteAsync("Hello World! "); 15 } 16 }
上面的MyMiddleware方法不是異步的,在執行完成前會導致線程阻塞。可以使用 async和await改為異步執行進而提高性能和擴展性。
1 // other code removed for clarity
2
3 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 4 { 5 app.Run(MyMiddleware); 6 } 7
8 private async Task MyMiddleware(HttpContext context) 9 { 10 await context.Response.WriteAsync("Hello World! "); 11 }
上面的例子與下面的代理是一樣的
1 app.Run(async context => await context.Response.WriteAsync("Hello World!") ); 2
3 //or
4
5 app.Run(async (context) =>
6 { 7 await context.Response.WriteAsync("Hello World!"); 8 });
通過這種方式,我們可以在 Run方法中配置中間件。
配置多個中間件
通常在ASP.NET Core應用中會存在多個中間件,中間件順序執行。Run方法添加了一個terminal中間件因為無法繼續調用其他中間件。下面的代碼會一直執行Run方法並且永遠都不會執行第二個Run方法。
1 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 2 { 3 app.Run(async (context) =>
4 { 5 await context.Response.WriteAsync("Hello World From 1st Middleware"); 6 }); 7
8 // the following will never be executed
9 app.Run(async (context) =>
10 { 11 await context.Response.WriteAsync("Hello World From 2nd Middleware"); 12 }); 13 }
想要配置多個中間件,使用Use擴展方法。它和Run方法相似,區別在於它包含了下一個參數用於順序的調用下一個中間件。
1 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 2 { 3 app.Use(async (context, next) =>
4 { 5 await context.Response.WriteAsync("Hello World From 1st Middleware!"); 6
7 await next(); 8 }); 9
10 app.Run(async (context) =>
11 { 12 await context.Response.WriteAsync("Hello World From 2nd Middleware"); 13 }); 14 }
上面的代碼會在瀏覽器中顯示
Hello World From 1st Middleware!Hello World From 2nd Middleware!
因此,我們可以使用Use()方法按照我們需要的順序配置多個中間件。
使用NuGet添加內置的中間件
ASP.NET Core是一個模塊化的框架,可以通過Nuget在程序中添加服務端的功能。在我們的程序中有很多插件化可用的中間件。
下面使內置的中間件:
Middleware | Description |
---|---|
Authentication | Adds authentication support. |
CORS | Configures Cross-Origin Resource Sharing. |
Routing | Adds routing capabilities for MVC or web form |
Session | Adds support for user session. |
StaticFiles | Adds support for serving static files and directory browsing. |
Diagnostics | Adds support for reporting and handling exceptions and errors. |
診斷中間件
診斷功能的中間件用於報告並處理ASP.NET Core中的異常和錯誤,診斷EF Core的遷移錯誤。
在程序中添加 Microsoft.AspNetCore.Diagnostics 包,該包包含以下中間件和服務:
Middleware | Extension Method | Description |
---|---|---|
DeveloperExceptionPageMiddleware | UseDeveloperExceptionPage() | Captures synchronous and asynchronous exceptions from the pipeline and generates HTML error responses. |
ExceptionHandlerMiddleware | UseExceptionHandler() | Catch exceptions, log them and re-execute in an alternate pipeline. |
StatusCodePagesMiddleware | UseStatusCodePages() | Check for responses with status codes between 400 and 599. |
WelcomePageMiddleware | UseWelcomePage() | Display Welcome page for the root path. |
可以在Startup類中的Configure方法中,調用 Use* 擴展方法去使用上面的中間件。
添加WelcomePage中間件,在根目錄顯示Welcome信息。
1 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 2 { 3 app.UseWelcomePage(); 4 //other code removed for clarity
5 }
這里調用不同的 Use* 擴展方法去引入不同的中間件