Playground: Swagger no Asp.Net Core com Swashbuckle

William Santos - Jul 27 '20 - - Dev Community

Olá!

Este é mais um post da sessão Playground, uma iniciativa para demonstrar, com pequenos tutoriais, tecnologias e ferramentas que entendo ter potencial para trazer ganhos aos seus projetos.

Apresentando o Swashbuckle

Neste post quero falar sobre o Swashbuckle, uma biblioteca muito útil para ajudar a documentar APIs via Swagger.

A principal vantagem de documentar a API com este recurso é que todos os endpoints ficam disponíveis não apenas para conhecimento como também para testes. Essa é uma grande contribuição para o processo de integração com outros times durante o desenvolvimento e também para a homologação, pois permite que a API seja validada sem a necessidade de se gerar código cliente para acioná-la.

Para tirar proveito do Swashbuckle você vai precisar de:

  • Um editor ou IDE (ex.: VSCode)

Começando a aplicação

Como nossa intenção é apenas documentar uma API e expor suas formas de uso, vamos começar criando e aproveitando a Web API de exemplo do Asp.Net Core. Para isso, vamos criar a infraestrutura da aplicação:

PS X:\code\playground-swagger> dotnet new webapi -o Playground.Swagger.WeatherForecast
Enter fullscreen mode Exit fullscreen mode

Uma vez que vamos aproveitar a aplicação de exemplo, não precisaremos nos preocupar com a criação de um domínio com lógica de negócio como nos posts anteriores. Então, vamos à documentação!

Instalando e configurando o Swashbuckle

Para adicionarmos o Swashbuckler ao nosso projeto, vamos entrar com os seguintes comandos no Terminal:

PS X:\code\playground-swagger\Playground.Swagger.WeatherForecast> dotnet add package Swashbuckle.AspNetCore
Enter fullscreen mode Exit fullscreen mode

Em seguida, vamos registrar o gerador de Swagger em nossa aplicação, para que a documentação possa ser gerada. Para isso, vamos criar uma pasta chamada Configuration na raíz do projeto, e adicionar o arquivo SwaggerConfigurationExtensions.cs com o seguinte conteúdo:

using System;
using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

namespace Playground.Swagger.WeatherForecast
{
    public static class SwaggerConfigurationExtensions
    {
        private const string ApiTitle = "Weather Forecast API";
        private const string ApiVersion = "v1";

        public static IServiceCollection AddCustomSwagger(this IServiceCollection services)
        {
            services.AddSwaggerGen(setup => {
                setup.SwaggerDoc(ApiVersion, new OpenApiInfo
                {
                    Version = ApiVersion,
                    Title = ApiTitle,
                    Description = "API to consume weather foreacast",
                    Contact= new OpenApiContact
                    {
                        Name = "William Santos",
                        Email = "me@wsantos.dev",
                        Url = new Uri("https://wsantos.dev")
                    },
                    License = new OpenApiLicense
                    {
                        Name = "Use under MIT License",
                        Url = new Uri("https://opensource.org/licenses/MIT"),
                    }
                });

                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                setup.IncludeXmlComments(xmlPath);
            });

            return services;
        }

