前言
中间件(Middleware)
概念
中间件是 ASP.NET Core 请求处理管道(pipeline) 中的一段可插拔组件,接收 HttpContext、执行任意逻辑、并决定是否把请求交给管道中的下一个中间件。管道呈“洋葱模型”(请求顺序进入,响应倒序返回)。
调用签名核心是:RequestDelegate next -> Task Invoke(HttpContext context)。
中间件就是请求管道里的“拦路插件”,每个请求经过它,它可以拦截、修改、放行或终止请求。
1.执行流程
-
注册顺序决定请求进入的顺序。
-
每个中间件要决定是否
await next(context)(放行)或不调用next(短路/终止)。 -
请求走入时是顺序;响应返回时是逆序(栈式回退)。
-
每个中间件既可以在请求前处理逻辑,也可以在请求后处理逻辑。
请求 -> Middleware1 -> Middleware2 -> Middleware3 -> Endpoint
响应 <- Middleware3 <- Middleware2 <- Middleware1

2.实现方式
RequestDelegate 是中间件的核心,它接收一个 HttpContext,返回一个 Task。
中间件管道本质上是 RequestDelegate 链。
每个中间件通过调用 await next(context) 来传递请求。
public delegate Task RequestDelegate(HttpContext context);
2.1内联委托方式(Lambda/RequestDelegate)
直接在 Configure 中写 Lambda 表达式,RequestDelegate 链的最轻量写法。
特点:
- 快速、轻量
- 不可复用
- 适合简单逻辑、调试或快速原型
app.Use(async (context, next) =>
{Console.WriteLine("请求前逻辑");await next(); // 调用下一个中间件Console.WriteLine("响应后逻辑");
});
示例
在Program中通过委托建立中间件

请求http://localhost:5004/WeatherForecast接口,可以看到中间件执行逻辑
请求前逻辑
执行请求中...
响应后逻辑

2.2类中间件方式(RequestDelegate+Invoke/InvokeAsync)
自定义中间件类,通过构造函数注入 RequestDelegate next,实现 InvokeAsync(HttpContext) 方法。
特点:
- 灵活、可复用
- 支持依赖注入(构造函数注入服务)
- 最常用的自定义中间件实现方式
public class CustomMiddleware
{private readonly RequestDelegate _next;public CustomMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context){Console.WriteLine("CustomMiddleware请求前逻辑");await _next(context); // 调用下一个中间件Console.WriteLine("CustomMiddleware响应后逻辑");}
}
调用方式:app.UseMiddleware<MyMiddleware>();
示例
自定义中间件CustomMiddleware

请求接口,可以看到CustomMiddleware请求逻辑
委托中间件请求前逻辑
CustomMiddleware请求前逻辑
执行请求中...
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

