Customizing Swagger Responses for Better API Documentation

Stephen Darlington
Trimble Maps Engineering Blog
3 min readJun 23, 2020

By now we should all be using Swagger to automatically generate documentation for our RESTful APIs (If you’re not, why not?) It works great out of the box to show other developers the basics of your resources. But the standard responses leave something to be desired. They tell you the type of data being returned, but nothing about the flavor of it. For example, let’s say your resource returns an address. Standard Swagger will show the user this:

Wouldn’t it be nice if your response looked like this?

Well, it can be done and I’m here to show you how.

Initial Setup

I’m going to quickly run through how to get Swagger set up on a new API. The first thing you need to do is install the following NuGet packages.

Swashbuckle.AspNetCore.Swagger
Swashbuckle.AspNetCore.SwaggerGen
Swashbuckle.AspNetCore.SwaggerUI

Then, you enable it in Startup.cs by adding the following lines to ConfigureServices()

services.AddSwaggerGen(c =>
{
c.SwaggerDoc(“v1”, new OpenApiInfo
{
Version = “v1”,
Title = “Address API”
});
});

And these lines to Configure()

app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.DocumentTitle = "Address API - Swagger docs";
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Address API v1");
c.EnableDeepLinking();
c.DefaultModelsExpandDepth(0);
});

Next, we’ll create the Address model for our API to return:

public class Address
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}

And finally, our resource to return an address:

[HttpGet("address")]
[ProducesResponseType(200)]
public ActionResult<Address> GetAddress()
{
return new Address();
}

Now that that’s out of the way, let’s get down to business.

Configure Custom Response

The first thing we have to do is install another NuGet package. This time it’s Swashbuckle.AspNetCore.Filter.

Then we have to create a class that implements Swashbuckle.AspNetCore.Filter.IExamplesProvider<T>. Inside our class, we implement the GetExamples() method.

using Swashbuckle.AspNetCore.Filters;public class AddressExample : IExamplesProvider<Address>
{
public Address GetExamples()
{
return new Address
{
Address1 = "115 Federal Street",
City = "Pittsburgh",
State = "PA",
PostalCode = "15212",
Country = "USA"
};
}
}

The GetExamples()method will be invoked by Swagger whenever it renders the documentation page. It simply returns an instance of our Address object populated with whatever address you want to display (your company’s address or the address of your favorite baseball stadium).

Next, we add a property to our GetAddress resource to tell Swagger what type of response it generates:

[HttpGet("address")]
[SwaggerResponse(200, "An address", typeof(Address))]
[ProducesResponseType(200)]
public ActionResult<Address> GetAddress() {...}

And, finally, we add two more lines to Startup.cs to tell Swagger to use our examples filter:

services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Address API"
});
c.ExampleFilters();
});
services.AddSwaggerExamplesFromAssemblyOf<AddressExample>();

The ExamplesFilters() method turns on the Swagger filters and the AddSwaggerExamplesFromAssemblyOf() method imports any Swagger IExampleFilters<> found in the given assembly. If you implement multiple filters in the same assembly, you only need to call this method once. You do not need to do it for each implemented filter unless those filters are in different assemblies.

At this point, running your solution will produce a Swagger document that looks like this:

PNC Park for the win!

Our example is pretty simple, but imagine your API returns dates or phone numbers or another complex string. Using Swagger’s example filters communicates to consumers of your API how the data you are returning looks and allows them to make smarter decisions when integrating your services in their product.

--

--