Este artigo é parte da série:
Dando continuidade ao processo de criação da nossa REST API, agora vamos ajustar todos os parâmetros de entrada e saída.
Para fins deste exemplo, vamos trabalhar com uma lista em memória, A lista de UFs e capitais feitas no artigo anteror, mas dessa vez, vamos colocar a montagem da lista no construtor da classe para que possamos fazer outros métodos que manipulem a mesma lista.
Na linguagem C#, para escrever um construtor basta fazer um método com o mesmo nome da classe. Como em nosso exemplo, a classe se chama ListaUFController, então se faz necessário criar um método com este mesmo nome. Este método será executado todas as vezes que o objeto for instanciado. Sendo assim, agora o início da nossa classe vai ficar assim:
public class ListaUFController : ControllerBase
{
static List<UF> UFs = new List<UF>();
public ListaUFController()
{
if (UFs.Count == 0)
{
UFs.Add(new UF { Id = 1, Nome = "RJ", Capital = "Rio de Janeiro" });
UFs.Add(new UF { Id = 2, Nome = "SP", Capital = "São Paulo" });
UFs.Add(new UF { Id = 3, Nome = "BA", Capital = "Salvador" });
}
}
Com isso criamos um objeto UFs que é uma lista de objetos UF, depois, no construtor, verificamos se a lista já foi populada e, caso não tenha sido, ela passa a ser populada com as UFs RJ, SP e BA. Se a montagem desta lista estivesse fora do if, a cada vez que o objeto fosse instanciado a lista de UFs ganharia mais 3 elementos.
A nova versão da classe ficou assim:
using Microsoft.AspNetCore.Mvc; using Treino_REST_02.Models; namespace Treino_REST_02.Controllers { [Route("api/Operacao")] [ApiController] public class SomaController : ControllerBase { [HttpPost(Name = "Soma")] public int Soma(int A, int B) { return A + B; } } [Route("api/ListaUF")] [ApiController] public class ListaUFController : ControllerBase { static List<UF> UFs = new List<UF>(); public ListaUFController() { if (UFs.Count == 0) { UFs.Add(new UF { Id = 1, Nome = "RJ", Capital = "Rio de Janeiro" }); UFs.Add(new UF { Id = 2, Nome = "SP", Capital = "São Paulo" }); UFs.Add(new UF { Id = 3, Nome = "BA", Capital = "Salvador" }); } } [HttpGet(Name = "Listagem")] public IEnumerable<UF> ListaUF() { return UFs; } [HttpGet("{IdUF:int}", Name = "MostraUF")] public UF MostraUF(int IdUF) { UF result = UFs.Find(x => x.Id == IdUF); return result; } [HttpPost(Name ="Adiciona")] public IEnumerable<UF> AdicionaUF(UF NovaUF) { UFs.Add(NovaUF); return UFs; } [HttpDelete(Name ="EliminaUF")] public IEnumerable<UF> EliminaUF(int DelId) { UF result = UFs.Find(x => x.Id == DelId); UFs.Remove(result); return UFs; } } }
Agora temos os três verbos mais usados em uma REST API em ação: get, post e delete.
- O método ListaUF continua trazendo a relação de UFs e possui o verbo get, que deve ser utilizado quando o método retorna uma consulta sem fazer alterações na camada de persistência.
- O método MostraUF mostra os dados de uma única UF fazendo a pesquisa por id. Como se trata de uma consulta, utiliza o verbo get.
- O método Adiciona UF acrescenta uma nova UF à lista e possui o verbo post, que deve ser utilizado quando o método faz alterações na camada de persistência, como inclusões e alterações em bancos de dados.
- O método EliminaUF elimina uma das UFs da lista e utiliza o método delete, que deve ser utilizado quando a operação irá resultar em eliminação de itens na camada de persistência.
Execute o programa e veja os 3 métodos funcionando. É agora que começa nossa aventura de hoje.
Execute qualquer um dos métodos dentro do Swagger e observe que não importa o que aconteça, o nosso retorno sempre é do tipo 200 (Ok). Na verdade, se você olhar mais abaixo, nos tipos de retorno do dos nossos métodos, só temos o tipo 200.
Existe um tipo chamdo ActionResult específico para trabalhar com REST API, e nele podemos especificar os tipos de retorno. Por exemplo, digamos que o usuário entrou com um id inválido no método MostraUF, é interessante que a API entregue o tipo 404 (Not Found) como resposta. Para isso, vamos fazer a seguinte modificação:
[HttpGet("{IdUF:int}", Name = "MostraUF")] public ActionResult<UF> MostraUF(int IdUF) { UF result = UFs.Find(x => x.Id == IdUF); if (IdUF == 0) { return BadRequest(); } if (result == null) { return NotFound(); } return Ok(result); }
Agora execute o Swagger novamente, execute o método MostraUF e faça dois testes: no primeiro digita uma id válida, entre 1 e 3 e veja a resposta, depois digite uma id inválida e observe o código de erro 404 sendo entregue como resposta. Faça o teste também entrando com zero no id e veja a resposta BadRequest.
Apesar de estar tudo funcionando dentro do planejado, observe que logo abaixo do código 404 existe uma palavra “Undocumented”, e que na lista de “resposes” lá no final só consta 200 Ok. Agora vamos informar ao Swagger sobre as possibilidades de retorno. Para isso, faça a seguinte modificação:
[HttpGet("{IdUF:int}", Name = "MostraUF")] [ProducesResponseType(200)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult<UF> MostraUF(int IdUF) { if (IdUF == 0) { return BadRequest(); } UF result = UFs.Find(x => x.Id == IdUF); if (result == null) { return NotFound(); } return Ok(result); }
Agora o Swagger vai te mostrar que todos os tipos de retorno estão documentados.
E assim ficou o nosso código ao final deste exercício:
using Microsoft.AspNetCore.Mvc; using Treino_REST_02.Models; namespace Treino_REST_02.Controllers { [Route("api/Operacao")] [ApiController] public class SomaController : ControllerBase { [HttpPost(Name = "Soma")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<int> Soma(int A, int B) { return Ok(A + B); } } [Route("api/ListaUF")] [ApiController] public class ListaUFController : ControllerBase { static List<UF> UFs = new List<UF>(); public ListaUFController() { if (UFs.Count == 0) { UFs.Add(new UF { Id = 1, Nome = "RJ", Capital = "Rio de Janeiro" }); UFs.Add(new UF { Id = 2, Nome = "SP", Capital = "São Paulo" }); UFs.Add(new UF { Id = 3, Nome = "BA", Capital = "Salvador" }); } } [HttpGet(Name = "Listagem")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<IEnumerable<UF>> ListaUF() { return Ok(UFs); } [HttpGet("{IdUF:int}", Name = "MostraUF")] [ProducesResponseType(200)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult<UF> MostraUF(int IdUF) { if (IdUF == 0) { return BadRequest(); } UF result = UFs.Find(x => x.Id == IdUF); if (result == null) { return NotFound(); } return Ok(result); } [HttpPost(Name ="Adiciona")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<IEnumerable<UF>> AdicionaUF(UF NovaUF) { UFs.Add(NovaUF); return Ok(UFs); } [HttpDelete(Name ="EliminaUF")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult<IEnumerable<UF>> EliminaUF(int DelId) { if (DelId == 0) { return BadRequest(); } UF result = UFs.Find(x => x.Id == DelId); if (result == null) { return NotFound(); } UFs.Remove(result); return Ok(UFs); } } }
Próximo: