.NET Core中间件中如何始终获取端点的HTTP动词属性
解决方案
要在405场景下获取目标端点的HTTP方法元数据,关键是从路由匹配的候选端点集合中提取信息,无需反射,性能可控。
实现步骤
- 保持中间件注册顺序:继续将自定义日志中间件放在
UseRouting()之后、UseEndpoints()之前,确保路由匹配已完成。 - 在中间件中获取候选端点:当遇到405错误时,从HttpContext的路由匹配特性中获取所有匹配路径但HTTP方法不匹配的候选端点,从中提取目标端点的元数据。
代码示例
自定义中间件核心逻辑
public async Task InvokeAsync(HttpContext context) { // 先执行后续中间件流程 await _next(context); // 处理响应阶段的日志收集 var currentEndpoint = context.GetEndpoint(); // 判断当前是否是405错误对应的端点 if (currentEndpoint?.Metadata.GetMetadata<IStatusCodeHttpResult>() is { StatusCode: 405 }) { // 获取路由匹配特性,该特性包含路径匹配但方法不匹配的候选端点 var matchingFeature = context.Features.Get<Microsoft.AspNetCore.Routing.Matching.IEndpointMatchingFeature>(); if (matchingFeature?.CandidateEndpoints != null) { // 遍历候选端点,提取HTTP方法元数据 foreach (var candidateEndpoint in matchingFeature.CandidateEndpoints) { var httpMethodMetadata = candidateEndpoint.Metadata.GetMetadata<HttpMethodMetadata>(); if (httpMethodMetadata != null) { // 此处拿到目标端点定义的HTTP方法集合,比如["POST"] var allowedMethods = httpMethodMetadata.HttpMethods; // 执行日志记录逻辑,比如记录该端点允许的请求方法为POST } } } } else { // 正常请求场景,直接从当前端点提取元数据 var httpMethodMetadata = currentEndpoint?.Metadata.GetMetadata<HttpMethodMetadata>(); if (httpMethodMetadata != null) { // 处理正常请求的日志逻辑 } } }
关键说明
IEndpointMatchingFeature是路由匹配完成后自动添加到HttpContext的特性,存储了所有匹配请求路径但因HTTP方法不匹配被排除的候选端点。HttpMethodMetadata直接封装了端点定义的HTTP方法信息,无需反射即可读取,性能高效,适合高并发日志场景。- 405场景下,候选端点集合中就是原本应该匹配的目标端点,从中提取
HttpMethodMetadata即可拿到[HttpPost]对应的方法定义。
额外优化
如果需要精准定位目标端点,可结合候选端点的RoutePattern与当前请求路径做进一步匹配,但大多数业务场景下,候选端点集合中只会存在一个路径完全匹配的端点,直接取第一个即可满足需求。
内容的提问来源于stack exchange,提问作者kdeez
相关产品推荐
相关产品推荐

