DEV Community

Roberto Higor
Roberto Higor

Posted on • Updated on

API Rest simples com Asp.Net Core

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"
}
Enter fullscreen mode Exit fullscreen mode

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   
Enter fullscreen mode Exit fullscreen mode

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>>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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");
    }
}
Enter fullscreen mode Exit fullscreen mode

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");
    }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)