如何在ASP.NET Core中间件中获取OData请求的RouteData?
解决OData请求在中间件中获取RouteData为null的问题
我之前处理过一模一样的问题,根源其实在中间件的执行顺序上——你的TestMiddleware注册在了OData路由处理中间件之前,这时候OData还没来得及解析请求的路由信息,context.GetRouteData()自然返回null。
核心原因
OData的路由解析逻辑封装在它专属的UseODataRouting()中间件里,这个中间件会负责解析OData格式的请求URL,把路由信息填充到HttpContext的RouteData中。如果你的自定义中间件跑在它前面,此时OData还没处理路由,自然拿不到有效数据。
解决方案1:调整中间件注册顺序(推荐)
最简单有效的办法就是把TestMiddleware放在UseODataRouting()之后注册,让OData先完成路由解析,你的中间件再去获取数据。
修改你的Program.cs(或Startup.cs,取决于.NET版本)中的中间件注册代码:
var app = builder.Build(); // 先注册基础中间件(比如HTTPS重定向、授权等) app.UseHttpsRedirection(); // 优先注册OData路由中间件 app.UseODataRouting(); // 再注册你的自定义TestMiddleware app.UseMiddleware<TestMiddleware>(); app.UseAuthorization(); app.MapControllers(); app.Run();
解决方案2:手动触发OData路由解析(仅用于无法调整顺序的场景)
如果因为项目架构限制不能调整中间件顺序,可以在TestMiddleware里手动调用OData的路由匹配服务,提前完成路由解析:
public class TestMiddleware { protected readonly RequestDelegate _next; public TestMiddleware(RequestDelegate next) { this._next = next; } public virtual async Task Invoke(HttpContext context) { // 从DI容器获取OData路由相关服务 var routeMatcher = context.RequestServices.GetRequiredService<IODataRouteMatcher>(); var odataOptions = context.RequestServices.GetRequiredService<IODataOptions>(); foreach (var routeComponent in odataOptions.RouteComponents) { // 尝试匹配当前请求的OData路由 var routeResult = await routeMatcher.MatchAsync(context, routeComponent.RoutePrefix); if (routeResult != null) { // 将解析后的RouteData赋值给HttpContext context.SetRouteData(routeResult.RouteData); // 同时设置OData路由特性(后续OData组件可能依赖这个) context.Features.Set<IODataRouteFeature>(new ODataRouteFeature { RouteData = routeResult.RouteData, RoutePrefix = routeComponent.RoutePrefix, Model = routeComponent.Model }); break; } } var routeData = context.GetRouteData(); // 现在就能拿到非空值了 await this._next.Invoke(context); } }
验证测试
调整顺序后,再请求http://localhost:40946/odata/Blog,你的TestMiddleware里的routeData应该就能正常获取到OData的路由信息了,比如包含odata路由前缀、控制器名称等内容。
内容的提问来源于stack exchange,提问作者PatrickNolan
相关产品推荐
相关产品推荐

