ASP.NET Core之中间件
本文翻译自: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* 扩展方法去引入不同的中间件