Welcome to today’s post.
In today’s post I will be discussing how to setup and create advanced documentation for web API methods within an ASP.NET Core web API application. This allows us to improve on the quality of API method documentation from a developer perspective.
I previous post I showed how to setup and add Swagger documentation to controller methods within an existing .NET Core web API application. I extended this to document secure web API methods.
With the default Swagger API documentation that is generated, the following API method properties are generated out of the box during compilation:
- Method name.
- HTTP Request type (GET, POST, PUT, DELETE, PATCH).
- Input parameters and types.
- Response type.
I will show how we can also provide the following additional API method documentation:
- Method summary description.
- Return summary description.
- Response code description(s).
- Additional remarks.
The purpose for including the method summary description is to allow more details on the functionality of the method. The return summary description allows for more details on the output of the method and its types. The response code description can include one or more details on each response code and an associated description on why the response code is generated. Finally, an additional remark section can include details on how to execute the method (such as from a CURL command prompt or from a browser URL and sample input parameters or a payload).
I will later give examples of web API methods that include each of the above descriptions.
First, I will show how to setup the enhanced Swagger API documentation in an existing web API application. I have used ASP.NET Core 7.0 for the example.
The changes below will enable the compilation of the project to generate an XML documentation file under the project’s bin subfolder. The generated XML documentation file will contain XML definitions of the above web API method descriptions for the summary, returns, responses and remarks.
When the application is run, the Swagger UI generator will read in the additional documentation from the output XML file and populate the descriptions within the Swagger UI definition for each API method that has the enhanced descriptions.
In the first section, I will show how to configure an ASP.NET Core application to support Swagger Document generation.
Configuring an ASP.NET Core Application with Swagger Document Generation
In this section, I will show how to setup and generate the Swagger Documentation. This involves setting up the NuGet packages, the application configuration file, configuring the startup class.
Required NuGet Packages
From the NuGet package manager, install the following NuGet packages (the versions below are for an ASP.NET Core 7.0 web API application):
Configuring the Application Project File
In the project’s solution explorer, open the CSPROJ file, then add the following line within the <PropertyGroup> tag:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Close and save the change.
Configuring the Startup Class
In the Startup class, we setup the service collection as follows.
We configure the Swagger generation service collection to read in the additional API method documentation from the output documentation XML file as shown:
builder.Services.AddSwaggerGen(options =>
{
..
// using System.Reflection to read the XML file from the executed assembly location.
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
..
});
We configure the Swagger UI middleware and endpoints as shown (standard as per a basic Swagger UI setup):
if (app.Environment.IsDevelopment())
{
// Enable middleware to serve generated Swagger as a JSON endpoint
app.UseSwagger();
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "BookLoan Catalog API");
c.RoutePrefix = string.Empty;
});
}
In the next section, I will show how to define documentation for each web API method.
Defining Documentation for each Web API Method
For each API method we wish to add documentation, the following tags are included, and descriptions entered within each tag:
/// <summary>
/// … enter a method summary …
/// </summary>
/// <param name="model"></param>
/// <returns> … enter a return summary … </returns>
/// <response code="A"> … enter a response summary … </response>
/// …
/// <response code="Z"> … enter a response summary … </response>
/// <remarks>
/// … enter a remarks summary …
/// </remarks>
In the remaining sub-sections, I will show examples of the different API methods and their respective documented outputs.
Example HTTP GET API with no input parameters
Below is an example of an API method with no parameters, which returns a list:
/// <summary>
/// A list of Books
/// </summary>
/// <returns>Returns a list of Books of type BookViewModel</returns>
[HttpGet("api/[controller]/List")]
public async Task<List<BookViewModel>> List()
{
..
}
When built and run, the generated Swagger UI output is shown below with the summary displayed near the method URI on the header and the remarks displayed above the parameters section:
The XML output that was generated after the compilation is shown below:
<member name="M:BookLoan.Controllers.BookController.List">
<summary>
A list of Books
</summary>
<returns>Returns a list of Books of type BookViewModel</returns>
<remarks>
Sample request:
GET /List
</remarks>
</member>
Example HTTP GET API with input parameters
Below is an example of an API method with one parameter, which returns a single JSON object:
/// <summary>
/// Get the details of a Book
/// </summary>
/// <param name="id"></param>
/// <returns>Return the details of a Book of type BookViewModel</returns>
[HttpGet("api/[controller]/Details/{id}")]
public async Task<ActionResult> Details(int id)
{
..
}
When built and run, the generated Swagger UI output is shown below with the summary displayed near the method URI on the header and the remarks displayed above the parameters section. The parameters are in the parameters section with each parameter’s name and description:
The XML output that was generated after the compilation is shown below:
<member name="M:BookLoan.Controllers.BookController.Details(System.Int32)">
<summary>
Get the details of a Book
</summary>
<param name="id"></param>
<returns>Return the details of a Book of type BookViewModel</returns>
<remarks>
Sample request:
GET /Details/1
</remarks>
</member>
Example HTTP GET API with input parameters and response codes
Below is an example of an API method with one parameter, which returns a single JSON object and the response codes that are returned:
/// <summary>
/// Get the details of a Book
/// </summary>
/// <param name="id"></param>
/// <returns>Return the details of a Book of type BookViewModel</returns>
/// <response code="404">Returns when the book item cannot be found</response>
/// <response code="400">If there is an error retrieving the book item</response>
/// <response code="200">If the book item is found</response>
[HttpGet("api/[controller]/Details/{id}")]
public async Task<ActionResult> Details(int id)
{
..
}
When built and run, the generated Swagger UI output is shown below with the response section displayed below the parameters section. Each response shows in a grid with the Code and Description:
The XML output that was generated after the compilation is shown below with response code description documentation:
<member name="M:BookLoan.Controllers.BookController.Details(System.Int32)">
<summary>
Get the details of a Book
</summary>
<param name="id"></param>
<returns>Return the details of a Book of type BookViewModel</returns>
<remarks>
Sample request:
GET /Details/1
</remarks>
<response code="404">Returns when the book item cannot be found</response>
<response code="400">If there is an error retrieving the book item</response>
<response code="200">If the book item is found</response>
</member>
Example HTTP POST API with input parameters, response codes and remarks
Below is an example of an API POST method with one parameter, a model payload, which returns a single JSON object and the response codes that are returned depending on whether a record was created or went into error:
/// <summary>
/// Create a book record
/// </summary>
/// <param name="model"></param>
/// <returns>Returns a book of type BookViewModel</returns>
/// <response code="400">If there is an error creating the book item</response>
/// <response code="200">If the book item is created</response>
/// <remarks>
/// Sample request:
///
/// POST /Create
/// {
/// "id": 1,
/// "name": "Book Title #1",
/// "author": "A. Author",
/// "yearPublished": 2000,
/// "genre": "Fiction",
/// "edition": "1",
/// "isbn": "1234",
/// "location": "Sydney",
/// "mediaType": "Book",
/// }
///
/// </remarks>
[HttpPost("api/[controller]/Create")]
public async Task<ActionResult> Create([FromBody] BookViewModel model)
{
..
}
When built and run, the generated Swagger UI output is shown below with the remarks section displaying more detailed instruction on executing the API:
The XML output that was generated after the compilation is shown below with response code description documentation:
<member name="M:BookLoan.Controllers.BookController.Create(BookLoan.Models.BookViewModel)">
<summary>
Create a book record
</summary>
<param name="model"></param>
<returns>Returns a book of type BookViewModel</returns>
<response code="400">If there is an error creating the book item</response>
<response code="200">If the book item is created</response>
<remarks>
Sample request:
POST /Create
{
"name": "Book Title #1",
"author": "A. Author",
"yearPublished": 2000,
"genre": "Fiction",
"edition": "1",
"isbn": "1234",
"location": "Sydney",
"mediaType": "Book",
}
</remarks>
</member>
With the above API methods examples we have seen how useful the documentation can be not just to developers when reviewing code, but to testers that execute tests through the Swagger UI and need meaningful descriptions of API methods and documented input parameters, output parameters, and the possible responses.
That is all for today’s post.
I hope you have found this post useful and informative.
Andrew Halil is a blogger, author and software developer with expertise of many areas in the information technology industry including full-stack web and native cloud based development, test driven development and Devops.