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

问题描述

我有一个使用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中,但这是一个方法吗?还有什么其他选择?

解决方法

有几种可能性:

  • 使用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 ,但那只会使问题变本加厉。版本控制的目的是使客户可以明确要求他们想要的版本。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...