Olá, pessoal!
Há um tempo publiquei um artigo mostrando como criar uma documentação viva com Swagger e .NET Core! Que tal melhorarmos um pouco a documentação gerada?
Este artigo é a continuação da primeira parte, então eu recomendo que antes de continuar sua leitura você tenha lido a primeira parte. Caso ainda não tenha lido, basta clicar neste link e depois voltar pra cá.
No último artigo terminamos criando o método ObterId
no nosso ClienteController
. Esta ação retorna um Guid
, mas vamos para uma aplicação um pouco mais real.
Faremos uma action
que vai simular a atualização de um cliente no banco de dados. Não vamos implementar realmente todos os passos, mas o conceito será o mesmo.
Vamos criar um objeto de response que nossa action receberá por parâmetro:
public class ClienteRequest
{
public Guid Id { get; set; }
public string Nome { get; set; }
public string Sobrenome { get; set; }
public DateTime DataNascimento { get; set; }
}
Para deixar nossa documentação mais rica, é recomendável incluir os comentários para identificar os campos:
public class ClienteRequest
{
/// <summary>
/// Id do cliente que será atualizado
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Nome do cliente
/// </summary>
public string Nome { get; set; }
/// <summary>
/// Sobrenome do cliente
/// </summary>
public string Sobrenome { get; set; }
/// <summary>
/// Data de nascimento do cliente
/// </summary>
public DateTime DataNascimento { get; set; }
}
Vamos criar a action
e utilizar este request.
/// <summary>
/// Atualiza o cliente informado no parâmetro
/// </summary>
/// <param name="clienteRequest">Informações para atualizar o cliente</param>
/// <returns>
/// Retorna o response do cliente atualizado
/// </returns>
[HttpPost]
public IActionResult Atualizar(ClienteRequest clienteRequest)
{
throw new NotImplementedException();
}
Agora vamos ver a documentação!
A próxima implementação é retornarmos um ClienteResponse
. Vamos lá:
public class ClienteResponse
{
public Guid Id { get; set; }
public string NomeCompleto { get; set; }
public DateTime DataNascimento { get; set; }
}
Neste caso substituí as propriedades Nome
e Sobrenome
por uma única propriedade chamada NomeCompleto
. Dessa forma conseguimos diferenciá-lo do request.
Em nossa action vamos fazer uma pequena implementação. Caso o Id informado no request esteja vazio, devemos retornar um 404 (Not found), caso contrário, um 200 (Ok) com um objeto de response:
[HttpPost]
public IActionResult Atualizar(ClienteRequest clienteRequest)
{
if (clienteRequest.Id != Guid.Empty)
return Ok(new ClienteResponse());
else
return NotFound();
}
Vamos dar uma olhada na situação da nossa documentação:
- O que houve aqui?
Bom, o que acontece é que chegamos no ponto em que os mecanismos automáticos não conseguem mais detectar tudo sozinhos – precisamos dar uma forcinha para a documentação.
O problema para a documentação é que o retorno informado é um IActionResult
, então ele fica incapaz de detectar as variações possíveis, mas podemos fazer isso através de anotações no método e comentários!
Podemos identificar as respostas através da anotação ProducesResponseType
. Basta colocá-la acima do método, da mesma forma que a anotação HttpPost
.
[HttpPost]
[ProducesResponseType(typeof(ClienteResponse), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public IActionResult Atualizar(ClienteRequest clienteRequest)
{
//...
}
Com isso já temos um resultado melhor, mas podemos ir um pouco mais longe – basta inserirmos a tag response nos comentários, identificando o code e a mensagem:
/// <summary>
/// Atualiza o cliente informado no parâmetro
/// </summary>
/// <param name="clienteRequest">Informações para atualizar o cliente</param>
/// <returns>
/// Retorna o response do cliente atualizado
/// </returns>
/// <response code="200">Cliente Atualizado</response>
/// <response code="404">Não foi possível encontrar um cliente com o Id informado</response>
/// <response code="500">Erro no servidor</response>
[HttpPost]
[ProducesResponseType(typeof(ClienteResponse), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public IActionResult Atualizar(ClienteRequest clienteRequest)
{
//...
}
Note que o code da tag response é responsável por indicar qual mensagem será utilizada para qual código HTTP.
Vamos entrar novamente na documentação e ver o resultado:
Existem várias outras formas de fazermos isso, inclusive a própria biblioteca possui uma extensão para anotações. Com isso, você poderá utilizar constantes na anotação do método, evitando cópias de textos das ações.
Mas quem sabe falamos disso em um artigo futuro, porque por hoje é só!
Atenção: você pode encontrar a aplicação de exemplo com o Swagger configurado no meu GitHub.
Gostou deste tipo de artigo? Tem alguma sugestão para artigos futuros? Me conte nos comentários.
Até mais!