写入自定义 ASP.NET Core 中间件Write custom ASP.NET Core middleware
本文内容
作者:Rick Anderson 和 Steve Smith
中间件是一种装配到应用管道以处理请求和响应的软件。ASP.NET Core 提供了一组丰富的内置中间件组件,但在某些情况下,你可能需要写入自定义中间件。
中间件类Middleware class
通常,中间件封装在类中,并且通过扩展方法公开。请考虑以下中间件,该中间件通过查询字符串设置当前请求的区域性:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
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();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
以上示例代码用于演示创建中间件组件。有关 ASP.NET Core 的内置本地化支持,请参阅 ASP.NET Core 全球化和本地化。
通过传入区域性测试中间件。例如,请求 https://localhost:5001/?culture=no
。
以下代码将中间件委托移动到类:
using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;
namespace Culture
{
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);
}
}
}
必须包括中间件类:
- 具有类型为 RequestDelegate 的参数的公共构造函数。
- 名为
Invoke
或InvokeAsync
的公共方法。此方法必须:- 返回
Task
。 - 接受类型 HttpContext 的第一个参数。
- 返回
构造函数和 Invoke
/InvokeAsync
的其他参数由依赖关系注入 (DI) 填充。
中间件依赖项Middleware dependencies
中间件应通过在其构造函数中公开其依赖项来遵循显式依赖项原则。在每个应用程序生存期 构造一次中间件。如果需要与请求中的中间件共享服务,请参阅按请求中间件依赖项部分。
中间件组件可通过构造函数参数从依赖关系注入 (DI) 解析其依赖项。UseMiddleware<T> 也可直接接受其他参数。
按请求中间件依赖项Per-request middleware dependencies
由于中间件是在应用启动时构造的,而不是按请求构造的,因此在每个请求过程中,中间件构造函数使用的范围内 生存期服务不与其他依赖关系注入类型共享。如果必须在中间件和其他类型之间共享范围内 服务,请将这些服务添加到 Invoke
方法的签名。Invoke
方法可接受由 DI 填充的其他参数:
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMyScopedService is injected into Invoke
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
}
中间件扩展方法Middleware extension method
以下扩展方法通过 IApplicationBuilder 公开中间件:
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
以下代码通过 Startup.Configure
调用中间件:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}