Swagger in .NET 5 – my preferred settings

on

APIs need to be well documented. It has become a standard that APIs are documented using the Open API standard and Swagger tools. Swagger is simple to set up in .NET 5, but I do have some things I like to set up.

What is Open API and what is Swagger?

Open API and Swagger are terms that often get mixed up. So, let’s define them first:

  • Open API – specification that defines a standard, programming language agnostic interface for documenting HTTP APIs. It can be found on GitHub.
  • Swagger – set of tools implementing the specification. You can find out more on swagger.io.

One of the most famous tools from Swagger is the Swagger UI. Swagger UI is a collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API. The initial implementation was published on npm and was intended for use with node.js. However, as the development community started to love the format, implementations for other languages started popping up quickly.

The most famous Swagger implementation for .NET in general (and, thus, for .NET 5 as well) is the Swashbuckle project.

Add Swagger to a .NET 5 project

When starting a new project in .NET 5, if you start from an existing template for an ASP.NET Core Web Application, there is an option to create an ASP.NET Core Web API. When selected, there is a checkbox to enable OpenAPI support on the right side.

ASP.NET Core API template - OpenAPI support

If you are adding Swagger manually to your API project, you first need to add the Swashbuckle.AspNetCore. At the time of this post, the latest version is 5.6.3.

In the Startup.cs file in the ConfigureServices() you need to add the following section configuring Swagger:

services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "SwaggerSetupExample", Version = "v1" });
    });

And then in the Configure() method it is necessary to tell the application to actually use Swagger UI:

if (env.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerSetupExample v1"));
}

It is often a good practice to make the Swagger UI available only in development mode.

If you have used the .NET 5 template and chosen the Enable OpenAPI support option, this has already been prepared for you.

If we just run the project now and open /swagger/index.html we will get the Swagger UI in our browser.

Setting up Swagger UI route

If nothing is explicitly set, Swagger UI will show up at /swagger/index.html. In order to change this, it is necessary to use the RoutePrefix in the app.UseSwaggerUI() definition:

app.UseSwaggerUI(c => {
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerSetupExample v1");
    c.RoutePrefix = "path-to-swagger";
});

This will make Swagger UI available at /path-to-swagger/index.html.

I like to have the Swagger API at the root of my API application, so I’d use c.RoutePrefix = string.Empty;

Comments as part of SwaggerUI

Visual Studio has a built in feature that whenever you type /// above a class, method, property etc. it automatically adds a section to describe the given element. An example of this can be seen here:

Summary comments on method

These comments are very useful because they can be used to auto-generate documentation. They are also used by Intellisense so that whenever you use your method in code, the comments will always appear to help you.

However, if added to the controller, controller methods or DTO classes and DTO class properties, these comments can also be used as documentation in the Swagger UI to provide consumers of the API with additional info.

The first thing that needs to be done is to create the actual output XML documentation file. In order to enable this, go to the project properties in Visual Studio and in the Build section enable the XML documentation file in the bottom and set a name to it. If you are using a different editor (such as VS Code), you can do this directly in the .csproj file by doing this:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
  <DocumentationFile>E:\MyPath\SwaggerSetupExample\SwaggerSetupExample.xml</DocumentationFile>
</PropertyGroup> 

In order to include the XML comments into your SwaggerUI, it is necessary to add the IncludeXmlComments to the AddSwaggerGen() method:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "SwaggerSetupExample", Version = "v1" });
    c.IncludeXmlComments("SwaggerSetupExample.xml");
});

ProducesResponseType Attribute

I try to make sure that all my controller methods have the [ProducesResponseType] attributes properly set up. These attributes tell users which HTTP response codes they can expect and what type of object they will get in the body with that code.

This keeps the API documentation clean and allows consumers of your API to cover all the cases easily.

[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(typeof(ClientErrorData), 400)]
private int SomeMethod(int inputParam)
{
    // Some code here
}

You can choose to either set the [ProducesResponseType] manually to each method or use Microsoft’s web API conventions that add these for you. You should, in this case, be careful that the code is actually returning responses in accordance to the given convention!

Conclusion

This is the way I prefer setting up Swagger in my .NET APIs. Sometimes it is necessary to to tweak it a bit, in case there are some specifics for the projects, but this works really well in most cases and allows me to deliver clean, well documented API systems.

A thing I really found useful is that adding the XML documentation to your Swagger UI actually forces you to write comments and maintain them. Using the [ProducesResponseType] attribute actually forces you to keep your exceptions clean and tidy and to cover all edge cases. In short, something as simple as setting up a tidy and consistent documenting flow can help you be a more thorough developer.

Leave a Reply

Your email address will not be published. Required fields are marked *

You are currently offline