Show only selected controllers in swagger-swashbuckle UI
Solution 1
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
{
...
}
}
Solution 2
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));
}
}
}
Solution 3
In response to the previous answer, this is the updated code for ASP.NET Core. I also added the feature to remove models.
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");
}
}
Solution 4
swaggerDoc.paths.Remove("/" + apiDescription.Route.RouteTemplate.TrimEnd('/'));
did not remove anything for me. So,
internal class SwaggerFilterOutControllers : IDocumentFilter
{
void IDocumentFilter.Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
foreach (var item in swaggerDoc.Paths.ToList())
{
if (!(item.Key.ToLower().Contains("/api/v1/xxxx") ||
item.Key.ToLower().Contains("/api/v1/yyyy")))
{
swaggerDoc.Paths.Remove(item.Key);
}
}
}
}
Solution 5
You can try this. You APIExplorerSetting to specify APIs to be included in a particular group.
Start by defining multiple Swagger docs in Startup.cs:
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "My API - V1",
Version = "v1"
});
c.SwaggerDoc("v2", new OpenApiInfo {
Title = "My API - V2",
Version = "v2"
});
});
Then decorate the individual controller with the above groups:
[ApiExplorerSettings(GroupName = "v2")]
Reference: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#generate-multiple-swagger-documents
Related videos on Youtube
Subash Kharel
Updated on September 15, 2022Comments
-
Subash Kharel about 1 year
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!
-
benPearce over 6 yearsPerhaps the number of controllers is the problem? Consolidate or split to separate domain applications. One hundred controllers in a single app does represent a bit of a smell.
-
-
Subash Kharel over 6 yearsI need to select the controller dynamically. I want to have a option in swagger UI and select controllers in the option and load them dynamically. Is it possible?
-
Rory over 6 yearsPleasure @SUBASH. I'm glad it's working for you now. If this or any answer has solved your question please consider accepting it by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this.
-
madufit1 about 5 yearsswaggerDoc.paths.Remove("/" + apiDescription.Route.RouteTemplate.TrimEnd('/')); did not remove anything.
-
mrmashal almost 4 years
using Microsoft.AspNetCore.Mvc;
-
linjunhalida over 3 yearsWhere should I put this code? same dir with startup.cs?
-
Andrew Samole over 3 yearsSure, it doesn't really matter. Just make sure you add this to your Startup.cs services.AddSwaggerGen(options => options.DocumentFilter<SwaggerFilterOutControllers>();
-
Andrew Samole over 3 yearsTake a look at this tutorial if you get lost: docs.microsoft.com/en-us/aspnet/core/tutorials/…
-
Anouar about 3 yearsPlease include a sample code from the suggested solution. Then add a link to the documentation. Only posting a link to some doc is not enough as the link can become stale in the future.
-
Anouar about 3 yearsYou need to edit your answer and not add a comment.
-
computercarguy about 3 yearsThe version I'm using, 5.6.1, uses
OpenApiDocument
instead ofSwaggerDocument
. There are probably other versions that do the same. -
CodeHacker over 2 yearsWhat if I want this to be enabled/disabled from the AppsSettings (Options<MyApplicationSettings>)?