2.3接口(IMiddleware)
IMiddleware 是 ASP.NET Core 自带的接口化中间件实现方式,通过 DI 容器管理生命周期和依赖,简化传统中间件类的实现。
特点:
- 生命周期由 DI 管理(Transient/Scoped/Singleton)
- 不需要手动保存
_next - 支持复杂依赖注入,适合大型中间件
public interface IMiddleware
{Task InvokeAsync(HttpContext context, RequestDelegate next);
}public class MyMiddlewareWithDI : IMiddleware
{private readonly ILogger<MyMiddlewareWithDI> _logger;public MyMiddlewareWithDI(ILogger<MyMiddlewareWithDI> logger){_logger = logger;}public async Task InvokeAsync(HttpContext context, RequestDelegate next){_logger.LogInformation("请求前逻辑");await next(context); // 调用下一个中间件_logger.LogInformation("响应后逻辑");}
}
调用方式
// 先注入DI
services.AddTransient<MyMiddlewareWithDI>();
// 再注册中间件
app.UseMiddleware<MyMiddlewareWithDI>();
示例
新增CustomDIMiddleware实现IMiddleware

然后先通过AddTransient<CustomDIMiddleware>()注册到DI,后面再使用UseMiddleware注册中间件CustomDIMiddleware
委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
执行请求中...
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

2.4RequestDelegate 工厂方式(高级方式)
将中间件逻辑封装成返回 RequestDelegate 的方法。动态生成中间件、框架内部使用。
特点:
- 高度灵活、可复用
- 可动态生成中间件
- 底层原理仍然是 RequestDelegate 链
public static class CustomMiddlewareFactory
{public static RequestDelegate CreateMiddleware(RequestDelegate next){return async context =>{Console.WriteLine("CustomMiddlewareFactory请求前逻辑");await next(context);Console.WriteLine("CustomMiddlewareFactory响应后逻辑");};}
}
调用方式
app.Use(CustomMiddlewareFactory.CreateMiddleware);
示例
新建自定义中间件工厂(CustomMiddlewareFactory),然后提供一个创建RequestDelegate的方法

然后使用Use方法调用,Use方法接收一个参数是RequestDelegate并且返回RequestDelegate的委托,其实和委托方式调用蕾西,这里只是封装起来了
委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
CustomMiddlewareFactory请求前逻辑
执行请求中...
CustomMiddlewareFactory响应后逻辑
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

2.5内置扩展方法中间件(Use系列)
框架自带中间件封装,例如:
// 路由
app.UseRouting();
// 认证
app.UseAuthentication();
// 授权
app.UseAuthorization();
// 执行路由匹配后的请求处理
app.UseEndpoints(endpoints => { ... });
特点:
- 封装 RequestDelegate 或类中间件
- 使用方便,集成 MVC / Minimal API
- 灵活性略低
2.5总结
关于中间件的执行流程,这里调试一遍就很明显了:
中间件按注册顺序依次执行“请求前逻辑”,到达终点后再按相反顺序依次执行“响应后逻辑”,形成典型的洋葱模型(先进后出、后进先出)。
委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
CustomMiddlewareFactory请求前逻辑
执行请求中...
CustomMiddlewareFactory响应后逻辑
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑
总结
-
ASP.NET Core 中间件都是 RequestDelegate 链
-
_next指向下一个中间件,形成管道链 -
每个中间件可以在请求前/响应后处理逻辑
-
不同实现方式只是 封装形式、复用性、DI 生命周期管理 不同
| 实现方式 | 核心机制 | 调用方式 | 特点 |
|---|---|---|---|
| 内联委托 / Lambda | RequestDelegate | app.Use(...) |
快速、轻量,不可复用 |
| 类中间件 + Invoke | 类 + RequestDelegate | app.UseMiddleware<T>() |
灵活、可复用,支持依赖注入 |
| 实现 IMiddleware 接口 | IMiddleware.InvokeAsync | app.UseMiddleware<T>() + DI |
生命周期可控,支持复杂依赖 |
| RequestDelegate 工厂 | 返回 RequestDelegate | app.Use(...) |
高度灵活,可动态生成 |
| 内置扩展方法 | 框架封装 RequestDelegate | app.UseXxx() |
使用方便,集成 MVC / Minimal API |
3.Use、Run、Map、UseWhen
-
Use:标准,多数中间件用await next()放行。 -
Run:终端中间件,不接next,写完后不会再调用后续中间件(短路)。 -
Map/MapWhen:基于路径或条件分支路由,创建子管道(可用于多态处理)。 -
UseWhen:条件中间件,满足条件时在子管道内执行next,不满足则略过。
| 方法 | 是否可放行 | 作用范围 | 匹配条件 | 常见用途 |
|---|---|---|---|---|
| Use | 可放行/短路 | 全局管道 | 无 | 日志、认证、异常处理、请求处理 |
| Run | 不放行 | 全局管道/终端 | 无 | 健康检查、默认响应、短路请求 |
| Map | 可放行/短路 | 子管道 | 基于路径 | 分模块处理不同 URL 分支 |
| UseWhen | 可放行/短路 | 子管道 | 任意条件 | 条件化中间件,如仅对 API 或特定 header 生效 |
4.应用场景
-
全局异常捕获(
UseExceptionHandler或DeveloperExceptionPage) -
日志/请求追踪/CorrelationId(Inject TraceId)
-
身份认证与授权(JWT、Cookies)
-
CORS、RateLimiting、RequestSizeLimit
-
Static Files、Response Compression、Response Caching
-
HTTPS 强制、HSTS、Content-Security-Policy header 插入
-
Body 读取、请求重写(Rewrite)、路径重写(UsePathBase、RewriteOptions)
-
流量劫持(Proxy headers)、IP 限制
5.总结
中间件是 ASP.NET Core 请求管道的插件
顺序和调用 next() 决定请求响应流程
Use 可放行,Run 终止,Map/UseWhen 创建子管道
常用于日志、异常、认证、CORS、限流、压缩等横切关注点
6.eshop的中间件
eshop中没有单独封装中间件,而是使用了MediatR命令管道统一处理业务命令的日志、参数验证、管道。
中间件是AspNetCore中很重要的组成,eshop中没有封装使用,但我还是再次学习了一遍

📌 创作不易,感谢支持!
每一篇内容都凝聚了心血与热情,如果我的内容对您有帮助,欢迎请我喝杯咖啡☕,您的支持是我持续分享的最大动力!
💬 加入交流群(QQ群):576434538
