ASP.NET 6.0 Web API 如何动态配置全局控制器路由前缀
动态全局路由前缀实现方案
[Route]特性的参数要求为编译时常量,无法直接绑定运行时读取的环境变量值,可通过ASP.NET Core应用模型约定实现动态全局路由前缀注入,无需修改现有控制器的路由标记。
实现步骤
- 启动阶段读取环境变量配置
在Program.cs启动初始化阶段,从配置系统读取环境变量中的路由前缀值,提前处理斜杠避免路由格式错误:
var builder = WebApplication.CreateBuilder(args); // 读取环境变量中的路由前缀,环境变量名可自定义,示例为ApiRoutePrefix var globalRoutePrefix = builder.Configuration["ApiRoutePrefix"] ?? string.Empty; // 格式化前缀,去除首尾多余斜杠,避免出现//api/xxx这类错误路由 if (!string.IsNullOrWhiteSpace(globalRoutePrefix)) { globalRoutePrefix = globalRoutePrefix.Trim('/'); }
- 实现全局路由前缀约定
自定义路由约定类,实现IApplicationModelConvention接口,在应用模型加载阶段给所有控制器的路由拼接前缀:
public class GlobalRoutePrefixConvention : IApplicationModelConvention { private readonly AttributeRouteModel _prefixModel; public GlobalRoutePrefixConvention(string routePrefix) { _prefixModel = new AttributeRouteModel(new RouteAttribute(routePrefix)); } public void Apply(ApplicationModel application) { foreach (var controller in application.Controllers) { // 给控制器上已声明的路由特性拼接前缀 var routedSelectors = controller.Selectors .Where(s => s.AttributeRouteModel != null) .ToList(); foreach (var selector in routedSelectors) { selector.AttributeRouteModel = AttributeRouteModel .CombineAttributeRouteModel(_prefixModel, selector.AttributeRouteModel); } } } }
- 注册约定到控制器配置
在AddControllers服务配置中,注册你实现的全局路由约定,原有中间件配置不需要改动:
builder.Services.AddControllers(options => { // 仅当配置了有效前缀时才添加约定 if (!string.IsNullOrWhiteSpace(globalRoutePrefix)) { options.Conventions.Add(new GlobalRoutePrefixConvention(globalRoutePrefix)); } }); var app = builder.Build(); // 原有路由、授权、控制器映射配置保持不变即可 app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();
效果说明
- 现有控制器上的
[Route("[controller]")]标记不需要做任何修改,比如环境变量ApiRoutePrefix值设为prod/api时,DashboardsController的路由会自动生成为prod/api/Dashboards - 该方案不会破坏Action上的路由标记、路由参数、约束等原有配置,所有原有路由规则正常生效
- 配置读取发生在应用启动阶段,修改环境变量后重启应用即可生效,符合ASP.NET Core配置系统的默认运行逻辑
- 如果需要给特定控制器跳过全局前缀,可自定义一个
[SkipGlobalPrefix]特性,在Apply方法中判断控制器是否带该特性,跳过拼接逻辑即可
内容的提问来源于stack exchange,提问作者VahidDev
相关产品推荐
相关产品推荐

