ASP.NET Core中间件怎么编写 自定义Middleware管道方法

ASP.NET Core中间件是按顺序处理HTTP请求响应的组件,可写为lambda委托或封装成带依赖注入的类,注册顺序决定执行逻辑,需注意短路、前置/后置时机及Options配置。

ASP.NET Core 中间件就是处理 HTTP 请求和响应的组件,按顺序组成管道。自定义中间件本质是一个接收 RequestDelegate(下一个中间件)并返回 Task 的委托,或封装成类更清晰、可复用。

写一个基础函数式中间件

最简方式是直接在 Program.cs 中用 lambda 编写:

app.Use(async (context, next) =>
{
    // 在下一个中间件执行前做的事(前置逻辑)
    Console.WriteLine("请求开始");

    await next(); // 调用管道中的下一个中间件

    // 在下一个中间件执行后做的事(后置逻辑)
    Console.WriteLine("请求结束");
});

注意:必须调用 next() 才能让请求继续向下走;不调用就“短路”了(比如做身份验证失败直接返回 401)。

封装成可重用的中间件类

推荐做法,利于测试、配置和复用。例如写一个记录请求耗时的中间件:

public class TimingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public TimingMiddleware(RequestDelegate next, ILogger logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var watch = Stopwatch.StartNew();
        await _next(context);
        watch.Stop();

        _logger.LogInformation("请求 {Path} 耗时 {ElapsedMs}ms",
            context.Request.Path, watch.ElapsedMilliseconds);
    }
}

然后在 Program.cs 中注册并使用:

app.UseMiddleware();

如果需要传参(如开关、阈值),可加一个 Options 类配合构造函数注入。

中间件的执行顺序很关键

中间件按 UseXXX 的调用顺序加入管道,越靠前的越先执行「前置」,越靠后的越先执行「后置」。常见顺序建议:

  • 异常处理UseExceptionHandler)放最前,捕获后续所有异常
  • 静态文件UseStaticFiles)通常较早,避免走完整管道
  • 认证/授权UseAuthenticationUseAuthorization)放在路由之前
  • 终结点路由UseEndpointsMapControllers)放在最后,真正分发请求

顺序错了可能导致功能失效(比如把认证放路由后面,就根本不会校验)。

带参数的中间件写法(Options 模式)

比如想让 TimingMiddleware 只对特定路径计时,或设置慢请求告警阈值:

public class TimingOptions
{
    public string? PathPrefix { get; set; } = "/";
    public long WarnThresholdMs { get; set; } = 500;
}

修改中间件构造函数注入 IOptions,并在 InvokeAsync 中判断路径和耗时:

if (!context.Request.Path.StartsWithSegments(options.Value.PathPrefix))
    return await _next(context);

注册时可配置:

builder.Services.Configure(opt =>
{
    opt.PathPrefix = "/api/";
    opt.WarnThresholdMs = 200;
});
app.UseMiddleware();

基本上就这些。核心就三点:理解委托链、掌握类封装写法、盯紧注册顺序。不复杂但容易忽略细节。