如何从非默认版本文档中排除默认API路由版本

时间:2020-10-26 14:52:27

标签: asp.net-core swagger aspnet-api-versioning

我有一个使用aspnet-api-versioning(4.1.1)库进行版本控制的ASP.NET Core(3.1)API。将项目设置为从URL读取版本,如果未指定版本,则使用默认版本(1)。示例控制器支持两个API版本(1和2),并具有两个相同的方法,每个版本一个。由于支持默认版本,因此控制器上有两个Route属性,一个不带版本,一个带属性。

在使用Swashbuckle.AspNetCore(5.6.3)库生成API的OpenAPI文档时,API版本1和2的文档都将包含非版本化路由; “ / Customer / {externalCustomerId}”。要解决的问题是,如何将Swagger生成配置为在默认版本的文档中仅包括非版本化路由?给定以下代码,版本1的文档应为:

  • / Customer / {externalCustomerId}
  • / v1 / Customer / [externalCustomerId}

,版本2的文档应为:

  • / v2 / Customer / {externalCustomerId}

启动:

public class Startup
{
    ... // Removed for brevity. Method below called from ConfigureServices(...).
    private static void ConfigureApiVersioning(IServiceCollection services)
    {
        services.AddVersionedApiExplorer(setup =>
        {
            setup.GroupNameFormat = "'v'V";
            setup.SubstituteApiVersionInUrl = true;
        });

        services.AddApiVersioning(setup =>
        {
            setup.AssumeDefaultVersionWhenUnspecified = true;
            setup.DefaultApiVersion = new ApiVersion(majorVersion: 1, minorVersion: 0);
            setup.ReportApiVersions = true;
            setup.ApiVersionReader = new UrlSegmentApiVersionReader();
        });
    }
}

控制器:

[Route("Customer")]
[Route("v{version:apiVersion}/Customer")]
[ApiVersion("1", Deprecated = true)]
[ApiVersion("2")]
[ApiController]
public class CustomerController : ControllerBase
{
    [HttpGet("{externalCustomerId}")]
    [MapToApiVersion("1")]
    public string Get()
    {
        return "Customer Api v1 responded with 200 ok";
    }

    [HttpGet("{externalCustomerId}")]
    [MapToApiVersion("2")]
    public string GetV2()
    {
        return "Customer Api v2 responded with 200 ok";
    }
}

可以(应该)使用SwaggerGenOptions.DocInclusionPredicate()解决吗?我试了一下,但找不到从谓词的ApiVersion获取默认API版本的方法。

一个选项可能是从DefaultApiVersionDescriptionProvider继承(或实现IApiVersionDescriptionProvider)以访问Options属性,这将使我们能够获取默认的API版本并使用带闭包的谓词在SwaggerGenOptions.DocInclusionPredicate()的Startup中,但这是一个好方法吗?还有什么其他选择?

1 个答案:

答案 0 :(得分:0)

有几种可能性:

  • 使用DocInclusionPredicate
  • 使用自定义的 IOperationFilter
  • 使用自定义的 IApiDescriptionProvider

第一个可能是最简单的。由于所有版本正确的路由都具有route参数,因此您只需要排除所有包含该参数的路由即可。像这样:

c.DocInclusionPredicate((d, api) => !api.RelativePath.Contains("v{version:apiVersion}"))

您需要删除/禁用options.SubstituteApiVersionInUrl;您还是不使用它。

您应该仔细考虑您的API文档所传达的内容;这是误导。 OpenAPI / Swagger文档将显示2.0的正确路由;但是,当客户请求时,他们将获得1.0。发生这种情况是因为您未指定任何版本,并且您假设使用1.0。您可以使用备用的 IApiVersionSelector ,例如 CurrentImplementationApiVersionSelector ,但那只会使问题变本加厉。版本控制的目的是使客户可以明确要求他们想要的版本。