自定义 ASP.NET Core 中间件
中间件是一种装配到应用管道以处理请求和响应的软件。
每个中间件添加或修改 http 请求,并可选择将控制权传递给下一个中间件组件。
下图说明了中间件组件的执行:
中间件构建请求管道。下图说明了 ASP.NET Core 请求处理。
中间件类
通常,中间件封装在类中,并且通过扩展方法公开。
using System.Globalization; namespace MvcMovie.Middleware { /// <summary> /// 中间件类,该中间件通过查询字符串设置当前请求的区域性 /// </summary> public class RequestCultureMiddleware { private readonly RequestDelegate _next; public RequestCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline. await _next(context); } } /// <summary> /// 创建扩展方法以通过 IApplicationBuilder 公开中间件 /// </summary> public static class RequestCultureMiddlewareExtensions { public static IApplicationBuilder UseRequestCulture( this IApplicationBuilder builder) { return builder.UseMiddleware<RequestCultureMiddleware>(); } } }
中间件类必须包括:
- 具有类型为 RequestDelegate 的参数的公共构造函数。
- 名为
Invoke
或InvokeAsync
的公共方法。 此方法必须:- 返回
Task
。 - 接受类型 HttpContext 的第一个参数。
- 返回
通过 Program.cs
调用中间件:
//调用自定义中间件 app.UseRequestCulture();
中间件依赖项(中间件使用注册服务类)
中间件在应用启动时构造,因此具有应用程序生存期。 在每个请求过程中,中间件构造函数使用的范围内生存期服务不与其他依赖关系注入类型共享。
若要在中间件和其他类型之间共享范围内服务,请将这些服务添加到 InvokeAsync
方法的签名。 InvokeAsync
方法可接受由 DI 填充的其他参数:
1 namespace Middleware.Example; 2 3 public class MyCustomMiddleware 4 { 5 private readonly RequestDelegate _next; 6 7 public MyCustomMiddleware(RequestDelegate next) 8 { 9 _next = next; 10 } 11 12 // IMessageWriter is injected into InvokeAsync 13 public async Task InvokeAsync(HttpContext httpContext, IMessageWriter svc) 14 { 15 svc.Write(DateTime.Now.Ticks.ToString()); 16 await _next(httpContext); 17 } 18 } 19 20 public static class MyCustomMiddlewareExtensions 21 { 22 public static IApplicationBuilder UseMyCustomMiddleware( 23 this IApplicationBuilder builder) 24 { 25 return builder.UseMiddleware<MyCustomMiddleware>(); 26 } 27 }
使用中间件:
1 builder.Services.AddScoped<IMessageWriter, LoggingMessageWriter>(); 2 3 var app = builder.Build(); 4 5 app.UseHttpsRedirection(); 6 7 app.UseMyCustomMiddleware();
IMessageWriter
接口和实现:
1 namespace Middleware.Example; 2 3 public interface IMessageWriter 4 { 5 void Write(string message); 6 } 7 8 public class LoggingMessageWriter : IMessageWriter 9 { 10 11 private readonly ILogger<LoggingMessageWriter> _logger; 12 13 public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) => 14 _logger = logger; 15 16 public void Write(string message) => 17 _logger.LogInformation(message); 18 }