Мак*_*вой 3 c# asp.net-core asp.net-core-webapi asp.net-core-routing
我在我的项目中使用https://github.com/ardalis/ApiEndpoints(每个控制器一个操作),但我遇到了[Route("[controller]")]不太适合我的问题,因为控制器如下所示:

我需要类似的东西[Route("[namespace]")],但 ASP.NET Core 不支持它。
有没有办法在 中添加自定义路由令牌解析Startup.cs?
到目前为止我的解决方案:
Route属性的源生成器。非常感谢@Kahbazi 为我指明了正确的方向!
这是我想出的:
private class CustomRouteToken : IApplicationModelConvention
{
private readonly string _tokenRegex;
private readonly Func<ControllerModel, string?> _valueGenerator;
public CustomRouteToken(string tokenName, Func<ControllerModel, string?> valueGenerator)
{
_tokenRegex = $@"(\[{tokenName}])(?<!\[\1(?=]))";
_valueGenerator = valueGenerator;
}
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
string? tokenValue = _valueGenerator(controller);
UpdateSelectors(controller.Selectors, tokenValue);
UpdateSelectors(controller.Actions.SelectMany(a => a.Selectors), tokenValue);
}
}
private void UpdateSelectors(IEnumerable<SelectorModel> selectors, string? tokenValue)
{
foreach (var selector in selectors.Where(s => s.AttributeRouteModel != null))
{
selector.AttributeRouteModel.Template = InsertTokenValue(selector.AttributeRouteModel.Template, tokenValue);
selector.AttributeRouteModel.Name = InsertTokenValue(selector.AttributeRouteModel.Name, tokenValue);
}
}
private string? InsertTokenValue(string? template, string? tokenValue)
{
if (template is null)
{
return template;
}
return Regex.Replace(template, _tokenRegex, tokenValue);
}
}
Run Code Online (Sandbox Code Playgroud)
配置令牌Startup.cs(可以将其包装在扩展方法中):
services.AddControllers(options => options.Conventions.Add(
new CustomRouteToken(
"namespace",
c => c.ControllerType.Namespace?.Split('.').Last()
));
Run Code Online (Sandbox Code Playgroud)
之后自定义令牌可用于路由:
[ApiController]
[Route("api/[namespace]")]
public class Create : ControllerBase {}
Run Code Online (Sandbox Code Playgroud)
[ApiController]
public class Get : ControllerBase
{
[HttpGet("api/[namespace]/{id}", Name = "[namespace]_[controller]")]
public ActionResult Handle(int id) {}
}
Run Code Online (Sandbox Code Playgroud)