我有一个 ASP.NET Core 6 Web API 项目。一些端点与名称由多个单词组成的控制器相关,因此按照 .NET 中的约定采用 PascalCase 格式。假设我有一个
PackageGroupsController
。我希望它的路线是 /package-groups
而不是默认的 /PackageGroups
并且我不想为每个控制器指定硬编码路线。我怎样才能使用全局配置或其他东西来实现这一点?
AddControllers
允许您自定义所使用的约定,您可以尝试使用带有 RouteTokenTransformerConvention
的约定。比如:
builder.Services.AddControllers(opts =>
opts.Conventions.Add(new RouteTokenTransformerConvention(new ToKebabParameterTransformer())));
public class ToKebabParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object? value) => value != null
? Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower() // to kebab
: null;
}
想分享我的实现,并对 Guru Stron 的答案稍加修改。
builder.Services.AddControllers(options =>
options.Conventions.Add(new RouteTokenTransformerConvention(new ToKebabParameterTransformer())));
public partial class ToKebabParameterTransformer : IOutboundParameterTransformer
{
[GeneratedRegex("([a-z])([A-Z])")]
public static partial Regex KebabCaseGeneratedRegex();
public string? TransformOutbound(object? value)
{
if (value is null || value is not string) return null;
return KebabCaseGeneratedRegex().Replace((string)value, "$1-$2").ToLower();
}
}
用法与原答案相同,修改部分如下:
SYSLIB1045
)”
GeneratedRegex
属性中指定模式来解决partial class
is
运算符来处理 null 而不是字符串值我还发现从
ControllerContext
检索到的控制器名称没有被转换,因此必须单独进行转换,类似于下面:
[Route("[controller]")]
public partial class SomeKebabCaseController() : ControllerBase
{
// Included only for demonstration purpose, this should converted to be a utility class or similar to make it reusable
[GeneratedRegex("([a-z])([A-Z])")]
public static partial Regex KebabCaseGeneratedRegex();
[HttpGet]
public IActionResult ControllerName() {
var controllerName = ControllerContext.RouteData.Values["controller"]!.ToString()!;
var formattedControllerName = KebabCaseGeneratedRegex().Replace((string)controllerName, "$1-$2").ToLower();
return Ok(formattedControllerName);
}
}