.NET Core开发实战课程备忘(13) -- 中间件:掌握请求处理过程的关键
核心对象
IApplicationBuilder:让我们注册我们自己的中间件
RequestDelegate:我们处理整个请求的委托
代码实现 创建项目 创建名字为MiddlewareDemo的ASP.NET Core项目,类型为API
直接注入委托 Startup.Configure方法里,在app.UseHttpsRedirection()中间件之前添加以下代码:
1 2 3 4 5 app.Use(async (context, next) => { await next(); await context.Response.WriteAsync("Hello world -- my middleware in delegate" ); });
运行代码访问/WeatherForecast,可以看到原本的json后面会添加Hello world -- my middleware in delegate这句话
对特定路径注册特定中间件 注释掉上面的代码,在原处新增以下代码
1 2 3 4 5 6 7 8 app.Map("/abc" , builder => { builder.Use(async (context, next) => { await next(); await context.Response.WriteAsync("Hello world abc -- from map middleware" ); }); });
运行代码访问/WeatherForecast,结果与初始项目运行一致,访问/abc,页面会返回Hello world abc -- from map middleware
对特定路径注册中间件升级版 当这个特定路径的判断比较复杂,可以使用MapWhen来注册,注释掉上一步代码,在原处新增以下代码:
1 2 3 4 5 6 7 8 app.MapWhen(context => { return context.Request.Query.Keys.Contains("abc" ); }, builder => { builder.Use(async (context, next) => { await next(); await context.Response.WriteAsync("Hello world query abc -- from mapWhen middleware" ); }); });
这里表示当url参数里包含abc这个函数,则触发指定的中间件,运行代码,运行代码访问/WeatherForecast,结果与初始项目运行一致,访问/WeatherForecast?abc=aaa,会在原有的返回结果后面添加Hello world query abc -- from mapWhen middleware
使用扩展方法来注册中间件(最佳姿势) 自定义中间件是按约定来调用的,即中间件里需要包含一个InvokeAsync方法,方法参数为HttpContext,通常中间件不直接对外暴露,所以类的访问修饰符通常是默认的internal,然后通过IApplicationBuilder的扩展方法向外暴露
在根目录创建文件夹Middlewares/MyMiddleware,在目录下创建两个文件MyMiddleware.cs和MyMiddlewareExtension.cs,具体代码如下:
MyMiddleware.cs代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.Logging;namespace MiddlewareDemo.Middlewares.MyMiddleware { class MyMiddleware { private readonly RequestDelegate _next; private readonly ILogger<MyMiddleware> _logger; public MyMiddleware (RequestDelegate next,ILogger<MyMiddleware> logger ) { _next = next; _logger = logger; } public async Task InvokeAsync (HttpContext context ) { using (_logger.BeginScope("TraceIdentifier:{TraceIdentifier}" ,context.TraceIdentifier)) { _logger.LogDebug("开始执行MyMiddleware中间件" ); await _next(context); _logger.LogDebug("执行MyMiddleware中间件结束" ); } } } }
MyMiddlewareExtension.cs代码:
1 2 3 4 5 6 7 8 9 10 11 12 using Microsoft.AspNetCore.Builder;namespace MiddlewareDemo.Middlewares.MyMiddleware { public static class MyMiddlewareExtension { public static IApplicationBuilder UseMyMiddleware (this IApplicationBuilder app ) { return app.UseMiddleware<MyMiddleware>(); } } }
因为这里使用了日志作用域,所以还需要到appsettings.json里修改以下日志配置,具体内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "Logging" : { "LogLevel" : { "Default" : "Trace" , "Microsoft" : "Warning" , "Microsoft.Hosting.Lifetime" : "Information" }, "Console" : { "IncludeScopes" : true , "LogLevel" : { "MiddlewareDemo.Middlewares.MyMiddleware.MyMiddleware" : "Trace" } } }, "AllowedHosts" : "*" }
回到Startup.Configure,注释掉前面的测试代码,在原处新增以下代码:
运行项目,访问/WeatherForecast,可以看到控制台打印出了对应的日志