In this article we’ll see how add the functionality provided by “Swagger API” through the user interface “Swagger UI” to a RestFul API project based on Asp.NET Core WebApi. The version of the SDK used in the samples is the 2.1.2.

Swagger, for who doesn’t know it, is a framework that allow add API documentation about how to consume a Rest API and provide built-in support to make calls to the API through a built-in user interface. Another features go outside this post. My advice is to review its online web site:

To integrate some of the Swagger functionality in our project we will use the Swashbuckle library you can find in Nuget:

You can find two versions of this library and you have to make sure that to install the Asp.Net Core version.

image

Once installed, it provide, among others, 2 main components.

  1. SwaggerGen: which by reflection, read the logic structure of our service: “Routes”, “Models”, “Actions” y “Controllers”, and expose a JSON object describing this structure according the Swagger 2.0 specification.

  2. SwaggerUI: which read and interprest the JSON object, and build a user interface which allow us to access interactively to the documentation of the API and do call tests to the API.

In first place, we registry in the startup class “SwaggerGen” as a dependency in the service container. We’re going to do, first, with a basic configuration and later we’re going to extend it with a more advanced setup:

//Swagger setup. Need to be added after MVC setup.
services.AddSwaggerGen(cfg => {
    cfg.SwaggerDoc(
        "bioregProjectsApi",
        new Info
        {
            Version = "0.6",
            Title = "API for projects administration"
        });
});

after, we configure out project to use “Swagger UI”, which will add to our project the elements needed for generate the “Swagger UI”.

app.UseSwaggerUI(cfg =>
{
    cfg.SwaggerEndpoint("/swagger/bioregProjectsApi/swagger.json", "Bioreg Projects Api");
});

and now we can test our RestFul API with the generated Swagger UI

                 image

If we expand one of the actions, we can see the information about the action, the parameters for the call and the models used by the action. Also we have a button “TryOut” to test the operation.

By default “SwaggerGen” have created for us an URI: “/swagger/[apiname]/swagger.json” which expose a JSON object describing our API and we can use it in the Swagger Hub. Although, we must have in mind that the generated JSON code by SwaggerGen follow the “Swagger 2.0” specification and not the “OpenAPI 3.0”.

Well, we already have running our “Swagger UI” interface, we can, now,  do some adjustments to the configuration to get a better rich and intuitive UI. And,  instead of show a huge set of changes, I’m going to show them step by step and showing the sample code at the same time.

Default endpoint route

By default, the generated “Swagger UI”  is available from the URI “/Swagger”, but we can change this behavior so it will be available from the URI  we want, even set it up to empty  so it can be accessed from directly from the URL like in the next code sample.

app.UseSwaggerUI(cfg =>
{
    cfg.SwaggerEndpoint("/swagger/bioregProjectsApi/swagger.json", "Bioreg Projects Api");
    cfg.RoutePrefix = string.Empty;
});

now the access to “Swagger UI” will be: http://myapi/  instead of http://myapi/swagger.

Customize using C# XML comments

SwashBuckle” also allows to use C# special XML comments to customize and to enrich the information showed by the “Swager UI“.  For accomplish this, first of all is to enable the XML documentation generation in the properties of our project.

image

later, we  add the next line of code to the configuration of “SwaggerGen”, in the startup class, to set that it have to include the XML comments file in the generation process of the “Swagger UI”.

services.AddSwaggerGen(cfg => {
    cfg.SwaggerDoc(
        "bioregProjectsApi",
        new Info
        {
            Version = "0.6",
            Title = "API for projects administration"
        });
    cfg.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Edigital.Bioreguladores.Projects.Api.xml"));
    cfg.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Edigital.Bioreguladores.Projects.Data.Domain.xml"));
});

As you can see, in the above sample code, we’ve added also the XML documentation file generated for the assembly which contains the data domain. The XML comments over the members of the data domain classes will be use to enrich the information showed by “Swagger UI” about the data models used by the API. For example:

/// <summary>
/// The email or the username of the user owner of the project. Both need to be unique.
/// </summary>
/// <example>plutoh@gmail.com</example>
[BsonElement("OwnerId"), BsonRequired]
public string Owner { get; set; }

will be show, as you see in the next image, wherever the model appear in the API documentation, .

image

Once added the XML comments files to the “SwaggerGen” configuration, we can use the most common tags (summary, param, return, remarks, etc…) to enrich the documentation of our API.

The tag “response” is not an official tag  but is supported by the “SwaggerGen”. This tag allow us add information about the responses produced by our API. if we need specify a concrete type for any of the responses, we have to add an attribute “ProducesResponseType“, indicating the type, to the method in addition to the XML comments. Such as showing in the next code sample.

