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

如何让无ApiVersion属性的接口始终生成默认版本Swagger文档?

问题:无ApiVersion属性的接口无法在混合版本控制器中生成默认版本Swagger文档

我在使用Asp.Versioning.Mvc.ApiExplorer库构建带版本的Swagger文档时遇到了问题:已经配置了Operation Filter,指定默认Api版本为1.0并开启了AssumeDefaultVersionWhenUnspecified,但当控制器中同时存在带ApiVersion属性和不带该属性的接口时,不带属性的接口不会生成默认版本(1.0)的Swagger文档——只有当控制器里全是无属性接口时,才会生成默认版本文档。我需要让无ApiVersion属性的接口始终生成默认版本的Swagger文档。


相关代码

Operation Filter实现

public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
    var apiDescription = context.ApiDescription;
    operation.Deprecated |= apiDescription.IsDeprecated();

    foreach (var responseType in context.ApiDescription.SupportedResponseTypes)
    {
        var responseKey = responseType.IsDefaultResponse
            ? "default"
            : responseType.StatusCode.ToString();
        var response = operation.Responses[responseKey];

        foreach (var contentType in response.Content.Keys)
        {
            if (!responseType.ApiResponseFormats.Any(x => x.MediaType == contentType))
            {
                response.Content.Remove(contentType);
            }
        }
    }

    if (operation.Parameters == null)
    {
        return;
    }
    
    foreach (var parameter in operation.Parameters)
    {
        var description = apiDescription.ParameterDescriptions
            .First(p => p.Name == parameter.Name);

        parameter.Description ??= description.ModelMetadata?.Description;

        if (parameter.Schema.Default == null && description.DefaultValue != null)
        {
            var json = JsonSerializer.Serialize(
                description.DefaultValue,
                description.ModelMetadata.ModelType);
            parameter.Schema.Default = OpenApiAnyFactory.CreateFromJson(json);
        }

        parameter.Required |= description.IsRequired;
    }
}

测试控制器代码

[ApiController]
[ApiExplorerSettings(GroupName = "Version")]
[Route("version")]
public class VersionController : ControllerBase
{
    /// <summary>
    /// 测试接口(需要生成默认版本1.0的文档,但目前未生成)
    /// </summary>
    /// <response code="200">请求成功</response>
    [HttpGet]
    public async Task<IActionResult> Version1Get()
    {
        return Ok("version1.0 response");
    }
    
    /// <summary>
    /// 测试1.2版本接口
    /// </summary>
    /// <response code="200">请求成功</response>
    [HttpGet]
    [ApiVersion(1.2)]
    public async Task<IActionResult> Version2Get()
    {
        return Ok("version1.2 response");
    }
}

版本配置代码

{
    options.ApiVersionReader = new HeaderApiVersionReader("x-ms-version");

    options.DefaultApiVersion = new ApiVersion(1, 0);
    
    options.ReportApiVersions = true;
    options.AssumeDefaultVersionWhenUnspecified = true;

}).AddMvc().AddApiExplorer(
    options =>
    {
        options.GroupNameFormat = "VV";

        options.FormatGroupName = (group, version) => $"{group} - {version}";
        options.DefaultApiVersion = new ApiVersion(1, 0);

        options.AssumeDefaultVersionWhenUnspecified = true;
    } );

解决方案

这个问题的核心原因是:当控制器中存在带ApiVersion属性的接口时,Asp.Versioning会默认认为该控制器下所有接口都需要显式指定版本,忽略了全局的AssumeDefaultVersionWhenUnspecified配置。以下是两种可行的解决方式:

方法1:控制器级别显式声明支持的版本(官方推荐)

给控制器添加默认版本的ApiVersion属性,并开启AllowMultipleVersions,让无属性的接口自动继承默认版本:

[ApiController]
[ApiExplorerSettings(GroupName = "Version")]
[Route("version")]
[ApiVersion(1.0)] // 显式声明默认版本
[ApiVersion(1.2)] // 声明已存在的1.2版本
[AllowMultipleVersions] // 允许控制器下存在多版本接口
public class VersionController : ControllerBase
{
    // 无ApiVersion属性的接口会自动归到1.0版本
    [HttpGet]
    public async Task<IActionResult> Version1Get()
    {
        return Ok("version1.0 response");
    }
    
    [HttpGet]
    [ApiVersion(1.2)]
    public async Task<IActionResult> Version2Get()
    {
        return Ok("version1.2 response");
    }
}

方法2:自定义OperationFilter补全版本信息

如果不想修改控制器代码,可以通过自定义Filter为无版本属性的接口手动指定默认版本:

public class DefaultVersionOperationFilter : IOperationFilter
{
    private readonly ApiVersion _defaultVersion;

    public DefaultVersionOperationFilter(ApiVersion defaultVersion)
    {
        _defaultVersion = defaultVersion;
    }

    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var apiDescription = context.ApiDescription;
        // 检查接口是否未关联任何版本
        if (!apiDescription.ApiVersionProperties.IsApiVersionNeutral && 
            apiDescription.ApiVersionProperties.ApiVersion == null)
        {
            // 手动设置默认版本
            apiDescription.ApiVersionProperties.ApiVersion = _defaultVersion;
            // 更新Swagger分组名称
            apiDescription.GroupName = $"Version - {_defaultVersion.ToString()}";
        }

        // 执行原有OperationFilter逻辑
        var originalFilter = new YourOriginalOperationFilter();
        originalFilter.Apply(operation, context);
    }
}

然后在Swagger配置中注册该Filter:

services.AddSwaggerGen(options =>
{
    options.OperationFilter<DefaultVersionOperationFilter>(new ApiVersion(1, 0));
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:29:57