ASP.NET Core Razor Pages动态路由与物理文件冲突:多端点匹配错误如何解决?
解决ASP.NET Core Razor Pages动态路由端点冲突问题
问题原因
出现The request matched multiple endpoints /Users/Index错误的核心原因:MapRazorPages()会为物理页面/Users/Index.cshtml自动生成默认路由(如/Users/Index或/Users),而你注册的动态路由{**id}会捕获所有请求。当访问/Users/{id}时,动态路由会将请求转换为指向/Users/Index的请求,此时默认路由与动态路由同时匹配同一个端点,导致冲突。
解决方案
方案一:限制动态路由的匹配范围
修改动态路由的模板,仅让其处理/Users/开头的请求,避免干扰其他页面的默认路由逻辑:
修改program.cs中的动态路由注册代码:
// 将原有的{**id}替换为/Users/{**id} app.MapDynamicPageRoute<MyRouteTransformer>("/Users/{**id}");
此时动态路由只会捕获/Users/xxx格式的请求,MyRouteTransformer中的逻辑无需修改——请求/Users/123时,values["id"]会直接获取到123。
方案二:在路由转换器中过滤请求
如果必须保留全局的{**id}动态路由模板,可在MyRouteTransformer中添加过滤逻辑,仅处理特定路径的请求,其他请求返回null交给默认路由处理:
public class MyRouteTransformer : DynamicRouteValueTransformer { public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values) { string path = values["id"] as string; // 仅处理以Users/开头的路径 if (!string.IsNullOrEmpty(path) && path.StartsWith("Users/")) { // 提取Users/后的部分作为id参数 string actualId = path.Substring("Users/".Length); return new RouteValueDictionary() { { "page", "/Users/Index" }, { "id", actualId } }; } // 其他请求返回null,交由默认路由处理 return null; } }
优化建议:使用模型绑定替代直接读取Query
在Razor Pages中,推荐通过模型绑定获取参数,而非直接读取Request.Query,更符合框架规范:
- 在
IndexModel中添加绑定属性:
public class IndexModel : PageModel { // 从路由或查询参数绑定id [FromRoute] public string Id { get; set; } public void OnGet() { // 直接使用Id属性即可 } }
- 在
cshtml中直接引用模型属性:
@page @model RazorTest.Pages.Users.IndexModel <h1>Users!</h1> <h2>@Model.Id</h2>
内容的提问来源于stack exchange,提问作者Pahin
相关产品推荐
相关产品推荐

