You need to enable JavaScript to run this app. .Net Core 5.0应用Swagger版本配置异常:路由格式不符、版本切换未过滤端点
优惠活动
大模型
产品
解决方案
定价
更多

.Net Core 5.0应用Swagger版本配置异常:路由格式不符、版本切换未过滤端点

版本化Swagger配置修复方案

你遇到的两个异常都来自现有配置和逻辑的匹配缺陷,逐点调整即可正常运行:

问题a:Swagger路由版本显示为/api/v1/... 而非预期的/api/v1.0/...

  • 根因是AddVersionedApiExplorer 的版本格式化规则不匹配:设置的o.GroupNameFormat = "'v'VVV" 中,VVV 是简化版本格式,会把1.0、2.0这类次版本为0的版本截断为纯主版本数字,最终渲染为v1而非v1.0。
  • 修复方式:将格式化规则替换为可保留完整次版本号的配置:o.GroupNameFormat = "'v'VVV[.FFF]",该规则会完整渲染带小数点的版本值,不会自动截断版本号。
  • 补充:你之前注释掉的两个Swagger过滤器可以直接启用,能解决路由版本参数残留的问题,对应的实现代码如下:
    // 从Swagger请求参数列表中移除路由自带的version占位符参数
    public class SwaggerRemoveVersionFromParameter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var versionParam = operation.Parameters.FirstOrDefault(p => p.Name == "version");
            if (versionParam != null)
                operation.Parameters.Remove(versionParam);
        }
    }
    
    // 把路由占位符中的{version}替换为当前文档对应的实际版本值
    public class SwaggerReplaceVersionWithExactValueInPath : IDocumentFilter
    {
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
            var allPaths = swaggerDoc.Paths.Keys.ToList();
            foreach (var oldPath in allPaths)
            {
                var newPath = oldPath.Replace("v{version}", $"v{context.ApiDescription.GroupName}");
                swaggerDoc.Paths[newPath] = swaggerDoc.Paths[oldPath];
                swaggerDoc.Paths.Remove(oldPath);
            }
        }
    }
    
    把之前注释的两行过滤器配置打开即可:
    c.OperationFilter<SwaggerRemoveVersionFromParameter>();
    c.DocumentFilter<SwaggerReplaceVersionWithExactValueInPath>();
    

问题b:Swagger下拉切换版本时,所有端点混合展示,无法按版本过滤

  • 根因是自定义的DocInclusionPredicate 匹配逻辑存在缺陷:
    现有逻辑只提取了控制器类上标注的ApiVersion属性,完全没有匹配Action方法自身的版本标注。加上你的控制器同时标注了v1.0、v2.0两个版本,所有挂在这个控制器下的Action不管自身标注了什么版本,都会被判定为同时属于两个版本的端点,最终所有端点都会出现在每个版本的展示列表里。
  • 修复方式:重写DocInclusionPredicate 的匹配逻辑,同时识别控制器级、Action级的版本标注,并且匹配端点实际归属的API版本:
    c.DocInclusionPredicate((docName, apiDesc) =>
    {
        if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
        // 同时收集控制器和Action上标注的所有API版本
        var allDefinedVersions = methodInfo.DeclaringType.GetCustomAttributes(true)
            .Concat(methodInfo.GetCustomAttributes(true))
            .OfType<ApiVersionAttribute>()
            .SelectMany(attr => attr.Versions);
        // 获取当前端点实际归属的API版本
        var endpointApiVersion = apiDesc.GetApiVersion();
        if (endpointApiVersion == null) return false;
        // 匹配文档名和端点所属版本
        return allDefinedVersions.Any(v => $"v{v}" == docName) 
               && $"v{endpointApiVersion}" == docName;
    });
    
  • 额外注意:当前配置开启了AssumeDefaultVersionWhenUnspecified = true,这个规则会让没有显式标注版本的Action自动归类到默认的v1.0版本,也是你看到所有标了v2.0的端点全跑到v1.0分组下的重要诱因。如果所有Action都已经显式标注了版本属性,建议将该配置关闭,避免未标注属性的端点被错误归类到默认版本下。

内容的提问来源于stack exchange,提问作者Mark and Mollie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 23:24:02