Enriched Web API Documentation using Swagger/OpenAPI in ASP.NET Core
Introduction
Before selecting or attempting any integration with an API, most developers check out its API documentation. Keeping the API documentation up to date to reflect the software changes is challenging and requires time and effort. In the case of Web APIs, we would like to document the following:
- Authorization Types (e.g., API Key, Bearer token, Authorization code, etc.)
- Action Methods: The endpoints, HTTP Methods, Headers, etc.
- Data Contracts: The description of the data to be exchanged between the service and a client. We can show each parameter’s name, type, restrictions, etc.
- Examples that use the Web API to help consumers start quickly.
It would be nice to have a standardized way of describing Web APIs, to allow both humans and computers to generate, discover and understand its capabilities without requiring access to the source code. Good news, 🎉 this standard exists and is called OpenAPI Specification (OAS), based initially on the Swagger Specification.
A Web API documentation
provides the necessary information (e.g., endpoints, data contracts, etc.) to describe our Web API to our consumers. In addition, however, we may want to provide documentation for our source code to help developers improve and maintain it. Therefore, a Code documentation
will provide information about our projects, classes, constructors, methods, etc. To automatically generate code documentation from comments, start by reading Wagner and Warren’s (2021) article.
In this article, we will learn about Web API documentation
, how we can automatically generate it in ASP .NET Core and how to provide enriched information by offering examples, documentation per different versions, and many more 😉.
OpenAPI in .NET Core
In practice, in an ASP .NET Core project, we use specific Attributes and XML comments to define all the needed information (e.g., HTTP response codes, information messages, etc.) directly to our source code. We can automatically generate a JSON or YAML document (or set of documents) that describes our API by using this information. This generated document(s) is known as OpenAPI definition
, which can be used by:
- API Documentation generation tools (e.g., Swagger UI, Redoc, etc.) to render our OpenAPI definition (e.g., as a web page).
- Code generation tools (NSwag, Swagger Codegen, etc.) to automatically generate the consumer’s source code in various programming languages.
- Testing tools to execute API requests and validate responses on the fly.
- Mock Server tools to provide a mock-fake server to return static or dynamically generated example responses.
So, by using OpenAPI in our Web API projects, we can automatically generate our documentation directly from or source code by maintaining the data annotations, XML comments and examples based on our actual data transfer classes. The two main OpenAPI implementations for .NET are Swashbuckle and NSwag. In the examples of the following sections, we will use the Swashbuckle
tools.
Create a New Web API in .NET 6.0 with OpenAPI Enabled
Since the ASP.NET Core 5.0, the Web API templates enable the OpenAPI support by default. The template contains a NuGet dependency on Swashbuckle, register services, and add the necessary middlewares to generate a basic OpenAPI definition
file and serve it in a Web UI (via the Swagger UI tool). In the following instructions, we will see how to create a new Web API project with enabled OpenAPI support.
That’s a great start! With only a few clicks, our new API projects support OpenAPI. However, there are things that we can configure and improve to provide more information to our API consumers. For example, we could perform the actions shown in the following figure and list. However, we will see more ways to enrich our API documentation in the following sections.
- Set the appropriate response media type (e.g., application/json).
- Provide examples with real-life data (not auto-generated with dummy data).
- Include additional HTTP status codes. For example, to inform about the possible error HTTP status codes (4xx and 5xx).
Provide OpenAPI Documentation in Existing Project
Let’s assume that our current project serves API with multiple versions, and we would like to provide OpenAPI Documentation for all versions. For that purpose, we will use the project that we created in .NET Nakama (2021, December).
To provide OpenAPI Documentation, we would start by installing the Swashbuckle.AspNetCore NuGet package. To support API documentation for multiple versions, we need to install the Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer NuGet package.
Our next step is to register some services and add some middlewares. I have created some extension methods that group all the necessary actions for that purpose. You can find the source code of the extensions and examples in GitHub.
So, we can download, modify and use the following extensions in our Program.cs
(or in the System.cs
in previous .NET versions). In addition, we can see an example of the Program.cs
file here.
The AddApiVersioningConfigured
extension (can be found in ConfigureApiVersioning.cs) has been updated (in comparison with the one provided in article .NET Nakama (2021, December) to support versioning on our documentation.
Then, we should use the AddSwaggerSwashbuckleConfigured
extension (found in ConfigureSwaggerSwashbuckle.cs file) in our Program.cs
file to configure the Swagger generator based on our needs. In the following sections, we will see in detail several enrichment scenarios.
In the ConfigureSwaggerSwashbuckleOptions.cs
file, we can configure the basic information (e.g., title, description, license, etc.) about our API (see Figure 3).
Add the UseSwagger()
middleware in our Program.cs
file to serve the generated OpenAPI definition(s) as JSON files and the UseSwaggerUI()
middleware to server the Swagger-UI for all discovered API versions. In the following example, we serve the API documentation only in the development environment. However, we can decide which environments to provide the documentation based on our API audience. Remember that we could only generate the JSON files and serve them (e.g., with Swagger UI) in a separate project.
Finally, if we want to see the SwaggerUI when start debugging, we will have to set the "launchUrl": "swagger"
in the launchSettings.json
file.
The following figure shows a Swagger UI example for an API with two versions containing essential information.
Enrich Documentation via XML Comments and Attributes
The structure of the extracted XML documentation is defined in C# by using XML documentation comments. The documentation comments support several XML tags, such as summary, return description, exceptions, list of information, etc. In this article, we will use some of them. For more information about the recommended XML tags for C#, read Wagner B., et al. (2021) article.
Generate and Read Documentation Comments (XML)
To enable the documentation file generation, we should set the GenerateDocumentationFile
option to True. Then, the compiler will find all comment fields with XML tags in our source code and create an XML document.
However, when this option is enabled, the compiler will generate CS1591 warnings for any public members in our project without XML documentation comments. We can exclude these warnings by including them in the NoWarn
option.
So, to enable the GenerateDocumentationFile
option and stop the CS1591 warnings we should:
- Right-click the project in
Solution Explorer
and selectEdit Project File
. - Add the following PropertyGroup section (or include the options in an existing PropertyGroup).
Next, we need to include the XML documentation comments in the OpenAPI definition file. For that purpose, we should use the IncludeXmlComments
method in the ConfigureSwaggerSwashbuckle.cs
file as shown in the following code.
Finally, we should include the XML comments in our controller actions using triple slashes. For example, we can add a summary
section to describe the performed action. Figure 4 presents a part of the Swagger UI that shows the API endpoint summary.
API Responses (HTTP Codes and Types)
Any consumer would need beneficial information, such as the possible HTTP status codes and their response body. In Figure 5, we can see an example where the API endpoint could return its five possible HTTP status codes (200, 400, 409, 500, and 503). To enrich the response metadata for a given action method, we should:
- Install the Swashbuckle.AspNetCore.Annotations NuGet package.
- Update the controller actions to specify the possible response codes and their response types (if any) by using the
response
tag and theSwaggerResponse
attribute.
In the following code example, we set the response description of the success HTTP status code in the response
tag. In addition, we are setting all possible HTTP status codes and response types (e.g., IEnumerable<SampleResponse>
) for the successful response.
Define Media Types (Consumed and Produced)
To define the appropriate consume and produce media types, we can decorate our controller with the [Consumes]
and [Produces]
attributes. For example, if we use the application/json
, we can use the aforementioned attributes to decorate our controller, as shown in the following code example. Figure 6 shows the effect of the [Produces]
attribute in Swagger UI.
Enrich Documentation via Filters
The Swashbuckle.AspNetCore.Filters
NuGet package provides several functionalities that significantly improve our API documentation. For example, we can create valuable request and response examples with valid data, including security requirements, custom request and response headers, etc. In addition, we can manually test our API using these features just by using the Swagger UI without modifying the auto-generated request.
API Examples (Request and Response)
To provide request and response examples with valuable and valid data, we should:
- Install the Swashbuckle.AspNetCore.Filters NuGet package.
- Enable the automatic annotation of the
[SwaggerRequestExample]
and[SwaggerResponseExample]
in theConfigureSwaggerSwashbuckle.cs
file. For that purpose, we should:- Use the
options.ExampleFilters();
in theAddSwaggerGen(options)
. - Read the examples for the current assembly by registering the
AddSwaggerExamplesFromAssemblies
.
- Use the
Then we can implement the IExamplesProvider
interface for our data transfer classes (request and response). In the following source code example, we return an example for the SampleRequest
class, shown in Figure 7.
Input-Validation in API Documentation (Data Annotations and Fluent)
If we use System.ComponentModel.DataAnnotations
attributes to validate our DTOs, then the validations are recognized and automatically included in the API documentation. However, we should perform the following steps if we are using FluentValidation for our DTOs.
- Install the MicroElements.Swashbuckle.FluentValidation NuGet package.
- Register the following service in the
ConfigureSwaggerSwashbuckle.cs
to add the fluent validation rules to the swagger generator.
Security Information Scheme
To provide security information about the authorization scheme we are using (e.g., JWT Bearer), we can define it by using the following source code in the ConfigureSwaggerSwashbuckle.cs
file. In this way, the Authorize
button will be shown (Figure 10), and we can use it to specify the appropriate values (e.g., the bearer token in Figure 11).
Mark Endpoints that Require Authorization
Our API endpoints may require authorization (using the [Authorize]
attribute) or allow anonymous requests. As we can understand, it would be helpful to distinguish these cases in our Swagger UI. For that purpose, we can show the (Auth)
text next to the endpoint’s summary to quickly see which of them require authorization (Figure 12). We can perform that by using the following OperationFilter
in the ConfigureSwaggerSwashbuckle.cs
file as shown below:
Summary
An Web API documentation
provides the necessary information (e.g., endpoints, data contracts, etc.) to describe our Web API to our consumers. However, keeping an up to date Web API documentation is challenging and requires time and effort. Therefore, an easy and automatic process as much as possible would be a great help.
The OpenAPI Specification
provides a standardized way of describing Web APIs to allow both humans and computers to generate, discover and understand the API capabilities. In an ASP .NET Core project, we use specific Attributes and XML comments to define all the needed information (e.g., HTTP response codes, information messages, etc.) directly to our source code. Thus, we can provide up-to-date documentation easily as we keep our code up to date.
The essential OpenAPI tools that we would need are a) a tool to generate the OpenAPI definition and b) a tool to generate the API documentation (as a web page, PDF, etc.). This article showed how to use the Swashbuckle tools to create API documentation in an ASP.NET Core project (new or existing) with enriched information.
When creating a Web API Documentation, our goal should be to provide all the information that a consumer would need to communicate with our Web API (without having access to our code). This way, we would reduce the time to a first hello world (TTFHW) call (i.e., the time to integrate with our Web API). So let’s think about our consumers and create beautiful and valuable Web API documentation for them.
References
- .NET Nakama (2021, December 4). All about Web API Versioning in ASP.NET Core. https://www.dotnetnakama.com/blog/all-about-web-api-versioning-in-asp-dotnet-core/
- Roth D. (2021, August 10). ASP.NET Core updates in .NET 6 Preview 7. https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-net-6-preview-7/#minimal-host-and-template-improvements
- Wagner B. and Warren G. (2021, November 29). XML documentation comments. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/
- Wagner B., et al. (2021, November 30). Recommended XML tags for C# documentation comments. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/recommended-tags
If you liked this article (or not), do not hesitate to leave comments, questions, suggestions, complaints, or just say Hi in the section below. Don't be a stranger 😉!
Dont't forget to follow my feed and be a .NET Nakama. Have a nice day 😁.