聊聊 ASP.NET Core 中间件和过滤器的区别

张开发
2026/6/10 0:25:45 15 分钟阅读
聊聊 ASP.NET Core 中间件和过滤器的区别
先说中间件中间件是 ASP.NET Core 处理 HTTP 请求的基本部件是框架本身的组成部分。每一个请求进来后按照Use的注册顺序依次经过每一个中间件到达终端后再按照相反的方向依次返回。一系列中间件串联起来就组成了 ASP.NET Core 的请求管道。这个模型有人叫洋葱模型也有人叫俄罗斯套娃模型都是一个意思。请求 → 中间件A → 中间件B → 中间件C终端响应 ← 中间件A ← 中间件B ←中间件可以做什么呢它收到请求后可以在请求/响应对象上加点佐料自己的逻辑然后调用next()把请求传递给下一个中间件。如果不调用next()请求就在这里短路了后面的中间件不会执行这个中间件就成了终端中间件。下面是一个简单示例演示如何自定义一个记录请求耗时的中间件// 定义中间件类public class TimingMiddleware{private readonly RequestDelegate _next;public TimingMiddleware(RequestDelegate next){_next next;}public async Task InvokeAsync(HttpContext context){var sw Stopwatch.StartNew();// 调用 next()请求继续往下走await _next(context);// next() 返回后响应正在往回走sw.Stop();Console.WriteLine($[{context.Request.Path}] 耗时{sw.ElapsedMilliseconds}ms);}}// 在 Program.cs 中注册var app builder.Build();app.UseMiddlewareTimingMiddleware(); // 注册自定义中间件app.UseRouting();app.UseAuthorization();app.MapControllers();app.Run();如果你不想单独定义一个类也可以用app.Use直接写一个内联中间件app.Use(async (context, next) {Console.WriteLine($请求进来了{context.Request.Path});await next(); // 传递给下一个中间件Console.WriteLine($响应回来了{context.Response.StatusCode});});这里注册的是终端中间件不接受next请求到这里就结束了不会再往下传app.Run(async context {await context.Response.WriteAsync(到终点了不继续往下走);});再聊过滤器过滤器是在路由中间件内部起作用的。请求经过中间件管道到达路由中间件后路由中间件确定了要调用哪个 Controller / Action。在真正执行 Action 的前后过滤器就夹在这里介入。用一张简单的示意图来表示请求进来→ 中间件们→ 路由中间件确定目标 Action→ 过滤器们Action 执行前后插手→ Action 执行← 过滤器们← 路由中间件← 中间件们响应返回正因为过滤器处于路由之后所以它能拿到 MVC 的上下文信息比如当前是哪个 Action、Action 上有哪些 Attribute、ModelState 是否合法等等。这是普通中间件做不到的因为中间件执行的时候路由还没解析呢。// 定义过滤器类继承 ActionFilterAttributepublic class ValidateModelAttribute : ActionFilterAttribute{// 在 Action 执行之前触发public override void OnActionExecuting(ActionExecutingContext context){if (!context.ModelState.IsValid){// ModelState 校验不通过直接短路返回 400var errors context.ModelState.Where(e e.Value?.Errors.Count 0).ToDictionary(e e.Key,e e.Value!.Errors.Select(x x.ErrorMessage).ToArray());context.Result new BadRequestObjectResult(new{code 400,message 参数校验失败,errors});}}// 在 Action 执行之后触发public override void OnActionExecuted(ActionExecutedContext context){// 可以在这里统一处理响应比如包一层统一的返回格式}}使用方式很简单直接作为 Attribute 标注在 Controller 或 Action 上// 标注在单个 Action 上[HttpPost][ValidateModel]public IActionResult CreateUser([FromBody] CreateUserRequest request){// 走到这里说明 ModelState 已经通过校验return Ok(new { message 创建成功 });}// 也可以标注在 Controller 上对所有 Action 生效[ApiController][ValidateModel]public class UserController : ControllerBase{// ...}如果想全局生效在Program.cs里注册就行builder.Services.AddControllers(options {options.Filters.AddValidateModelAttribute(); // 全局注册});它俩的区别中间件过滤器作用范围所有 HTTP 请求包括静态文件仅限 Controller / Action典型使用场景限流、压缩、跨域、日志、认证权限校验、参数校验、统一响应封装、异常处理一句话总结中间件是 HTTP 管道的基础设施过滤器是 MVC 系的切面机制它们不是同一层次的东西。给你一个小技巧不确定用哪个的时候问自己一个问题我需要知道当前是哪个 Action 吗需要的话用过滤器不需要的话中间件就够了。内置清单最后整理一份 ASP.NET Core 已经提供的常用中间件和过滤器遇到需求的时候先查查有没有现成的别重复造轮子。常用内置中间件中间件说明UseRouting路由解析UseAuthentication认证UseAuthorization授权UseStaticFiles静态文件服务UseCors跨域UseExceptionHandler全局异常处理UseHttpsRedirectionHTTPS 重定向UseResponseCompression响应压缩UseRateLimiter限流.NET 7 新增内置过滤器过滤器说明[Authorize]授权校验[AllowAnonymous]允许匿名访问[RequireHttps]强制 HTTPS[ValidateAntiForgeryToken]防止 CSRF 攻击[ResponseCache]响应缓存[Produces]指定响应内容类型[Consumes]指定请求内容类型

更多文章