如何配置Blazor Web API实现传统默认控制器动作路由映射
如何让Blazor Web API实现早期.NET Framework风格的默认路由映射
问题场景
现有UserController代码如下:
[Route("api/[controller]")] [ApiController] public class UserController : Controller { private readonly IHttpContextAccessor httpContextAccessor; private readonly IConfiguration configuration; public UserController(IHttpContextAccessor httpContextAccessor) { this.httpContextAccessor = httpContextAccessor; } [HttpGet] [Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)] [Route("GetUserName")] public String GetUserName() { return httpContextAccessor!.HttpContext!.User?.Identity?.Name?; } }
核心诉求:
- 移除控制器上的
[Route("api/[controller]")]和动作方法上的[Route("GetUserName")]特性后,依然可以通过.../user/getusername路径正常访问接口 - 后续新增控制器和方法时,无需手动标注任何
[Route("xxx")]特性,路由自动按照「控制器名/动作名」的默认规则完成映射
之前尝试在配置中添加MapDefaultControllerRoute()未生效:
app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); });
问题原因
MapDefaultControllerRoute()属于传统约定路由,.NET Core/.NET 5+ 中标记了[ApiController]特性的控制器,默认会强制启用特性路由规则,完全忽略约定路由配置,这是配置不生效的核心原因。
可行解决方案
按以下步骤配置即可实现需求:
- 注册控制器服务时,关闭
[ApiController]强制特性路由的默认约定
原代码中注入了IHttpContextAccessor,该服务默认不会自动注册,需要手动添加。// Program.cs 服务配置阶段 builder.Services.AddHttpContextAccessor(); // 手动注册IHttpContextAccessor builder.Services.AddControllers(options => { // 关键配置:关闭ApiController自动应用特性路由的约定 options.SuppressApiControllerAttributeRouteConvention = true; }); - 配置约定路由中间件
如果不需要统一的api前缀,直接保留默认路由配置即可,路径会自动匹配{controller}/{action}格式:app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); // 如果需要统一加api前缀,替换为以下配置,路径匹配格式为api/{controller}/{action} // endpoints.MapControllerRoute( // name: "default", // pattern: "api/{controller=User}/{action=GetUserName}/{id?}"); }); - 清理控制器上的冗余路由特性
- 移除控制器类上的
[Route("api/[controller]")]特性 - 移除Action方法上的
[Route("GetUserName")]特性 - 如需限定请求方法,可保留
[HttpGet]/[HttpPost]等特性,注意不要给这些特性传入路由模板参数,否则会覆盖约定路由 - 修复原代码中
GetUserName方法返回值处多余的?,否则会编译报错,修正后代码:
[ApiController] public class UserController : Controller { private readonly IHttpContextAccessor httpContextAccessor; public UserController(IHttpContextAccessor httpContextAccessor) { this.httpContextAccessor = httpContextAccessor; } [HttpGet] [Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)] public String GetUserName() { return httpContextAccessor!.HttpContext!.User?.Identity?.Name; } } - 移除控制器类上的
匹配规则说明
- 控制器名必须以
Controller结尾,路由匹配时会自动去掉Controller后缀,大小写不敏感,比如UserController对应路由段user - 方法名直接作为路由的第二段,大小写不敏感,比如
GetUserName方法对应路由段getusername - 路由模板中默认带可选
id参数,对应方法中名为id的参数会自动从路由段绑定,无需额外配置
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

