.NET 8 MVC中从Uri获取RouteData的替代方案求助
.NET 8 MVC从Uri获取路由值的高效方案(迁移自.NET Framework 4.8)
原.NET Framework 4.8实现
之前在.NET Framework 4.8中,通过自定义HttpContextBase子类模拟请求,调用RouteTable.Routes.GetRouteData获取路由值:
public class GetRouteDataContext : HttpContextBase { public override HttpRequestBase Request { get; } private GetRouteDataContext(Uri uri) { var url = uri.GetLeftPart(UriPartial.Path); var qs = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped); Request = new HttpRequestWrapper(new HttpRequest(null, url, qs)); } public static RouteValueDictionary RouteValuesFromUri(Uri uri) { return RouteTable.Routes.GetRouteData(new GetRouteDataContext(uri)).Values; } }
.NET 8中的适配问题
在.NET 8中,HttpContextBase、HttpRequestBase、HttpRequestWrapper以及RouteTable.Routes.GetRouteData这些旧API已被移除,无法直接复用原有逻辑。
当前实现的问题
你尝试通过EndpointDataSource手动遍历匹配路由的方式存在以下不足:
- 手动遍历所有端点效率低下,路由数量较多时性能损耗明显
- 使用
Contains匹配路径容易误判(比如/Home/Index会错误匹配/Home/IndexTest) - 依赖静态
HttpContext实例存在线程安全风险,服务获取方式不符合ASP.NET Core设计规范
高效替代方案
在.NET 8中,推荐使用内置的RouteMatcher完成路由匹配,它会复用应用已注册的路由规则,无需手动遍历端点。
实现步骤
- 确保项目已在
Program.cs中配置MVC路由(默认模板已包含此配置) - 创建封装路由匹配逻辑的服务类,依赖注入
MatcherFactory和EndpointDataSource:
public class RouteDataResolver { private readonly RouteMatcher _routeMatcher; public RouteDataResolver(MatcherFactory matcherFactory, EndpointDataSource endpointDataSource) { // 基于应用已注册的端点创建路由匹配器 _routeMatcher = matcherFactory.CreateMatcher(endpointDataSource); } public RouteValueDictionary GetRouteValuesFromUri(Uri uri) { var httpContext = new DefaultHttpContext { Request = { Scheme = uri.Scheme, Host = new HostString(uri.Host, uri.Port), Path = new PathString(uri.AbsolutePath), QueryString = QueryString.FromUriComponent(uri) } }; var routeContext = new RouteContext(httpContext); _routeMatcher.Match(routeContext); return routeContext.RouteData?.Values ?? new RouteValueDictionary(); } }
- 在
Program.cs中注册该服务:
builder.Services.AddScoped<RouteDataResolver>();
- 使用示例:在需要的类中注入
RouteDataResolver并调用方法:
public class SampleService { private readonly RouteDataResolver _routeResolver; public SampleService(RouteDataResolver routeResolver) { _routeResolver = routeResolver; } public void ProcessUri(Uri uri) { var routeValues = _routeResolver.GetRouteValuesFromUri(uri); var controllerName = routeValues["controller"]?.ToString(); var actionName = routeValues["action"]?.ToString(); // 执行业务逻辑 } }
方案优势
- 复用应用已有路由规则,匹配逻辑和实际请求完全一致,避免误判
- 内置匹配器性能远高于手动遍历端点
- 依赖注入方式符合ASP.NET Core设计规范,无线程安全风险
内容的提问来源于stack exchange,提问作者Ranjini
相关产品推荐
相关产品推荐