/// <summary>
/// Get a set of projects by a query.
/// </summary>
/// <returns>A collection of liteweight version of projects.</returns>
/// <param name="pageSize"></param>
/// <param name="page">Is Optional, will be 0 if its not provided.</param>
/// <param name="query">
/// </param>
/// <remarks>Page parameter is optional and is set to 1 if its not provided</remarks>
/// /// <response code="200">Success, return a collection of projectLiteDto. Or an empty array if the the query does not find any projects.</response>
/// <response code="400">If query has a bad format or has unknown fields.</response> 
/// <response code="501">Something wrong occurs with this operation.</response>
[HttpPost]
[ProducesResponseType(typeof(IEnumerable<ProjectLiteDto>),200)]
[ApiExplorerSettings(GroupName = "bioregProjectsApi")]
public IEnumerable<ProjectLiteDto> Get([FromBody] string query, [FromQuery] int pageSize = 20, int? page = 0)
{
    return _projectRepository.GetProjects(query, pageSize, page);
}

And in the next image, we can see where appear the information for each one of the tags.

image

Setup the model default view

Another interesting feature to setup is the model default view. By default, the “Swagger UI” show a JSON plain representation of the model. We can change this behavior, so it show instead a graphic view of the model, by using the method “DefaultModelRendenring” with the option “ModeRendering.Model“.

app.UseSwaggerUI(cfg =>
{
    cfg.SwaggerEndpoint("/swagger/bioregProjectsApi/swagger.json", "Bioreg Projects Api");
    cfg.SwaggerEndpoint("/swagger/bioregProjectsAsyncApi/swagger.json", "Bioreg Projects Async Api");
    cfg.RoutePrefix = string.Empty;
    cfg.DefaultModelRendering(ModelRendering.Model);
});

image

Group operations by http method type

Another interesting thing we can setup is the order and the grouping of the operations which appear in the “Swagger UI”. In this case, we are going to group the operations by the Http method type (Get, Post, Put, Delete, Patch, etc).  In a Restful API the most relevant information about an operation is the Http method needed to make the call. For a RestFul API, we are going to set it up like this, but if the API is not RestFul, could be better group the operations in another way.

To set this configuration we’ll use the method “TagActions” of the “SwaggerGen” configuration:

services.AddSwaggerGen(cfg => {
    cfg.SwaggerDoc(
        "bioregProjectsApi",
        new Info
        {
            Version = Configuration["Prefs:ApiVersion"],
            Title = Configuration["Prefs:ApiTitle"]
        }
    );
    .
    .
    .
    cfg.TagActionsBy(p => p.HttpMethod); //Group and order by httpMethod.
});

which force to generate a “Swagger UI” showing operations grouped by Http method type.

image

Is possible to group the operations by another tags. This feature, even being useful, go out of the scope of this post. And for small size APIs, this kind of grouping  is enough.

Group operations by version

There’s another type of grouping more general, like it would be an API version. However the use of this type of grouping depends of each project. In this grouping mode, is possible set, for each version, a different JSON metadata file.

In first place, we have to setup a second “SwaggerDoc” for the second version. In the example, I’ve set 2 versions: one for synchronous operations and another for the asynchronous:

//Swagger setup. Need to be added after MVC setup.
services.AddSwaggerGen(cfg => {
    cfg.SwaggerDoc(
        "bioregUsersApi",
        new Info
        {
            Version = Configuration["Prefs:ApiVersion"],
            Title = Configuration["Prefs:ApiTitle"]
        });
    cfg.SwaggerDoc(
        "bioregUsersApiAsync",
        new Info {
            Version = Configuration["Prefs:AsyncApiVersion"],
            Title = Configuration["Prefs:AsyncApiTitle"]
        });
    cfg.ExampleFilters();
    cfg.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Edigital.Bioreguladores.Users.Api.xml"));
    cfg.TagActionsBy(p => p.HttpMethod); //Group and order by httpMethod.
    cfg.DescribeAllEnumsAsStrings(); //show enums names instead enum values.
});

later, we have to add a second “Endpoint” for the access to our additional version:

app.UseSwaggerUI(cfg => 
{
    cfg.SwaggerEndpoint("/swagger/bioregUsersApi/swagger.json", "Bioreg User Api");
    cfg.SwaggerEndpoint("/swagger/bioregUsersApiAsync/swagger.json", "Bioreg Users Async Api");
    cfg.RoutePrefix = string.Empty;
    cfg.DefaultModelRendering(ModelRendering.Example);
});

and finally, doing use of the “ApiExplorer“, which already is included in the 2.1 version of Asp.NET Core, we decorate the methods with the “ApiExplorerSettings” attribute to group them according to its version:

[HttpDelete("{projectId}")]
[ApiExplorerSettings(GroupName = "bioregProjectsApi")]
public void DeleteById(string projectId) => _projectRepository.RemoveProject(projectId);

[HttpDelete("{projectId}")]
[ApiExplorerSettings(GroupName = "bioregProjectsAsyncApi")]
public async Task DeleteByIdAsync(string projectId) => await _projectRepository.RemoveProjectAsync(projectId);

and, just we can see that, in the generated “Swagger UI”, appear in the top right  zone, a dropdown with the links to the configured versions:

image

and that is all,  up here is this brief introduction to the “Swagger UI” using SwashBuckle.

SwashBuckle is a fantastic framework, which offer a lot of possibilities of extension and customization. Here, only we have seen some to of them. Probably the most interesting, I think.

I hope this article serves like a “Getting Started” over the benefits of add an user interface to our RestFul APIs.