        public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app)
        {
            app.UseSwagger();
            app.UseSwaggerUI(setup => 
            {
                setup.SwaggerEndpoint($"/swagger/{ApiVersion}/swagger.json", ApiTitle);
                setup.RoutePrefix = string.Empty;
                setup.DocumentTitle = ApiTitle;
            });

            return app;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

O código é um pouco extenso mas não é complexo. Vamos detalhá-lo!

O primeiro método desta classe de métodos de extensão é o AddCustomSwagger. Este método registra o gerador de Swagger em nossa aplicação, e inclui algumas informações iniciais para enriquecer a documentação. Observe que, no início do arquivo, é importado o namespace Microsoft.OpenApi.Models, e este namespace abriga a classe OpenApiInfo que é a responsável por conter os dados básicos da documentação, como o contato do desenvolvedor e o modelo de licença da API.

Ainda no registro do gerador de Swagger, temos instruções para que ele consuma um arquivo .xml com os comentários neste formato que adionaremos ao nosso controller à frente.

Já no método UseCustomSwagger informamos à aplicação que ela deve usar o gerador de Swagger, e servir a documentação gerada em /swagger/v1/swagger.json, aproveitando-a para gerar a UI do Swagger, que veremos à frente.

Importante: Neste exemplo listamos apenas uma versão de nossa API, mas é possível listar múltiplas. Para saber como acesse a documentação do Swashbuckle, em inglês.

Para finalizar a configuração do Swashbuckle, vamos incluir nossos métodos de extensão no arquivo Startup.cs, na raiz do projeto, da seguinte forma:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddCustomSwagger();
}
...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...
    app.UseCustomSwagger();
}
Enter fullscreen mode Exit fullscreen mode

Pronto! Agora podemos documentar os endpoints de nossa API para exibir na UI do Swagger.

Documentando a API

Esta é a parte mais simples do processo: vamos adicionar comentários XML em nosso controller para que sejam carregados e exibidos na UI do Swagger.

No arquivo WeatherForecastController, na pasta Controllers, vamos adicionar o seguinte conteúdo logo acima do método Get():

///<summary>
/// Gets weather forecast for the next days asked.
///</summary>
///<param name="Days"></param>
///<remarks>Sample: GET 10</remarks>
///<returns>The forecast for the informed period </returns>
///<response code="200">Returns the weather forecast list </response>
Enter fullscreen mode Exit fullscreen mode

Acima temos um resumo do que faz o método, os parâmetros que ele pode receber (neste caso apenas um, days), o que o método retorna, e quais status HTTP podem ser aguardados como retorno.

Importante: Como estamos testando um código trivial, apenas um status 200 é suficiente. Considere incluir outros status como 400 (para tratar parâmetros inválidos), 404 (para informar que o recurso solicitado não foi encontrado) ou mesmo 500 (caso alguma exceção ocorra).

Agora vamos adequar o método Get para aceitar o parâmetro days. O método deve ser o seguinte:

[HttpGet("{days}")]
public IEnumerable<WeatherForecast> Get(int days)
{
    var rng = new Random();
    return Enumerable.Range(1, days).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}
Enter fullscreen mode Exit fullscreen mode

E, por fim, vamos avisar ao Swagger que nossa API retorna seu conteúdo em formato JSON. Vamos adicionar o seguinte conteúdo ao nosso controller:

using System.Net.Mime;
...

namespace Playground.Swagger.WeatherForecast.Controllers
{
    ...
    [Produces(MediaTypeNames.Application.Json)]
    public class WeatherForecastController : ControllerBase
    {
        ...
    }   
}
Enter fullscreen mode Exit fullscreen mode

Pronto! Agora temos nosso método documentado e pronto para ser apresentado na UI do Swagger.

Toques Finais

Por fim, antes de testarmos nossa aplicação, vamos ao arquivo do projeto Playground.Swagger.WeatherForecast.csproj informar à aplicação que desejamos gerar nosso arquivo de documentação baseado nos comentários XML. Assim os comentários serão lidos e salvos no arquivo .xml que indicamos na configuração do Swashbuckle. Ao mesmo tempo, vamos informar que não queremos receber warnings para o caso de não documentarmos algum método:

<PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

E pronto!

Temos nossa API devidamente documentada e testável.

Se tudo deu certo, o resultado deve ser o seguinte:

Para ter acesso ao código-fonte da aplicação, acesse meu GitHub

Feedback

Gostou? Me deixe saber pelos indicadores. Dúvidas? Me pergunte nos comentários que respondo assim que puder!

Até a próxima!

Referências:
Swashbuckle - GitHub
Introdução ao Swashbuckle e ao ASP.NET Core

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .