Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show only selected controllers in swagger-swashbuckle UI

Tags:

I am currently using swagger in my project and i have more than 100 controllers there. I guess due to the large number of controller, swagger UI documentation page takes more than 5 min to load its controller. Is it possible to select specific controllers at the UI page and load options for them only? Or else there are other methods to load UI page faster? Help me!

like image 888
Subash Kharel Avatar asked Jan 20 '17 07:01

Subash Kharel


People also ask

How do I hide the action method in swagger?

By adding this attribute on a controller or action and specifying IgnoreApi = true , it gets hidden from auto-generated documentation. However, this user has to apply this to around 80 controllers.

How do I hide a schema in swagger net core?

How to do it? add this property in your Swagger UI Options defaultModelsExpandDepth: -1 for hide schema section and for more reference refer this swagger.io/docs/open-source-tools/swagger-ui/usage/… Can you please add your swagger ui configuration settings in your question.


2 Answers

you can use ApiExplorerSettings on either controller to ignore a controller completely or on a method.

[ApiExplorerSettings(IgnoreApi = true)]
public class MyController
{
    [ApiExplorerSettings(IgnoreApi = true)]
    public string MyMethod
    {
      ...
    }
}
like image 195
peeyush rahariya Avatar answered Sep 19 '22 15:09

peeyush rahariya


Using swashbuckle's document filter you can remove some elements of the generated specification after the fact, and they would then not be included on the integrated swagger-ui. Create a class such as the below:

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('/'));
            }
        }
    }
}

and then edit your SwaggerConfig.cs file to include the filter:

        GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                    c.DocumentFilter<SwaggerFilterOutControllers>();

Note that while the controllers have been removed from the specification, other items such as the result models will still be included in the specification and might still be slowing down the page load.

It could also be slow simply due to enumerating all of the controllers/models etc in the first place, in which case this might not help.

Edit: I noticed it would regenerate the whole definition every time the UI page was viewed (which could be crippling in your scenario). Fortunately it's super easy to cache this (which should be fine as it shouldn't change at runtime for the majority of people).

Add this to your config:

c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));

and use this class shamelessly copied from 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));
        }
    }
}
like image 44
Rory Avatar answered Sep 18 '22 15:09

Rory