如何在.Net Core 中使用 NSwag 阻止默认 api 版本显示在 swagger 文档中?

问题描述 投票:0回答:3

在 .net core 中通过以下方式修复 Api 版本控制后

            services.AddApiVersioning(options =>
            {
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
                options.UseApiBehavior = false; //If true [ApiController] attribute required for versioning
            })
            .AddVersionedApiExplorer(options =>
            {
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

我面临的下一个问题是默认 api 版本显示在 swagger 文档中。如下图所示。

有很多文章可以使用 swashbuckle 修复它,但是如何使用 NSwag 修复它?

asp.net-core .net-core swashbuckle nswag api-versioning
3个回答
2
投票

通过 NSwug,我们可以使用 DocumentProcessors,它可用于过滤掉不需要的 swagger 路径。

我使用了下面的nuget包

<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" /> 
<PackageReference Include="NSwag.AspNetCore" Version="13.9.4" />

下面显示了我如何注册它们并解决问题

        public void ConfigureServices(IServiceCollection services)
    {
            ....
            
            services.AddApiVersioning(options =>
            {
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
            })
            .AddVersionedApiExplorer(options =>
            {
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });
            
            services.AddSwaggerDocument(config =>
            {
                SwaggerConfigure(config, "v1", true);
            });

            services.AddSwaggerDocument(config =>
            {
                SwaggerConfigure(config, "v2", false);
            });
    }

SwaggerConfigure 实现

        private void SwaggerConfigure(AspNetCoreOpenApiDocumentGeneratorSettings configure, string version, bool isDefaultVersion)
    {
        configure.DocumentName = version;
        configure.ApiGroupNames = new[] { version };

        if (isDefaultVersion)
        {
            configure.DocumentProcessors.Add(new RemoveVersionFromDefault(version));
        }

        configure.PostProcess = document =>
        {
            document.Info.Version = version;
            document.Info.Title = $"{GetApiTitle()} API";
        };

        configure.AllowNullableBodyParameters = false;
        configure.SerializerSettings = new JsonSerializerSettings();
    }

文档处理器实现

    public class RemoveVersionFromDefault : IDocumentProcessor
    {
    private readonly string _defaultVersion;

    public RemoveVersionFromDefault(string defaultVersion)
    {
        _defaultVersion = defaultVersion;
    }

    public void Process(DocumentProcessorContext context)
    {
        var keys = new List<string>();
        foreach (var (key, value) in context.Document.Paths)
        {
            if (key.Contains($"/{_defaultVersion}/"))
            {
                keys.Add(key);
            }
        }

        foreach (var key in keys)
        {
            context.Document.Paths.Remove(key);
        }
    }
}

就是这样。希望这能帮助正在寻找 NSwug 类似解决方案的人


0
投票

有多种方法可以解决这种情况。另一种方法是创建并注册最后执行的自定义 IApiDescriptionProvider。从提供给 IApiDescriptionProvider.OnProvidersExecuted 上下文的结果

ApiDescription
实例中,您可以找到您要查找的内容并从结果中删除描述符。在这种情况下,您希望删除与 API 版本参数匹配的默认 API 版本的描述符。

这种方法有几个好处:

  1. 可以通过注入获取配置的默认API版本
    IOptions<ApiVersioningOptions>
  2. 您可以使用
    ApiDescriptor.GetApiVersion
    扩展方法来匹配 API 版本,并过滤仍具有 API 版本参数的描述符。您可以对名称进行硬编码,或者从步骤 1 中注入的
    ApiVersioningOptions.RouteConstraintName
    中获取它。无需 magic string 解析或匹配。
  3. 如果您在 Open API (Swagger) 文档生成器之间切换(例如,从 NSwag 切换到 Swashbuckle,反之亦然),则无需更改其他代码即可解决这种情况

旁白:有关以下的评论:

options.UseApiBehavior = false; //If true [ApiController] attribute required for versioning

不太准确。您可能会得到您想要的结果,但故事还不止于此。这种行为和定制没有很好的记录,几乎没有人改变它。该行为实际上由 IApiControllerSpecificationIApiControllerFilter 控制。默认过滤器实现只运行所有注册的规范,因此没有理由更改它。每个规范定义了控制器是否匹配。有一个与

[ApiController]
匹配的开箱即用规范,但这并不是唯一存在的规范(例如:OData 控制器)。
UseApiBehavior
选项存在的原因是因为在
[ApiController]
之前(在2.1中我认为),没有明确的方法来消除仅UI控制器和仅API控制器之间的歧义。这确实让一些混合使用两种类型控制器的开发人员感到恼火。相反,按下硬开关来禁用该功能可能会破坏想要该行为的开发人员。将值设置为
false
只会忽略所有过滤并恢复到
[ApiController]
之前的日子,这是在名为 API Behaviours 的功能增强中引入的。如果您决定这样做,新设计允许您更换或创建新规格。它可能不适用于您,但应该知道配置选项不是用于匹配
on
的硬
off
[ApiController]
,并且其他更复杂的控制器过滤也是可能的。


0
投票

这是一个使用 Nswag 的解决方案,我陷入了这个问题,然后通过一些搜索来调查 AddOperationFilter 并解决了问题。希望它对某人有帮助!:)

settings.GeneratorSettings.AddOperationFilter(x =>
{
    if (x.Document.Paths == null) return true;
    var keysToRemove = x.Document.Paths
        .Where(kv => kv.Key.StartsWith("/api/"))
        .Select(kv => kv.Key)
        .ToList();

    foreach (var key in keysToRemove)
    {
        x.Document.Paths.Remove(key);
    }

    return true;
});
© www.soinside.com 2019 - 2024. All rights reserved.