Múltiplas documentações em uma única Api - Swagger
Tags: braziliandevs, tutorial, dotnet
Published: 2022-04-29 00:54:20

Bem vindos Devs!

Pensei nesse post devido a necessidade que tive esses dias e por causa da dificuldade de achar algo claro sobre o assunto.

A ideia é vir aqui de vez em quando pra mostrar alguma ideia ou algo que precisamos no dia a dia e que tenha poucos exemplos.

Bora para o que interessa, hoje vamos falar de documentação de API!!
 
A documentação de Api é algo muito importante nos dias de hoje e uma das ferramentas mais utilizada é o Swagger. 

Em muitos cenários precisamos ter uma documentação interna para os desenvolvedores e outra para cliente/fornecedores que precisam consumir as nossas Apis.

Que tal eu mostrar uma forma simples e rápida de separar métodos e ter duas documentações diferentes de uma mesma api utilizando o Swagger? 

**Mas antes de começar, você sabe o que é Swagger?**

O Swagger é framework de código aberto que auxilia os desenvolvedores a documentar uma API automaticamente. Sua interface gráfica possui ferramentas que deixam a visualização mais intuitiva, mostrando os métodos, parâmetros, retornos e modelos de body. 

Além dessa documentação é possível também consumir os endpoints fazendo chamadas diretamente nas rotas. Desta forma você consegue testar de uma forma simplificada sem ter a necessidade de usar algum software especifico.

Agora que sabemos o que é o Swagger, vou mostrar na prática como gerar duas documentações diferentes.

**_Bora Codar_**!!!
Vamos criar uma aplicação em .net 6 e simular uma Api de produtos com 2 métodos um de buscar produto e outro de atualizar preço do produto. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zuc5tqqaqt7bwd36fu7.png)
 
Neste cenário queremos que as 2 rotas apareça para a documentação dos desenvolvedores, mas para os clientes apareçam  apenas a rota de buscar produto.

Primeiro passo é ir na sua classe de controller e adicionar a ação 
**[ApiExplorerSettings(GroupName = "CLIENTE")]**
no método que você quer disponibilizar para o cliente 

Essa ação será responsável pela visibilidade dessa rota apenas para os cliente. Não é possível adicionar mais de uma ação, então iremos marcar essa api apenas para os clientes e vamos tratar para aparecer para os desenvolvedores de outra forma.

Trecho do código da controller

```
namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class ProdutosController : ControllerBase
    {
        [ApiExplorerSettings(GroupName = "CLIENTE")]
        [HttpGet("buscar")]
        public IEnumerable<Produtos> BuscarProduto()
        //...

        [HttpPost("atualizar-preco")]
        public ActionResult BuscarPreco([FromBody] Produtos produto)
         //...

    }
}
```
Depois de configurado a controller vamos para a configuração do Swagger

Na classe Program onde é adicionado o serviço do Swagger devemos adicionar o seguinte código.

```
builder.Services.AddSwaggerGen(option => {
    option.SwaggerDoc("Cliente", new OpenApiInfo { Title = "Produtos API", Version = "v1" }); 
    option.SwaggerDoc("Desenvolvedor", new OpenApiInfo { Title = "Produtos API", Version = "v1" });
    option.DocInclusionPredicate((docName, apiDesc) => {
        if (docName == "Desenvolvedor")
            return true;

        var groupName = apiDesc?.GroupName;
        return groupName?.Trim().ToUpper() == docName.Trim().ToUpper();
    });
});

```
As linhas do SwaggerDoc é a adição das duas documentações uma para o desenvolvedor e outra para o cliente.

A linha DocInclusionPredicate é a onde fazemos a mágica (lembra que falei que iriamos tratar a visibilidade dos desenvolvedores de outra forma? então ela acontece aqui!).

Dentro do DocInclusionPredicate efetuamos uma validação, onde caso o docName seja Desenvolvedor já retorne True. Isto fará com que todos os métodos sejam mapeados para a documentação desenvolvedor na parte gráfica do Swagger.

Caso não seja a documentação do desenvolvedor ele irá validar se o docNome é igual ao GroupName definido lá na método da controller

Para finalizar podemos definir urls diferentes para cada documentação. Isso é feito também na classe Program 

Antes do app.Run()
```
app.UseSwagger(c => c.RouteTemplate = "/swagger-desenvolvedor/{documentName}/swagger.json");
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("../swagger-desenvolvedor/Desenvolvedor/swagger.json", "Produtos API");
    c.RoutePrefix = "swagger-desenvolvedor";
});

app.UseSwagger(c => c.RouteTemplate = "/swagger-cliente/{documentName}/swagger.json");
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("../swagger-cliente/Cliente/swagger.json", "Produtos API");
    c.RoutePrefix = "swagger-cliente";
});

app.Run();
```
Na linha app.UseSwagger deve ser definido o caminho do json.
Na linha app.SwaggerUI deve ser adicionado o mesmo caminho do json do swagger + o nome da aplicação + a rota da url.

Defini as rotas como swagger-desenvolvedor e swagger-cliente

Pronto sua api já está com a documentação segmentada, como podemos ver abaixo a rota atualizar-preço não aparece na documentação de clientes.
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptas3wcfccy9tafj0w0j.png)
 
A intenção do post é mostrar uma forma simplificada, existem algumas outras formas de customizar a UI do Swagger.


Espero que tenham gostado. Até a próxima!