You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

控制器ApiVersion属性能否含下划线?遗留WebAPI适配Swagger问题

嘿,这个问题我刚好踩过坑!核心原因是ASP.NET Core的API版本验证默认遵循语义化版本规范,只认点号分隔的格式(比如1.0),下划线_属于非法字符,所以[ApiVersion("1_0")]会直接抛出异常。下面给你两个可行的解决方案,按需选择:

方案1:自定义API版本解析规则,兼容下划线格式

这个方案是让系统直接识别下划线分隔的版本号,不需要修改现有路由结构。你需要自定义一个版本解析器,把下划线替换成点号后交给默认解析器处理:

// 在Program.cs(或Startup.cs)中配置API版本
builder.Services.AddApiVersioning(options =>
{
    // 替换默认的版本解析器为自定义实现
    options.ApiVersionParser = new UnderscoreApiVersionParser();
    // 开启响应头返回版本信息,方便调试
    options.ReportApiVersions = true;
});

// 自定义版本解析器类
public class UnderscoreApiVersionParser : IApiVersionParser
{
    public bool TryParse(string input, out ApiVersion version)
    {
        // 将下划线替换为点号,适配默认解析规则
        var normalizedVersion = input.Replace('_', '.');
        return ApiVersionParser.Default.TryParse(normalizedVersion, out version);
    }

    public bool IsMatch(string input)
    {
        // 匹配包含下划线的版本号,或者默认格式的版本号
        return input.Contains('_') || ApiVersionParser.Default.IsMatch(input);
    }
}

配置完成后,[ApiVersion("1_0")]就能正常工作,路由里的api/{version}/account也能正确匹配1_0、1_1这类格式的版本号。

方案2:保持ApiVersion用标准格式,路由层做兼容

如果不想修改版本解析规则,你可以在控制器上用标准的点号版本(1.0),但路由路径保留下划线格式,同时配置Swagger关联对应版本:

// 控制器上使用标准ApiVersion格式,路由保留下划线
[ApiVersion("1.0")]
[Route("api/1_0/account")]
public class AccountV10Controller : ControllerBase
{
    // 你的接口方法
    [HttpGet]
    public IActionResult Get() => Ok("V1.0 Account Data");
}

[ApiVersion("1.1")]
[Route("api/1_1/account")]
public class AccountV11Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("V1.1 Account Data");
}

然后配置Swagger,让它正确识别控制器对应的版本文档:

builder.Services.AddSwaggerGen(options =>
{
    // 注册每个下划线版本的Swagger文档
    options.SwaggerDoc("v1_0", new OpenApiInfo { Title = "My Legacy API", Version = "1_0" });
    options.SwaggerDoc("v1_1", new OpenApiInfo { Title = "My Legacy API", Version = "1_1" });

    // 配置文档包含规则,关联控制器的ApiVersion和Swagger文档版本
    options.DocInclusionPredicate((docName, apiDesc) =>
    {
        if (!apiDesc.TryGetMethodInfo(out var methodInfo)) return false;

        // 获取控制器上的ApiVersion属性
        var controllerVersions = methodInfo.DeclaringType
            .GetCustomAttributes<ApiVersionAttribute>(true)
            .SelectMany(attr => attr.Versions);

        // 把Swagger文档的版本(比如v1_0)转成标准格式,和控制器版本匹配
        var targetVersion = docName.Replace("v", "").Replace('_', '.');
        return controllerVersions.Any(v => v.ToString() == targetVersion);
    });
});

额外注意点

  • 如果你使用的是旧版的Microsoft.AspNetCore.Mvc.Versioning包(比如2.x版本),配置方式会略有不同,核心思路还是自定义解析或路由映射。
  • 测试时要确保所有遗留路由(比如/api/1_0/account)都能正常访问,同时Swagger文档能正确展示对应版本的接口。

内容的提问来源于stack exchange,提问作者Rory McCrossan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:46:25