当我有多个版本的 API 时,如何填充 swagger 文档的基本路径?

How can I populate the basepath of a swagger document when I have multiple versions of my API?

我正在使用 Swashbuckle.AspNetCore 来生成我的 swagger 文档,我正在使用 ApiVersion 来对我的控制器进行版本控制。我的设置支持多个版本,这很好用。这意味着我可以 select Swagger UI 中的一个版本,并且我为我的每个版本创建了一个 swagger 文档,只有相关的操作。

不过,我想重构swagger文档,以便更好地利用basepath-属性.

例如,让我使用为我的 API 版本 1 生成的 swagger 文档。在本文档中,所有路径都是以"/api/v1/..."开头,生成的swagger文档中没有basepath。然而,我 喜欢的是,我的所有路径都以 "/..." 开头,并且生成的文档包含一个基本路径 属性,其值为 "/api/v1".

我已经尝试创建一个 DocumentFilter,这让我很接近,但不是所有的方式。没错,我可以访问 GroupName 属性(其中包含版本字符串“v1”),但我的谓词显然失败了,因为 swaggerDoc.Info.Version 的值为“1.0”。这就是 class 今天的样子:

public class SetBasePath : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.BasePath = $"/{context.ApiDescriptionsGroups.Items.Where(i => i.GroupName == swaggerDoc.Info.Version).Single().GroupName}";
    }
}

然后我尝试了另一种方法,使用PreSerializeFilters首先将基本路径添加到swagger文档中,然后再次从文档中的路径中删除它。这也让我非常接近,但失败了,因为 PreSerializeFilters 不是针对每个 swagger 文档执行,而是执行一次(因此指定的最后一个基本路径将用于所有生成的文档)。这是我使用 PreSerializeFilters:

的代码
app.UseSwagger(c =>
{
    foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
    {
        var basepath = $"/api/{description.GroupName}";

        c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
        {
            swaggerDoc.Host = httpReq.Host.Value;
            swaggerDoc.BasePath = basepath;
        });

        c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
        {
            IDictionary<string, PathItem> paths = new Dictionary<string, PathItem>();
            foreach (var path in swaggerDoc.Paths)
            {
                paths.Add(path.Key.Replace(basepath, string.Empty, StringComparison.InvariantCulture), path.Value);
            }
            swaggerDoc.Paths = paths;
        });
    }
});

谁能帮我走完最后一英里,让我按照我喜欢的方式工作?

有几种方法可以使 ApiDescription 对象与 Swagger 文档版本相匹配。您无法安全地反转 Swagger 文档版本;但是,由于您一开始就可以控制创建它,因此匹配起来并不难。您可能正在使用示例行为,它看起来像:

new Info() { Version = description.ApiVersion.ToString() }

使用提供的扩展方法,您可以像这样在文档过滤器中匹配它:

public class SetBasePath : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        var docVersion = swaggerDoc.Info.Version;
        var groupName = (from descriptionGroup in context.ApiDescriptionGroups.Items
                         from description in descriptionGroup.Items
                         let apiVersion = description.GetApiVersion().ToString()
                         where apiVersion == docVersion
                         select descriptionGroup.GroupName).First();

        swaggerDoc.BasePath = "/api/" + groupName;
    }
}

希望对您有所帮助。