ASP.NET Core 路由通过中间件和端点路由实现,自定义主要在 Program.cs 或 Startup.cs 中配置;常用 MapControllerRoute(MVC)、MapRazorPages(Razor Pages)、MapFallbackToController/MapFallback(兜底路由),支持模板占位符、默认值、约束及手动端点注册。

ASP.NET Core 的路由不是靠 web.config 或全局注册表,而是通过中间件和端点路由(Endpoint Routing)机制实现的,自定义路由主要在 Program.cs(.NET 6+)或 Startup.cs(.NET 5 及更早)中配置,核心是控制请求 URL 如何映射到控制器、页面或处理程序。
使用 MapControllerRoute 自定义 MVC 路由
这是最常用的方式,适用于带控制器和动作方法的 Web API 或 MVC 应用。你可以在 AddControllersWithViews() 或 AddMvc() 后,用 MapControllerRoute 添加命名路由模板:
- 路由模板支持占位符,如
{controller}/{action}/{id?},id?表示可选参数 - 可以设置默认值,比如把首页固定指向
Home/Index:routes.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); - 支持多段自定义,例如博客文章路由:
routes.MapControllerRoute("blog-post", "posts/{year:int}/{month:int}/{slug}", new { controller = "Posts", action = "Detail" });
这样访问/posts/2024/04/my-first-post就会调用PostsController.Detail(2024, 4, "my-first-post")
使用 MapRazorPages 自定义 Razor Pages 路由
Razor Pages 默认按文件路径路由(如 /About 对应 Pages/About.cshtml),但你可以用 MapRazorPages() 并配合 PageRouteAttribute 或约定式重写:
- 在 PageModel 类上加
[PageRoute("/news/{id:int}")],即可将/news/123映射到该页面 - 也可在
Program.cs中用endpoints.MapRazorPages().AddPageRoute("/news/{id:int}", "/News/Details");做动态映射 - 注意:Razor Pages 的路由优先级低于 Controller 路由,若两者冲突,需调整注册顺序或使用约束
使用 MapFallbackToController 或 MapFallback 处理未匹配路由
当所有显式路由都不匹配时,可以用“兜底路由”统一处理,比如 SPA 应用需要把前端路由交由客户端接管:
-
endpoints.MapFallbackToController("Index", "Home");把所有未匹配请求转给 Home 控制器的 Index 动作 -
endpoints.MapFallbackToFile("index.html");直接返回静态文件(适合 Vue/React 的 history 模式) - 注意:这类兜底路由必须放在
MapControllerRoute等具体路由之后,否则会提前截断其他匹配
高级:用 IEndpointRouteBuilder 手动添加端点或自定义约束
如果需要更精细控制(如权限判断、动态路由生成、多租户子域名),可以绕过常规路由模板,直接操作 IEndpointRouteBuilder:
- 用
endpoints.MapGet("/api/status", async context => { await context.Response.WriteAsync("OK"); });注册极简端点 - 自定义路由约束继承
IRouteConstraint,比如只允许偶数 ID:public class EvenIdConstraint : IRouteConstraint { public bool Match(...) => id % 2 == 0; }
然后在路由中使用:{id:even}(需先注册约束服务) - 也可以用
MapDynamicControllerRoute实现运行时解析控制器名(如多租户场景)()
基本上就这些。路由配置的关键在于理解端点路由的执行顺序、约束优先级和 MVC/Razor Pages 的差异。不复杂但容易忽略细节,比如路由顺序、参数类型约束、大小写敏感性(默认不敏感),调试时可启用 app.UseRouting(); app.UseEndpoints(...) 日志或查看 EndpointDataSource 实例确认实际注册结果。











