ASP.NET Core属性路由中如何避免{id}类路由参数魔法字符串
规避ASP.NET Core属性路由中参数名魔法字符串的方案
ASP.NET Core 没有内置针对参数名的预设路由令牌,但可以通过以下几种方式规避硬编码的参数名魔法字符串:
- 最简便的方案:使用
nameof编译时常量拼接路由模板
C# 中nameof表达式会在编译时转换为对应变量/成员的字符串字面量,属于合法的属性常量参数,搭配字符串拼接即可实现和[action]令牌类似的重构友好效果。
// 写法1:配合字符串拼接,兼容所有C#版本 [HttpGet] [Route("[action]/" + "{" + nameof(id) + "}")] public IActionResult Foo([FromRoute] int id) { // 其他逻辑 } // 写法2:C# 10+ 支持常量字符串插值,写法更简洁 private const string IdParamName = nameof(id); [HttpGet] [Route($"[action]/{{{IdParamName}}}")] public IActionResult Foo([FromRoute] int id) { // 其他逻辑 }
这种方案的优势是无需额外配置,如果你后续修改方法参数名(比如把id改成userId),IDE重构功能会自动同步nameof对应的值,不会出现路由模板和参数名不匹配的问题,是大多数场景下的首选方案。
- 批量场景:自定义路由约定实现参数令牌
如果你的项目里有大量单路由参数的Action,可以通过实现IApplicationModelConvention自定义路由规则,给路由模板扩展类似[param]的自定义令牌,自动替换为Action的第一个路由参数的名称,示例实现如下:
// 自定义路由约定类 public class CustomRouteTokenConvention : IApplicationModelConvention { public void Apply(ApplicationModel application) { foreach (var controller in application.Controllers) { foreach (var action in controller.Actions) { foreach (var selector in action.Selectors) { if (selector.AttributeRouteModel?.Template == null) continue; // 把模板中的[param]替换为第一个路由参数的名称 var firstRouteParam = action.Parameters.FirstOrDefault(p => p.Attributes.Any(a => a.GetType() == typeof(FromRouteAttribute))); if (firstRouteParam != null) { selector.AttributeRouteModel.Template = selector.AttributeRouteModel.Template.Replace("[param]", "{" + firstRouteParam.ParameterName + "}"); } } } } } }
在Program.cs中注册该约定即可生效:
builder.Services.AddControllers(options => { options.Conventions.Add(new CustomRouteTokenConvention()); });
注册完成后就可以直接使用自定义令牌写路由:
[HttpGet] [Route("[action]/[param]")] public IActionResult Foo([FromRoute] int id) { // 其他逻辑 }
这种方式适合有大量相同规则路由的项目,减少重复代码,但需要额外维护扩展逻辑,小型项目不推荐。
内容的提问来源于stack exchange,提问作者lonix
相关产品推荐
相关产品推荐

