.NET Core API属性路由失效求助:Hosted Blazor WASM服务端路由异常
解决Hosted Blazor WASM服务端Attribute Routing路由不匹配问题
问题现象
在Hosted Blazor WASM项目中,服务端控制器的Attribute Routing出现异常:
[Route("api/{controller}")]可正常匹配https://localhost:7237/api/pages/[Route("api/{controller}/{action}")]无法匹配https://localhost:7237/api/pages/something,请求被路由到回退的index.html
原因分析
- 路由模板中的
{action}默认会尝试匹配控制器方法的名称,但你的方法名为Get,请求URL中的something并非方法名,导致路由无法匹配到目标方法,最终触发回退规则。 [ApiController]特性启用了路由的严格匹配规则,进一步放大了这种不匹配的问题。
解决方案
方案一:修改路由模板参数名
将路由模板中的{action}改为自定义参数名,避免与方法名匹配逻辑冲突:
[ApiController] public class PagesController : ControllerBase { public PagesController() { } [HttpGet] [Route("api/{controller}")] [Route("api/{controller}/{actionName}")] [Route("api/{controller}/{actionName}/{param}")] public async Task<PageVm> Get(string controller, string? actionName, string? param, string? WebsiteId) { DomainLogic dl = new DomainLogic(); PageVm PageVm = new PageVm(); PageVm.WebsiteId = await dl.GetWebsiteIdFromDomainAsync(db, Request); Console.WriteLine($"{controller} Get() was called with action: {actionName}"); return PageVm; } }
修改后访问https://localhost:7237/api/pages/something,actionName参数会被正确赋值为something,路由可匹配到Get方法。
方案二:显式绑定路由参数并添加可选约束
保留{action}参数名,通过[FromRoute]显式绑定并添加可选约束,避免与方法名匹配:
[ApiController] public class PagesController : ControllerBase { public PagesController() { } [HttpGet] [Route("api/{controller}")] [Route("api/{controller}/{action?}")] [Route("api/{controller}/{action?}/{param?}")] public async Task<PageVm> Get(string controller, [FromRoute] string? action, [FromRoute] string? param, string? WebsiteId) { DomainLogic dl = new DomainLogic(); PageVm PageVm = new PageVm(); PageVm.WebsiteId = await dl.GetWebsiteIdFromDomainAsync(db, Request); Console.WriteLine($"{controller} Get() was called with action: {action}"); return PageVm; } }
?标记参数为可选,[FromRoute]确保参数从路由路径中获取,而非尝试匹配方法名。
方案三:控制器级路由前缀简化配置
在控制器级别添加路由前缀,简化方法路由模板,同时避免冗余参数:
[ApiController] [Route("api/[controller]")] public class PagesController : ControllerBase { public PagesController() { } [HttpGet] [Route("")] // 匹配api/pages [Route("{action}")] // 匹配api/pages/something [Route("{action}/{param}")] // 匹配api/pages/something/123 public async Task<PageVm> Get([FromRoute] string? action, [FromRoute] string? param, string? WebsiteId) { string controller = nameof(PagesController).Replace("Controller", ""); DomainLogic dl = new DomainLogic(); PageVm PageVm = new PageVm(); PageVm.WebsiteId = await dl.GetWebsiteIdFromDomainAsync(db, Request); Console.WriteLine($"{controller} Get() was called with action: {action}"); return PageVm; } }
这种方式更符合ApiController的路由规范,无需手动传递controller参数。
验证方法
修改代码后重启服务,访问https://localhost:7237/api/pages/something,查看控制台是否输出对应日志,确认请求被控制器方法处理而非回退到index.html。
内容的提问来源于stack exchange,提问作者Julian Dormon
相关产品推荐
相关产品推荐

