Search code examples
c#swaggerasp.net-core-webapiswashbuckleapi-versioning

Grouping and Versioning not working well together in swagger in asp.net core 3.1 web api


I'm using Asp.Net Core 3.1 to build my API. I'm using swagger to generate document for my API. I decided to do grouping on my swagger document based on controller. So I ended up doing like this,

Startup - ConfigureServices:

options.SwaggerDoc(
    "LibraryOpenAPISpecificationCategories",
    ...

Startup - Configure:

options.SwaggerEndpoint(
    "/swagger/LibraryOpenAPISpecificationCategories/swagger.json",
    "Library API (Categories)");

Controller:

[Route("api/categories")]
[ApiController]
[ApiExplorerSettings(GroupName = "LibraryOpenAPISpecificationCategories")]
public class CategoriesController : ControllerBase

Until this point everything was working fine. When I added versioning the Swagger document stopped displaying the methods in the controller. I was trying to bring grouping inside version so that each version will have the groups like,

V1 -> LibraryOpenAPISpecificationCategories

V1 -> LibraryOpenAPISpecificationItems

V2 -> LibraryOpenAPISpecificationCategories

V2 -> LibraryOpenAPISpecificationItems

Here is what I did,

Startup - ConfigureServices:

services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VV";
});

services.AddApiVersioning(options =>
{
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.ReportApiVersions = true;
});

var apiVersionDescriptionProvider =
    services.BuildServiceProvider().GetService<IApiVersionDescriptionProvider>();

services.AddSwaggerGen(options =>
{
    foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
    {
        options.SwaggerDoc(
            $"LibraryOpenAPISpecificationCategories{description.GroupName}",
            ...

Startup - Configure:

app.UseSwaggerUI(options =>
{
    foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
    {
        options.SwaggerEndpoint(
            $"/swagger/LibraryOpenAPISpecificationCategories{description.GroupName}/swagger.json",
            $"Library API (Categories) {description.GroupName.ToUpperInvariant()}");

Controller:

[Route("api/categories")]
[ApiController]
[ApiExplorerSettings(GroupName = "LibraryOpenAPISpecificationCategories")]
public class CategoriesController : ControllerBase

No error is displayed in swagger document. Please assist me on where I'm going wrong. Am I missing anything?


Solution

  • After some analysis, I figured out that I missed DocInclusionPredicate in AddSwaggerGen in my ConfigureServices.

    Here is how I resolved,

    options.DocInclusionPredicate((documentName, apiDescription) =>
    {
        var actionApiVersionModel = apiDescription.ActionDescriptor
        .GetApiVersionModel(ApiVersionMapping.Explicit | ApiVersionMapping.Implicit);
    
        var apiExplorerSettingsAttribute = (ApiExplorerSettingsAttribute)apiDescription.ActionDescriptor.EndpointMetadata.First(x => x.GetType().Equals(typeof(ApiExplorerSettingsAttribute)));
    
        if (actionApiVersionModel == null)
        {
            return true;
        }
    
        if (actionApiVersionModel.DeclaredApiVersions.Any())
        {
            return actionApiVersionModel.DeclaredApiVersions.Any(v =>
            $"{apiExplorerSettingsAttribute.GroupName}v{v.ToString()}" == documentName);
        }
        return actionApiVersionModel.ImplementedApiVersions.Any(v =>
            $"{apiExplorerSettingsAttribute.GroupName}v{v.ToString()}" == documentName);
    });
    

    Hope this helps someone out there.