Documenting a Versioned .Net Web API Using Swagger

Dipendu Paul
5 min readJul 3, 2023

--

Photo by Sigmund on Unsplash

In this article, we will explore how to add swagger documentation in a .Net Web API application in which versioning has been implemented using Asp.Versioning.Mvc library.

If you are new to API versioning in a .Net Web API application, I highly recommend reading the articles published here and here.

You can follow the steps mentioned here using the code in the following Git repository https://github.com/FOSSKolkata/api-versioning-demo. Clone it on your desktop to get started with this article.

To start with make a copy of the code in the folder “Milestone 2” of the Git repository. Open the solution within and then add Swashbuckle.AspNetCore NuGet package to the project. Now add the statements services.AddSwaggerGen();in the ConfigureServices method and app.UseSwagger(); in the Configure method of the Startup class. This is the minimal setup that any Asp.Net Core API project requires for adding Swagger documentation in JSON format. Now run the project and navigate to https://localhost:{port number}/swagger/v1/swagger.json. The URL would throw a 500 Internal server error. This is because the steps we did till now, although may suffice for any other .Net Web API project but for the project where API versioning is enabled, you have to do a few more steps to make it work.

Add NuGet package Asp.Versioning.Mvc.ApiExplorer and make the following changes in ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(
options =>
{
options.DefaultApiVersion = new ApiVersion(1.0);
options.AssumeDefaultVersionWhenUnspecified = true;
// reporting api versions will return the headers
// "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader(),
new QueryStringApiVersionReader("api-version"),
new HeaderApiVersionReader("X-Version"),
new MediaTypeApiVersionReader("x-version"));
})
.AddMvc(
options =>
{
// automatically applies an api version based on the name of
// the defining controller's namespace
options.Conventions.Add(new VersionByNamespaceConvention());
})
.AddApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerGen();
}

Note that setup.SubstituteApiVersionInUrl = true; is only needed if the URL segment versioning scheme is enabled. It replaces the version placeholder in endpoint URLs with the version value present in the URL of the generated JSON document. For the substitution to work properly, you would also need to include UrlSegmentApiVersionReader in the lists of version readers as done in the above code snippet. The group name format is the format string that is applied to the current API version being explored. The setup.GroupNameFormat = "'v'VVV"; sets the group name to ‘v’ followed by [Major, optional minor version, and status].

Run the application and navigate to https://localhost:{port number}/swagger/v1/swagger.json to make sure that the JSON documentation is generated properly for version 1 API endpoints. To make sure you understand the functionality of SubstituteApiVersionInUrl, set it to false and see the difference in the endpoint URLs in the JSON document.

Now navigate to https://localhost:{port number}/swagger/v2/swagger.json which ideally should provide documentation of version 2 of the API, but instead, it would throw a 404 Not Found error. This is due to the fact that SwaggerGen service only generates documentation for version 1 by default. We need to explicitly tell SwaggerGen to generate documentation for version 2 of the API for the above issue to get resolved. Now as a quick fix modify the services.AddSwaggerGen()to the following:

services.AddSwaggerGen((options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "Version 1",
Title = "Test API V1",
Description = "An ASP.NET Core Web API for testing versioning"
});

options.SwaggerDoc("v2", new OpenApiInfo
{
Version = "Version 2",
Title = "Test API V2",
Description = "An ASP.NET Core Web API for testing versioning"
});
}));

Now run the application and navigate to https://localhost:{port number}/swagger/v2/swagger.json. It should now generate the documentation of version 2 properly. But in the above code, we have hardcoded documentation settings for version 1 and version 2. In the next step, we would make it dynamic so as to generate documentation for other versions of API that may get added in the future.

Add the following class to the API project at the top level:

using Asp.Versioning.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ApiVersioningDemoInNet7
{
public class NamedSwaggerGenOptions : IConfigureNamedOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider provider;
public NamedSwaggerGenOptions(IApiVersionDescriptionProvider provider)
{
this.provider = provider;
}

public void Configure(string? name, SwaggerGenOptions options)
{
Configure(options);
}

public void Configure(SwaggerGenOptions options)
{
// add swagger document for every API version discovered
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerDoc(
description.GroupName,
CreateVersionInfo(description));
}
}

private OpenApiInfo CreateVersionInfo(
ApiVersionDescription description)
{
var info = new OpenApiInfo()
{
Title = "Test API " + description.GroupName,
Version = description.ApiVersion.ToString()
};
if (description.IsDeprecated)
{
info.Description += " This API version has been deprecated.";
}
return info;
}
}
}

NamedSwaggerGenOptions class contains the configuration required to generate JSON documentation for all versions of API. This class uses the default IApiVersionDescriptionProvider service of Asp.Versioning.ApiExplorer library to gather information about all the API versions that exist and dynamically configure Swagger documentation for each of them.

Now simplify the services.AddSwaggerGen() statement in ConfigureServices method to the following:

services.AddSwaggerGen();
services.ConfigureOptions<NamedSwaggerGenOptions>();

Now you can run the application and make sure that JSON documentation for versions 1 and 2 and generated successfully.

As the last step, you would configure a user-friendly documentation of API using Swagger UI. The Swagger UI service, that ships with Swashbuckle.AspNetCore NuGet package takes the JSON document produced by SwaggerGen service as input and presents it in a much more user-friendly manner.

In Configure method of the Startup class, inject IApiVersionDescriptionProvider provider and add the following code to it:

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

Run the application and navigate to https://localhost:{port number}/swagger/index.html. The following UI should be displayed. Note the presence of a drop-down in the top right corner using which you can view documentation of different versions of API.

Wrapping Up

In this article, you saw how you can configure Swagger documentation for a versioned .Net Web API application.

I hope you enjoyed reading this article. We will meet again to explore some other topics. Till then keep learning and develop awesome applications.

--

--