Swagger - Filter examples

OpenAPI topic - examples in your documentation

You can enhance the swagger pages by providing additional coding, to better describe your API

This is done with the Swashbuckle.AspNetCore.Filters library.

Installation

Install the following Nuget Package
Swashbuckle.AspNetCore.Filters

Usage

Check out this set of code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <summary>
/// Returns a list of all notes
/// </summary>
/// <param name="companyKey">This is a code given to your agency</param>
/// <param name="applicationKey">This is a code representing your application</param>
/// <param name="applicationSubKey">This is a code representing an object class in your application</param>
/// <remarks>
/// A result(NoteVM) object containing a collection of
/// note type objects.
///
/// Get: api/v1/Notes
/// </remarks>
[HttpGet("{companyKey}/{applicationKey}/{applicationSubKey}")]
[SwaggerResponse(
StatusCodes.Status200OK,
"HTTP 200 means a model is being returned. Check the WasSuccessfulTrue to determine if it worked properly",
typeof(IResult<List<NoteDto>>))]
[SwaggerResponseExample(
StatusCodes.Status200OK,
typeof(NoteControllerSwashbuckleExamples.NoteGetAllNotesAsync))]
public async Task<IActionResult> GetNotes(
string companyKey,
string applicationKey,
string applicationSubKey)
{
var result = await _noteService.GetAllNotesAsync(companyKey, applicationKey, applicationSubKey);
return Ok(result);
}

Here is a description of the different commands

1
2
3
4
5
6
7
8
9
10
11
12
/// <summary>
/// Returns a list of all notes
/// </summary>
/// <param name="companyKey">This is a code given to your agency</param>
/// <param name="applicationKey">This is a code representing your application</param>
/// <param name="applicationSubKey">This is a code representing an object class in your application</param>
/// <remarks>
/// A result(NoteVM) object containing a collection of
/// note type objects.
///
/// Get: api/v1/Notes
/// </remarks>

This is basic swagger coding. Use the 3 slashes to add documenting comments. This populates the initial row, the parameters, and a section between the method header and the method parameters.

1
[HttpGet("{companyKey}/{applicationKey}/{applicationSubKey}")]

This is part of the syntax to define API

1
2
3
4
[SwaggerResponse(
StatusCodes.Status200OK,
"HTTP 200 means a model is being returned. Check the WasSuccessfulTrue to determine if it worked properly",
typeof(IResult<List<NoteDto>>))]

This is part of the Swagger Annotations. It adds a section called Responses.

1
2
3
[SwaggerResponseExample(
StatusCodes.Status200OK,
typeof(NoteControllerSwashbuckleExamples.NoteGetAllNotesAsync))]

This is part of the Swagger Filters. We need to define NoteControllerSwashbuckleExamples.NoteGetAllNotesAsync an example will be provided later.

1
2
3
4
5
6
7
8
public async Task<IActionResult> GetNotes(
string companyKey,
string applicationKey,
string applicationSubKey)
{
var result = await _noteService.GetAllNotesAsync(companyKey, applicationKey, applicationSubKey);
return Ok(result);
}

This is the actual method being documented.

Here is a sample of the filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using Swashbuckle.AspNetCore.Filters;
using Note.Application.DTOs;
using Note.Shared;

namespace Notes.API
{
public class NoteControllerSwashbuckleExamples
{

public class NoteGetAllNotesAsync : IExamplesProvider<Result<List<NoteDto>>>
{
public Result<List<NoteDto>> GetExamples()
{
return new Result<List<NoteDto>> // Task<IActionResult>()
{
Model = new List<NoteDto>
{

new NoteDto {
CompanyKey = "0",
ApplicationKey="Vendor",
ApplicationSubKey = "1",
Dt = DateTime.Parse("2014-02-07"),
// Dt = new DateTime(2023, 01, 12), //"2023-01-12T08:00:00",
Note= "First Note",
NoteTypeEntity= new NoteTypeDto {
CompanyKey="0",
Id= 4,
NoteType= "NewsFlash",
ShowOnNew = true
},
Who= "maw",
Id= 1
},
new NoteDto {
CompanyKey = "0",
ApplicationKey="Vendor",
ApplicationSubKey = "1",
Dt = new DateTime(2023, 01, 12),
Note = "Jan 15 - they came into the office for the first visit.",
NoteTypeEntity = new NoteTypeDto {
NoteType = "Timeline",
ShowOnNew = false,
Id = 3
},
Who = "maw",
Id = 2
}
},
WasSuccessful = true,
Message = new StatusMessage
{
CorrelationId = Guid.NewGuid(),
Exception = null,
FriendlyMessage = "Retrieved all Notes records successfully",
DetailedMessage = "Retrieved all Notes records successfully",
MessageId = null,
Level = MessageLevel.Info
},
ResultId = 0,
StatusMessages = null,
CustomData = null
};
}
}

NoteControllerSwashbuckleExamples contain nested public classes are repeated over and over until the entire api is documented. (at least examples of objects coming and going are documented)

Some notes

1
public class NoteGetAllNotesAsync : IExamplesProvider<Result<List<NoteDto>>>

the IExamplesProvider is part of the Swagger.Filters - it means you need to create a method called GetExamples.

The type being fed to it is the type of object that is being returned. (Actually my API’s call services. My services return a base model object containing data formatted as <Result<List>)

Program.CS Notes

I have the following swashbuckle filter related code in my program.cs file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
:
using Swashbuckle.AspNetCore.Filters;
:

// this get's examples from the assembly
// learn more at https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters
builder.Services.AddSwaggerExamplesFromAssemblies(Assembly.GetEntryAssembly());
:

//
// https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio
builder.Services.AddEndpointsApiExplorer();

// Swashbuckle documentation
// https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio

// This is from https://www.youtube.com/watch?v=GZY7M4v-d68
builder.Services.AddSwaggerGen(
c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{ Title = "Checkbook API", Version = "v1" });
c.EnableAnnotations();
c.ExampleFilters();

try
{
// from https://code-maze.com/swagger-ui-asp-net-core-web-api/
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var filePath = Path.Combine(AppContext.BaseDirectory, xmlFile);

c.IncludeXmlComments(filePath);
}
catch
{
}
});

// 20230918 - 55475 - Integrate swagger
if (isDevelopment)
{
app.UseDeveloperExceptionPage(); // this added an error page
app.UseSwagger();

// The UseSwaggerUI method call enables an embedded version of the Swagger UI tool.
// this creates the 2 urls
// https://localhost:7230/swagger/v1/swagger.json - to see the json
// https://localhost:7230/swagger/index.html - to see the stuff
app.UseSwaggerUI(c => c.SwaggerEndpoint(
"/swagger/v1/swagger.json",
"Notes API V1"));

}

app.Run();