DEV Community

Roberto Higor
Roberto Higor

Posted on

Retornando dado específico em API REST ASP.NET Core

Existem algumas diferenças entre a rota de listagem de todos os dados e da listagem específica. Entre elas, as duas que se destacam são:

  • Precisamos receber um parâmetro indicando qual objeto retoranr
  • Precisamos verificar se o objeto existe ou não para que seja retornada uma mensagem de erro.

Uma rota para retornar um objeto do tipo Palavra, sendo especificado pelo seu id recebe a seguinte anotação:

[HttpGet]
[Route("{id}")]
public async Task Palavra GetPalavra(int id)
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

Estamos dizendo pro ASP.NET core que nossa rota irá receber um parâmetro, que estamos chamando de id. Isso pois, caso queiramos retornar a palavra com id 2, iremos realizar uma chamada na rota /api/Palavras/2.

No exemplo acima, dizemos então que a rota recebe um atributo chamado id. Esse atributo é passado como argumento do método de nossa rota, nesse caso int id. Através dessa variável, podemos realizar diversas ações específica a essa rota. No código abaixo, vemos um exemplo simples de retornar uma Palavra por id.

[HttpGet]
[Route("{id}")]
public async Task ActionResult<Palavra> GetPalavra(int id)
{
    try 
    {
        var palavra = await _repository.GetPalavraPorId(id);
        return palavra;
    }
    catch (Exception)
    {
        return this.StatusCode(StatusCodes.Status500InternalServerError, "Database failure");
    }

}
Enter fullscreen mode Exit fullscreen mode

Retornando Not Found

O código acima possuí um problema. No caso de não haver uma palavra com o id recebido, é retornado o código HTTP 204: No Content

Erro 204 no content

O correto seria retornar uma mensagem de erro para o cliente, com o retorno 404 Not Found. Sabemos que existe um método que retorna esse erro, o NotFoun(), basta então checarmos no controller se o retorno do banco está vazio ou não

[HttpGet]
[Route("{id}")]
public async Task ActionResult<Palavra> GetPalavra(int id)
{
    try 
    {
        var palavra = await _repository.GetPalavraPorId(id);
        if (palavra == null) return NotFound();
        return palavra;
    }
    catch (Exception)
    {
        return this.StatusCode(StatusCodes.Status500InternalServerError, "Database failure");
    }

}
Enter fullscreen mode Exit fullscreen mode

Nosso código agora, irá retornar o erro 404 caso a Palavra não seja encontrada no banco de dados, junto de um JSON que segue a RFC 7807.

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  "title": "Not Found",
  "status": 404,
  "traceId": "|6b16da39-47c24449f9eb6854."
}
Enter fullscreen mode Exit fullscreen mode

E, como antes, no caso do método ser executado com sucesso, é retornado nosso objeto em JSON com o código HTTP 200: OK.

Exceptions

Uma boa prática de quando acontecer uma exception é realizar um log dela e retornar um erro 500. Para isso, capturamos a exception e escrevemos no log. Isso pode ser feito tanto no catch quanto em um filtro que captura exceptions.

O cliente então irá receber um código 500 caso ocorra algum erro interno. Se formos lançar essa exception, a aplicação irá ser suspendida, o que não seria uma boa ideia. Exceptions podem ser erros como um banco de dados indisponível, onde não temos controler por ser algo inesperado.

Fontes

https://docs.microsoft.com/pt-br/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0#ar
http://www.macoratti.net/19/06/aspnc_3dwebapi1.htm
https://docs.microsoft.com/pt-br/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0#exception-filters

Oldest comments (0)