ASP.NET Core 中间件是按顺序处理 HTTP 请求和响应的组件,构成“洋葱模型”管道;需在 Program.cs 中用 UseXXX()/MapXXX() 注册,推荐类封装形式(含 InvokeAsync),依赖服务应通过方法参数注入而非构造函数;顺序至关重要,如静态文件须在身份验证前;可用 UseWhen/Map 分支或隔离路径;调试时注意执行时机、短路及响应写入限制。
ASP.NET Core 中间件是处理 HTTP 请求和响应的组件,按顺序构成请求处理管道。开发中间件关键是实现请求委托逻辑,注册则需在 Program.cs(.NET 6+)中通过 UseXXX() 或 MapXXX() 方法挂载。
自定义中间件的两种写法
推荐使用类封装方式,结构清晰、易于测试;也可用内联委托,适合简单逻辑。
-
类形式中间件(推荐):定义一个类,构造函数接收
RequestDelegate next,实现InvokeAsync(HttpContext context)方法。类必须有公共构造函数且不依赖作用域服务(如需 DI,用InvokeAsync参数注入)。 -
内联中间件:直接在
Program.cs中用app.Use(async (context, next) => { ... })编写,适合调试或一次性逻辑,但不易复用和单元测试。
中间件的注册顺序很重要
中间件执行顺序即注册顺序,靠前的中间件最先接触请求、最后接触响应(类似“洋葱模型”)。错误的顺序会导致功能失效,比如静态文件中间件 UseStaticFiles() 必须在身份验证之前,否则未授权用户也能访问图片等资源。
- 常用顺序参考:异常处理 → 重定向 → HSTS → HTTPS 强制 → 静态文件 → 身份验证 → 授权 → 路由 → 终结点。
- 用
UseWhen()可基于条件分支注册中间件,例如只对 API 路径启用 CORS。 - 用
Map()或MapWhen()可为特定路径前缀创建子管道,隔离逻辑(如/health不走认证)。
在 Program.cs 中注册中间件
.NET 6+ 统一使用 WebApplicationBuilder 构建应用,中间件注册全部在 app 实例上调用方法。
- 内置中间件如
app.UseRouting()、app.UseAuthentication()直接调用即可。 - 自定义类中间件用
app.UseMiddleware,框架自动解析依赖(支持构造函数注入 IServiceScopeFactory 等)。() - 若中间件依赖作用域服务(如
DbContext),应在InvokeAsync方法参数中注入,而非构造函数——避免生命周期冲突。
调试与验证中间件行为
可在中间件中加日志或断点观察执行时机。注意:中间件一旦调用 next(context) 就进入下一个环节,之后代码属于“响应阶段”;若未调用 next,请求就在此终止(如返回 401)。
- 用
app.Use(async (ctx, next) => { Console.WriteLine("Before"); await next(); Console.WriteLine("After"); })快速验证洋葱模型。 - 检查响应头、状态码、Body 是否被提前写入(调用
context.Response.WriteAsync后再调next会报错)。 - 结合
DeveloperExceptionPage和HttpContext.TraceIdentifier定位具体请求链路。
基本上就这些。中间件机制本身不复杂,但顺序、生命周期和执行时机容易忽略,写的时候多想想“谁先谁后”“有没有短路”“依赖的服务是不是能拿到”,基本不会踩坑。

应的组件,构成“洋葱模型”管道;需在 Program.cs 中用 UseXXX()/MapXXX() 注册,推荐类封装形式(含 InvokeAsync),依赖服务应通过方法参数注入而非构造函数;顺序至关重要,如静态文件须在身份验证前;可用 UseWhen/Map 分支或隔离路径;调试时注意执行时机、短路及响应写入限制。






