ASP.NET Core 中间件

文章目录


前言

ASP.NET Core 中间件是构成请求处理管道的核心组件,用于处理 HTTP 请求和响应。


一、中间件的本质

定义:

  • 中间件是按顺序执行的组件,串联成请求处理管道(Pipeline),每个组件负责处理请求或响应的特定阶段。

类比:

  • 类似工厂流水线,每个工位(中间件)对请求进行加工,最终生成响应。

二、作用场景:

  • 典型场景:
    • 身份验证/授权(如 UseAuthentication
    • 静态文件处理(如 UseStaticFiles
    • 异常处理(如 UseExceptionHandler
    • 日志记录、请求日志
    • 路由匹配(如 UseRouting
    • 自定义业务逻辑(如缓存、请求改写)

三、中间件的执行顺序

  • 关键规则 :顺序至关重要,顺序决定行为,先注册的中间件先执行请求,后执行响应(类似栈结构)。

  • 推荐顺序

    bash 复制代码
    app.UseExceptionHandler();    // 1. 通常放在管道最前端,确保后续中间件的异常被捕获。
    app.UseHttpsRedirection();	  // 2. HTTPS重定向
    app.UseStaticFiles();         // 3. 若请求匹配静态文件,直接响应,终止后续中间件
    app.UseRouting();            // 4. 路由解析
    app.UseAuthentication();      // 5. 身份验证
    app.UseAuthorization();		  // 6. 授权
    app.UseEndpoints(...);        // 7. 终结点处理(如 MVC)

四、中间件的配置方式

1)委托形式(最常见):

  • 示例

    bash 复制代码
    app.Map("/test", async midbuilder => {
        midbuilder.Use(async (context, next) => {
            context.Response.ContentType = "text/html";
            // 处理请求(如记录日志)
            await next.Invoke();// 调用下一个中间件
            // 处理响应(如修改响应头)
        });
        midbuilder.Use(async (context, next) => {        
             // 处理请求
            await next.Invoke();// 调用下一个中间件
            // 处理响应
        });
        midbuilder.Run(async context => {        
            await context.Response.WriteAsync("run<br/>");
        });
    
    });

2)类形式:

  • 实现

    bash 复制代码
     public class RequestTimeMiddleware
     {
         private readonly RequestDelegate next;
         public RequestTimeMiddleware(RequestDelegate next)
         {
             this.next = next;
         }
    
         public async Task InvokeAsync(HttpContext context)
         {
             var start = DateTime.Now;
             await next(context);
             var duration = DateTime.Now - start;
             await context.Response.WriteAsync($"Time {duration.TotalMilliseconds}ms</br>");
      
         }
     }
  • 注册中间件

    bash 复制代码
    app.UseMiddleware<RequestTimeMiddleware>();

五、核心方法

  • Use:添加可传递请求到下一个中间件的组件。

    bash 复制代码
     midbuilder.Use(async (context, next) => {        
    	         // 处理请求
    	        await next.Invoke();// 调用下一个中间件
    	        // 处理响应
    	    });
  • UseWhen:根据条件动态选择中间件。

    bash 复制代码
    app.UseWhen(context => context.Request.Headers.ContainsKey("X-Custom-Header"), 
    branch => branch.UseMiddleware<CustomHeaderMiddleware>());
  • Run :添加终止中间件(不调用 next)。

    bash 复制代码
    app.Run(async context => 
    {
        await context.Response.WriteAsync("Hello World");
    });
  • Map:根据请求路径分支管道。

    bash 复制代码
    app.Map("/admin", adminApp =>
    {
        adminApp.UseAuthentication();
        adminApp.UseAuthorization();
    });
  • 完整示例

    bash 复制代码
    app.Map("/test", async midbuilder => {
        midbuilder.Use(async (context, next) => {
            context.Response.ContentType = "text/html";
            // 处理请求(如记录日志)
            await next.Invoke();// 调用下一个中间件
            // 处理响应(如修改响应头)
        });
        midbuilder.Use(async (context, next) => {        
             // 处理请求
            await next.Invoke();// 调用下一个中间件
            // 处理响应
        });
        midbuilder.Run(async context => {        
            await context.Response.WriteAsync("run<br/>");
        });
    
    });

六、注意事项

  • 静态文件中间件应在路由前注册,避免路由匹配影响性能。
  • 日志中间件若需记录完整处理时间,需放在异常处理之后,确保异常处理后的响应时间也被记录。
  • 使用next()时,若后续中间件抛出异常,异常会向上冒泡到已执行过的中间件中,需合理使用try-catch。

七、中间件 vs 过滤器(Filter)

  • 中间件:作用于整个请求管道,与 MVC 无关(更底层)。

  • 过滤器:专为 MVC 设计,处理 Controller/Action 特定逻辑(如模型绑定、权限校验)。


总结

中间件是 ASP.NET Core 请求处理的核心机制,通过管道式设计实现高度模块化和灵活的 HTTP 处理逻辑。理解其顺序性和短路机制是构建高效应用的关键。

相关推荐
钟离墨笺21 分钟前
Go 语言-->指针
开发语言·后端·golang
时光追逐者38 分钟前
C#/.NET/.NET Core技术前沿周刊 | 第 48 期(2025年7.21-7.27)
c#·.net·.netcore·.net core
前端梭哈攻城狮41 分钟前
dify二开示例
前端·后端·python
该用户已不存在43 分钟前
Node.js 真的取代了PHP吗?
前端·后端·node.js
二闹1 小时前
OpenCV识物:用代码“认出”物体
后端·opencv
花落人散处1 小时前
SpringAI——接入高德MCP服务
java·后端
超浪的晨1 小时前
Java 代理机制详解:从静态代理到动态代理,彻底掌握代理模式的原理与实战
java·开发语言·后端·学习·代理模式·个人开发
天天摸鱼的java工程师1 小时前
🧠 MySQL 索引结构有哪些?优缺点是什么?【原理 + 场景实战】
java·后端·面试
阿宙ppppp1 小时前
基于yolov5+LPRNet+flask+vue的车牌识别(1)
后端·图像识别
Java水解2 小时前
Spring AI模块化RAG架构解析:三阶段设计与实现详解
后端·spring