ASP.NET Core中如何配置控制器与操作以冒号替代斜杠拼接API URL
ASP.NET Core中如何配置控制器与操作以冒号替代斜杠拼接API URL
兄弟,我完全懂你想要的效果——就是让API路由从默认的/api/workflows/:sync变成/api/workflows:sync,用冒号替代控制器和操作之间的斜杠对吧?这个需求其实不难实现,给你两种实用的方法,看你的场景选就行:
方法一:直接指定完整路由模板(快速简单)
如果你的操作不多,或者每个操作的路由规则比较独立,直接在操作方法上写完整的路由模板就完事了,这样能绕开控制器和操作之间的默认斜杠拼接。
比如把你的代码改成这样:
[ApiController] public class WorkflowsController : ControllerBase { // 直接用[controller]令牌自动替换控制器名称,不用硬写 [HttpPost("api/[controller]:sync")] public IActionResult Sync() { return Ok("It worked!"); } }
这样不管你控制器名称改成啥,路由都会自动对应上,比如控制器叫OrdersController,路由就会变成/api/orders:sync,很灵活。
方法二:自定义路由约定(适合多操作场景)
如果你的控制器有很多操作都需要这种冒号拼接的规则,一个个写完整路由太麻烦,那可以自定义一个路由约定,让ASP.NET Core自动处理这种拼接逻辑。
第一步:创建自定义路由约定类
这个类会帮我们修改路由模板的拼接方式,当操作的路由以冒号开头时,直接把它拼在控制器路由后面,不加斜杠:
public class ColonRouteConvention : IApplicationModelConvention { public void Apply(ApplicationModel application) { foreach (var controller in application.Controllers) { // 获取控制器的路由模板 var controllerSelector = controller.Selectors.FirstOrDefault(); if (controllerSelector?.AttributeRouteModel == null) continue; // 清理控制器路由的结尾斜杠,避免重复拼接 var cleanedControllerRoute = controllerSelector.AttributeRouteModel.Template.TrimEnd('/'); // 遍历控制器下的所有操作 foreach (var action in controller.Actions) { foreach (var actionSelector in action.Selectors) { if (actionSelector.AttributeRouteModel == null) continue; var actionRoute = actionSelector.AttributeRouteModel.Template; // 只处理以冒号开头的操作路由 if (actionRoute.StartsWith(":")) { // 合并控制器路由和操作路由,中间不加斜杠 actionSelector.AttributeRouteModel.Template = $"{cleanedControllerRoute}{actionRoute}"; // 清空控制器的路由模板,防止默认拼接逻辑干扰 controllerSelector.AttributeRouteModel = null; } } } } } }
第二步:注册自定义约定
在Program.cs(.NET 6+)或者Startup.cs(.NET 5及更早版本)里,把这个约定添加到MVC的配置中:
// .NET 6+ Program.cs的写法 var builder = WebApplication.CreateBuilder(args); // 添加控制器并注册自定义路由约定 builder.Services.AddControllers(options => { options.Conventions.Add(new ColonRouteConvention()); }); var app = builder.Build(); // 其他中间件配置... app.MapControllers(); app.Run();
第三步:使用原来的代码写法
现在你就可以用最开始的代码写法了,不用做任何修改,路由会自动变成你想要的冒号拼接格式:
[Route("api/[controller]")] public class WorkflowsController : ControllerBase { [HttpPost(":sync")] public IActionResult Sync() { return Ok("It worked!"); } // 再比如另一个操作,也会自动变成/api/workflows:batch [HttpPost(":batch")] public IActionResult BatchProcess() { return Ok("Batch worked!"); } }
这样不管你加多少个操作,只要路由以冒号开头,都会自动用冒号和控制器路由拼接,非常方便。
内容来源于stack exchange
相关产品推荐
相关产品推荐

