仅在swagger-swashbuckle UI中显示选定的控制器

Sub*_*rel 10 c# swagger swagger-ui swashbuckle

我目前在我的项目中使用招摇,我在那里有超过100个控制器.我想由于控制器数量众多,swagger UI文档页面需要超过5分钟才能加载其控制器.是否可以在UI页面中选择特定控制器并仅为它们加载选项?或者还有其他方法可以更快地加载UI页面?帮我!

小智 10

您可以在任何一个控制器上使用ApiExplorerSettings来完全忽略一个控制器或某个方法。

[ApiExplorerSettings(IgnoreApi = true)]
public class MyController
{
    [ApiExplorerSettings(IgnoreApi = true)]
    public string MyMethod
    {
      ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我需要动态选择控制器。我想在swagger UI中有一个选项,然后在该选项中选择控制器并动态加载它们。可能吗? (2认同)

Ror*_*ory 10

使用swashbuckle的文档过滤器,你可以在事后删除生成的规范的一些元素,然后它们就不会被包含在集成的swagger-ui中.创建一个如下所示的类:

using System;
using System.Web.Http.Description;
using Swashbuckle.Swagger;

internal class SwaggerFilterOutControllers : IDocumentFilter
{
    void IDocumentFilter.Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        foreach (ApiDescription apiDescription in apiExplorer.ApiDescriptions)
        {
            Console.WriteLine(apiDescription.Route.RouteTemplate);

            if ((apiDescription.RelativePathSansQueryString().StartsWith("api/System/"))
                || (apiDescription.RelativePath.StartsWith("api/Internal/"))
                || (apiDescription.Route.RouteTemplate.StartsWith("api/OtherStuff/"))
                )
            {
                swaggerDoc.paths.Remove("/" + apiDescription.Route.RouteTemplate.TrimEnd('/'));
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后编辑您的SwaggerConfig.cs文件以包含过滤器:

        GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                    c.DocumentFilter<SwaggerFilterOutControllers>();
Run Code Online (Sandbox Code Playgroud)

请注意,虽然控制器已从规范中删除,但其他项(如结果模型)仍将包含在规范中,并且可能仍会降低页面加载速度.

它也可能因为首先枚举所有控制器/模型等而变慢,在这种情况下这可能没有帮助.

编辑:我注意到每次查看UI页面时它都会重新生成整个定义(这可能会在您的场景中瘫痪).幸运的是,缓存它非常容易(这应该很好,因为它不应该在运行时为大多数人改变).

将其添加到您的配置:

c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
Run Code Online (Sandbox Code Playgroud)

并从https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Dummy.Core/App_Start/CachingSwaggerProvider.cs无耻地复制使用此类

using Swashbuckle.Swagger;
using System.Collections.Concurrent;

namespace <your namespace>
{
    public class CachingSwaggerProvider : ISwaggerProvider
    {
        private static ConcurrentDictionary<string, SwaggerDocument> _cache =
            new ConcurrentDictionary<string, SwaggerDocument>();

        private readonly ISwaggerProvider _swaggerProvider;

        public CachingSwaggerProvider(ISwaggerProvider swaggerProvider)
        {
            _swaggerProvider = swaggerProvider;
        }

        public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
        {
            string cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
            return _cache.GetOrAdd(cacheKey, (key) => _swaggerProvider.GetSwagger(rootUrl, apiVersion));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*ole 5

针对之前的答案,这是 ASP.NET Core 的更新代码。我还添加了删除模型的功能。

using System;
using System.Linq;
using System.Web.Http;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.Swagger;

using Microsoft.AspNetCore.Mvc.ApiExplorer;

internal class SwaggerFilterOutControllers : IDocumentFilter
{

    void IDocumentFilter.Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        foreach (var item in swaggerDoc.Paths.ToList())
        {
            if (!(item.Key.ToLower().Contains("/api/endpoint1") ||
                  item.Key.ToLower().Contains("/api/endpoint2")))
            {
                swaggerDoc.Paths.Remove(item.Key);
            }
        }

        swaggerDoc.Definitions.Remove("Model1");
        swaggerDoc.Definitions.Remove("Model2");
    }
}
Run Code Online (Sandbox Code Playgroud)