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

Top comments (0)

Stop sifting through your feed.

Find the content you want to see.

Change your feed algorithm by adjusting your experience level and give weights to the tags you follow.