当前位置: 首页 > news >正文

ASP.NET Core 中间件

一、什么是中间件?

  • 中间件 是一种装配到 ASP.NET Core 应用程序请求处理管道中的软件组件,用于处理 HTTP 请求和响应。
    在这里插入图片描述

  • 每个中间件组件可以:

    • 选择是否将请求传递到下一个中间件:通过调用 next() 或者不调用 next() 来决定是否将请求继续传递给下一个中间件。

    • 在传递前后执行某些操作:可以在将请求传递给下一个中间件之前或者之后执行一些自定义逻辑。

    • 请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

  • 中间件的作用:中间件比筛选器更底层和更上游,是一种性能更高、适用范围更广的面向切面技术,可处理如网关、URL 转发、限流等复杂操作。
    在这里插入图片描述

二、常见的中间件

1. 所有请求返回同一个结果

  • 这个中间件会对所有请求返回相同的响应内容,不论请求的 URL 是什么。
app.Run(async context =>
{await context.Response.WriteAsync("Hello world!");  // 所有请求的响应内容
});

2. 拦截所有请求

  • 通过 app.Use 方法可以拦截所有请求,并在处理请求时进行一些操作,例如设置统一的 HTTP 头信息。
app.Use(async (context, next) =>
{context.Response.Headers["framework"] = "Furion";  // 设置自定义响应头await next.Invoke();  // 将请求传递给下一个中间件
});

3. 特定路由中间件

  • 这个中间件仅对特定的 URL 路径进行处理,例如 /hello
