9

I need to serve multiple swagger UIs on single C# ASP.NET Core application. This is needed because application API consists of internal "private" API for UI and other stuff and "public" API that can be accessed by other applications and users.

Each Swagger endpoint should be on it's own swagger UI page and have a different URL address. I am able to divide existing API specification to two different json files and the json files in different routes using this code on Startup.cs Configure method:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ 
    ...

    app.UseSwagger()
    app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("v0.1_public/swagger.json",  "Public API v0.1");
                c.SwaggerEndpoint("v0.1_private/swagger.json", "Private API v0.1");
            });
    ...
}

I divide the specifications by filtering and adding two Swagger generators in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
     ...
     services.AddSwaggerGen(c =>
        {
            c.DocumentFilter<PublicAPISwaggerFilter>();
            c.SwaggerDoc("v0.1_public", new OpenApiInfo
            {
                Title = "Public API",
                Version = "v0.1"
            });
        });
     services.AddSwaggerGen(c =>
        {
            c.DocumentFilter<PrivateApiSwaggerFilter>();
            c.SwaggerDoc("v0.1_private", new OpenApiInfo
            {
                Title = "Private API",
                Version = "v0.1"
            });
        });
     ...
}

Swagger UI is then served on https://localhost:port/swagger and both endpoints are listed on dropdown menu.

How can I create two swagger UIs when other is on route https://locahost:port/private/swagger and other one is https://locahost:port/public/swagger and each one them is displaying only one of the endpoints described above?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Aksim
  • 91
  • 1
  • 3

2 Answers2

2

you can place your private and public controllers in separate directories (i.e Controllers/Private and Controllers/Public) and use controller model convention

  1. Create controller conventions
public sealed class SwaggerConventions : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        // private controllers will contain 'private' word in namespace
        bool isPrivate = controller.ControllerType.Namespace != null && controller.ControllerType.Namespace.Contains("Private");

        controller.ApiExplorer.GroupName = isPrivate ? "private" : "public;
    }
}
  1. Use conventions in your startup/program.cs
    builder.AddControllers(c =>
    {
        c.Conventions.Add(new SwaggerConentions());
    })
  1. Configure swagger endpoints
services.AddSwaggerGen(swagger =>
{
    swagger.SwaggerDoc("public", new OpenApiInfo { Title = "public API", Version = "v1" });
    swagger.SwaggerDoc("private", new OpenApiInfo { Title = "private API", Version = "v1" });

}

app
.UseSwagger()
.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint($"/swagger/public/swagger.json", "Public API V1");
    c.SwaggerEndpoint($"/swagger/private/swagger.json", "Private API");
}
Piotr K.
  • 106
  • 1
  • 4
-2

You will need to split out your private and public controllers into separate applications. Doing so is also beneficial as you don't want to mix publicly accessibly API's with internal ones. It will be easier to maintain this way.

If its the specific URL convention you are after this can be handled by IIS or other tools you are using to host the applications.

Kobus
  • 31
  • 2
  • 5