API Rest simples para retornar dados
1. Criando controller
Para o controller, é criado uma classe que herda de ControllerBase
. Existe também a herança de Controller
, porém ela é utilizada somente em projetos com manipulação de páginas da Web, não para solicitações de API WEB.
A classe recebe a anotação [ApiController]
, que fornece algumas funcionalidades como binding sources, validações com [Required]
, fazendo com que seja disparado o erro 400 Bad Request automáticamente no caso de erro de validação. Além disso, resultados de erro (código de status 400 ou superior) irão retornar uma resposta em JSON que segue a RFC 7807.
{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}
Em seguida, a classe recebe uma anotação [Route("api/[controller]")
. O argumento [controller]
faz com que a rota receba o nome da classe, tirendo o sufixo Controller. Por exemplo, uma classe chamada Palavras*Controller* terá, nesse caso, a rota api/Palavras.
2. Criando uma rota GET
As rotas seguem uma estrutura de pasta.
api/Palavras
GetDefinicao
No caso de uma classe que está recebendo a rota api/Palavras. Caso seja criado um método, por exemplo, em uma rota customizada chamada GetDefinicao, a URI da rota será de api/Palavras/GetDefinicao.
O método da rota recebe uma anotação indicando sua operação HTTP (GET, POST, PUT, PATCH, DELETE ETC). No caso de uma rota para busca de recursos, utiliza-se [HttpGet]
.
Uma rota GET de recursos geralmente busca os recursos utilizando um repositório, guardando o resultado em uma variável. Em seguida, é retornado os valores para o cliente, que serão automaticamente mapeados para JSON.
Retornos
No ASP.NET Core existe métodos para retornar status code, como BadRequest()
e NotFound()
. Esses métodos estão disponíveis ao definir o tipo de retorno da rota como ActionResult
ou IActionResult
. Nesse caso, utilizaremos o método para retornar Ok junto do conteúdo, que é passado como argumento. É interessante sempre retornar esses status codes, ao invés de lançar uma exceção para que o cliente receba a resposta em JSON e a aplicação não pare.
Para retornar um objeto ou lista de objetos, é passado o tipo dentro de ActionResult
. No caso de uma lista de objetos da classe Command, é retornado .
ActionResult<IEnumerable<Palavra>>
// ou
ActionResult<IList<Palavra>>
A diferença entre passar um tipo para ActionResult<T>
ou utilizar IActionResult
sem passar um tipo é a de que, no primeiro caso, será retornado automaticamente um Ok()
se o tipo for o mesmo do específicado, pois o retorno é convertido para ObjectResult
. Caso contrário, será retornado um status code de erro
IActionResult
é útil quando o retorno pode ser de diversos tipos.
Para rotas que utilizam repositórios async, é passado a assinatura async com o retorno Task, como Task<IActionResult>
, lembrando de passar a assinatura await no método assíncrono. Métodos async são úteis quando se espera uma operação externa, como por exemplo esperar o banco retornar os dados requisitados. Dessa maneira, a aplicação não é bloqueada enquanto aguarda esse retorno, podendo fazer outras requisições com outros clientes. E.g
var results = await _repository.GetAllPalavras(includeTalks);
Código completo
[HttpGet]
public async Task<IActionResult> Get()
{
try
{
// Por ser async, é necessario await
// Caso contrário, será retornado o OK mesmo sem atribuir o results.
var palavras = await _repository.GetAllPalavras();
var retorno = new
{
Count = results.Count(),
Results = palavras
};
return Ok(retorno);
}
catch (Exception)
{
return this.StatusCode(StatusCodes.Status500InternalServerError, "Database failure");
}
}
O código acima retorna os registros no banco para o cliente. Se acontecer algum erro, é considerado como uma falha do servidor, retornando o código 500. Isso pois esse método get não recebe argumentos, como por exemplo o Id de uma entidade, que retornaria o NotFound()
. Por conta disso, caso ocorra algum erro, é por parte do servidor. Por não existir um método para Internal server error, é utilizado o StatusCodes
.
Caso o retorno fosse ActionResult, bastaria retornar com a linha return result;
, que seria convertido automaticamente para um Ok()
.
O método acima retorna um objeto anônimo contendo a quantidade de registros no banco e a lista com os registros. Caso queiramos uma rota que apenas retorna a lista, utilizamos do ActonResult<List<Palvra>>
[HttpGet]
public async Task<ActionResult<List<Palavra>>> Get()
{
try
{
var palavras = await _repository.GetAllPalavras();
// Pelo retorno ser explícito, é retornado o Ok() automaticamente.
// Caso o retorno não seja igual ao especificado, é retornado um erro.
return retorno;
}
catch (Exception)
{
return this.StatusCode(StatusCodes.Status500InternalServerError, "Database failure");
}
}
Top comments (0)