app.Map("/hello", app => {app.Run(async context =>{await context.Response.WriteAsync("Map Test 1");  // 仅对 /hello 路径进行处理});
});

4. 嵌套路由中间件

  • 中间件可以嵌套使用,根据不同的路由层级进行处理,例如处理 /level1/level2a/level1/level2b 路径的请求。
app.Map("/level1", level1App => {level1App.Map("/level2a", level2AApp => {level2AApp.Run(async context =>{await context.Response.WriteAsync("Map Level 2A");});});level1App.Map("/level2b", level2BApp => {level2BApp.Run(async context =>{await context.Response.WriteAsync("Map Level 2B");});});
});

三、自定义中间件

1. 通过 app.Use 定义中间件

  • 这是定义中间件的最简单方式,但通常不推荐用于复杂场景。可以直接在 app.Use 内部编写中间件逻辑。
app.Use(async (context, next) =>
{var cultureQuery = context.Request.Query["culture"];  // 获取请求中的 culture 查询参数if (!string.IsNullOrWhiteSpace(cultureQuery)){var culture = new CultureInfo(cultureQuery);CultureInfo.CurrentCulture = culture;  // 设置当前文化信息CultureInfo.CurrentUICulture = culture;  // 设置当前 UI 文化信息}await next(context);  // 将请求传递给下一个中间件
});

2. 通过独立类定义中间件(推荐)

  • 创建一个独立的中间件类,并通过 app.UseMiddleware 方法来使用这个中间件。这种方式便于复用和维护。
public class RequestCultureMiddleware
{private readonly RequestDelegate _next;public RequestCultureMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context){var cultureQuery = context.Request.Query["culture"];  // 从查询字符串中获取文化信息if (!string.IsNullOrWhiteSpace(cultureQuery)){var culture = new CultureInfo(cultureQuery);CultureInfo.CurrentCulture = culture;  // 设置当前线程的文化信息CultureInfo.CurrentUICulture = culture;  // 设置当前线程的 UI 文化信息}await _next(context);  // 将请求传递给下一个中间件}
}// 扩展方法
public static class RequestCultureMiddlewareExtensions
{public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder){return builder.UseMiddleware<RequestCultureMiddleware>();  // 使用自定义中间件}
}// 使用中间件
app.UseRequestCulture();

3. 配置更多参数

  • 中间件可以接收更多的构造参数,包括依赖注入的服务和普通参数。
public class RequestCultureMiddleware
{private readonly RequestDelegate _next;private readonly ILogger<RequestCultureMiddleware> _logger;public RequestCultureMiddleware(RequestDelegate next, ILogger<RequestCultureMiddleware> logger, int age, string name){_next = next;_logger = logger;}public async Task InvokeAsync(HttpContext context){_logger.LogInformation("Executing middleware for {Name} who is {Age} years old.", name, age);  // 使用日志记录操作信息await _next(context);  // 继续执行下一个中间件}
}// 扩展方法
public static class RequestCultureMiddlewareExtensions
{public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, int age, string name){return builder.UseMiddleware<RequestCultureMiddleware>(new object[] { age, name });  // 传递参数到中间件}
}// 使用中间件
app.UseRequestCulture(30, "百小僧");

四、中间件的顺序

  • 中间件的执行顺序 是至关重要的,它决定了每个中间件在请求处理管道中的位置。中间件按照它们在代码中注册的顺序依次执行,先注册的中间件先执行,后注册的中间件后执行。因此,顺序的安排会直接影响到应用的行为。

五、依赖注入/解析服务

  • 中间件可以通过构造函数注入服务,也可以在中间件内部通过 HttpContext.RequestServices 解析服务。这样可以在中间件中使用已经注册的服务。
public class RequestCultureMiddleware
{private readonly RequestDelegate _next;private readonly ILogger<RequestCultureMiddleware> _logger;public RequestCultureMiddleware(RequestDelegate next, ILogger<RequestCultureMiddleware> logger){_next = next;_logger = logger;}public async Task InvokeAsync(HttpContext context){var repository = context.RequestServices.GetService<IRepository>();  // 解析服务await _next(context);  // 继续执行下一个中间件}
}

六、删除特定的 HTTP 响应头

  • 可以通过中间件删除或修改 HTTP 响应头。例如,删除默认添加的响应头信息。
app.Use(async (context, next) =>
{context.Response.Headers.Remove("Server");  // 删除 Server 响应头await next();  // 继续执行下一个中间件
});

七、常见问题

  • 在中间件中获取终点路由的特性或其他信息时,可以通过以下方式实现:
var endpointFeature = context.Features.Get<IEndpointFeature>();  // 获取终点特性
var attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata<YourAttribute>();  // 获取自定义的特性
  • 需要注意的是,这种操作必须在 UseRouting()UseEndpoints() 之间的中间件中调用,才能确保路由信息已经解析。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 制造业必看!推荐几款设备管理软件,产品特点一目了然!
  • 用EA和SysML一步步建模(06)使命声明-解构需求02
  • 【数据结构】希尔排序(缩小增量排序)
  • 进程调度相关
  • 构建数字化时代的企业:数据驱动的信息架构战略
  • python实现插入排序算法
  • 高防IP是如何防御攻击
  • 【C++登堂入室】类和对象(中)——类的6个默认成员函数
  • SprinBoot+Vue民宿预约微信小程序的设计与实现
  • [数据集][目标检测]智慧农业草莓叶子病虫害检测数据集VOC+YOLO格式4040张9类别
  • 基于springboot的甜鱼闲置物品交易网站的设计与实现---附源码77155
  • 再次进阶 舞台王者 第八季完美童模全球赛品牌大使【韩嘉滢】赛场秀场超燃合集!
  • Playwright 自动化验证码教程
  • ansible_find模块
  • 计算机三级 - 数据库技术 - 第十三章 大规模数据库架构 笔记
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • [数据结构]链表的实现在PHP中
  • 【刷算法】从上往下打印二叉树
  • 30天自制操作系统-2
  • Akka系列(七):Actor持久化之Akka persistence
  • Android优雅地处理按钮重复点击
  • C++11: atomic 头文件
  • Elasticsearch 参考指南(升级前重新索引)
  • ES6语法详解(一)
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Js基础知识(一) - 变量
  • Just for fun——迅速写完快速排序
  • linux学习笔记
  • PAT A1120
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • python3 使用 asyncio 代替线程
  • SOFAMosn配置模型
  • vue的全局变量和全局拦截请求器
  • Yii源码解读-服务定位器(Service Locator)
  • 和 || 运算
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 批量截取pdf文件
  • 数组大概知多少
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #define 用法
  • (3)nginx 配置(nginx.conf)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (搬运以学习)flask 上下文的实现
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (数据结构)顺序表的定义
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (未解决)macOS matplotlib 中文是方框
  • (学习日记)2024.01.19
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。