I have an ASP.NET Core 8 Web API . I want to have the API docs on a separate swagger page per controller. e.g. all endpoints under AmazonController
should be served on ..../v1/swagger/amazon.html
. Similarly, all endpoints under EBayController
should be served on ...v1/swagger/ebay.html
.
Currently, I am using NSwag to generate ApiClient
per controller and services.AddOpenApiDocument
to configure the OpenAPI docs. The issue is I can add register multiple AddOpenApiDocument
in DI with different configurations e.g. using DocumentProcessers
to filter out irrelevant endpoints by name in a document, but, the resulting swagger page remains the same. i.e. ...swagger/index.html
.
Each document appears as a separate "definition" on the same ...swaggger/index.html
page.
I want to keep each controller's docs on its own respective swagger docs page and have its own versioning. Cannot seem to find how to do it best. I am open to all suggestions.
I want to have the API docs on a separate swagger page per controller. e.g. all endpoints under AmazonController should be served on ..../v1/swagger/amazon.html. Similarly, all endpoints under EBayController should be served on ...v1/swagger/ebay.html.
You could register multiple OpenAPI documents in the DI container, each with a filter to include only the relevant controller's endpoints and serve each document on a separate endpoint instead of listing them all on the same Swagger UI page.
Refer to the following sample:
Configure NSwag to Generate Separate Documents
builder.Services.AddControllers();
// Register multiple OpenAPI documents
builder.Services.AddOpenApiDocument(config =>
{
config.DocumentName = "todo";
config.Title = "todo API";
config.ApiGroupNames = new[] { "todo" }; // Tag controllers with [ApiExplorerSettings(GroupName = "Amazon")]
config.PostProcess = document =>
{
document.Info.Version = "v1";
document.Info.Title = "todo API";
};
});
builder.Services.AddOpenApiDocument(config =>
{
config.DocumentName = "values";
config.Title = "values API";
config.ApiGroupNames = new[] { "values" };
config.PostProcess = document =>
{
document.Info.Version = "v1";
document.Info.Title = "values API";
};
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseOpenApi(settings =>
{
settings.Path = "/v1/swagger/{documentName}.json"; // Serves separate OpenAPI documents
});
app.UseSwaggerUi3(settings =>
{
settings.Path = "/v1/swagger/todo.html";
settings.DocumentPath = "/v1/swagger/todo.json";
});
app.UseSwaggerUi3(settings =>
{
settings.Path = "/v1/swagger/values.html";
settings.DocumentPath = "/v1/swagger/values.json";
});
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
Tag Controllers with [ApiExplorerSettings]
[Route("api/[controller]")]
[ApiController]
[ApiExplorerSettings(GroupName = "todo")]
public class TodoController : ControllerBase
{
// GET: api/<TodoController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
...
[Route("api/[controller]")]
[ApiController]
[Authorize]
[ApiExplorerSettings(GroupName = "values")]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
...
After running the application, the result as below:
Todo controller: https://localhost:7245/v1/swagger/todo.html
→ Todo API docs
Values controller: https://localhost:7245/v1/swagger/values.html
→ Todo API docs
And you can view the .json result use https://localhost:7245/v1/swagger/todo.json
or https://localhost:7245/v1/swagger/values.json
.
Update:
I want to have one more group that should show all the controllers including Amazon, EBay, todos, files, customers, etc. Basically, this one should be the default swagger docs page that gets rendered when I hit swagger/index.html and it should display all endpoints. Would it be necessary to apply the ApiExplorerSettings tag on all controllers and define a name for it?
You can add one more OpenAPI documents as below:
builder.Services.AddOpenApiDocument();
...
if (app.Environment.IsDevelopment())
{
// Add OpenAPI 3.0 document serving middleware
// Available at: http://localhost:<port>/swagger/v1/swagger.json
app.UseOpenApi();
// Add web UIs to interact with the document
// Available at: http://localhost:<port>/swagger
app.UseSwaggerUi3(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}
The Program.cs file like this:
Then, you can display all endpoints in swagger index page(https://localhost:7245/swagger/index.html
).