Introdução
O tratamento de exceção é uma parte importante do desenvolvimento de software. Quando algo dá errado em uma aplicação, é importante ter um mecanismo para lidar com a exceção e fornecer um feedback adequado para o usuário. No Asp.Net Core, podemos usar o Middleware UseExceptionHandler
para lidar com exceções globalmente em toda a aplicação. Neste post, vamos apresentar um tutorial detalhado sobre como implementar um controle de erros de forma simples em sua API.
Implementar um tratamento de erro global em uma API pode trazer uma série de benefícios significativos para o desenvolvimento e manutenção do seu aplicativo. Aqui estão alguns dos principais benefícios:
- Padronização do tratamento de erro: ajuda a garantir que a abordagem de tratamento de erro seja igual em todos os endpoints e evita duplicação de código.
- Resposta amigável ao usuário: Você pode retornar respostas amigáveis e compreensíveis aos usuários quando ocorrerem erros. Evite mensagens técnicas!
- Segurança: Tratar erros de forma adequada ajuda a evitar a exposição de informações sensíveis ou detalhes técnicos aos usuários ou a pessoas mal-intencionadas.
- Monitoramento e análise: Permite que você tenha uma visão geral dos tipos de erros que estão acontecendo com mais frequência.
- Tratamento de exceções não previstas: Um tratamento de erro global permite capturar exceções não previstas.
Criando o Middleware
Para criar o Middleware de tratamento de exceção, crie uma nova classe e nomeie-a como TratamentoErroGlobal.cs. Em seguida, adicione o seguinte código:
public static class TratamentoErroGlobal{ public static void AdicionarTratamentoErroGlobal(this IApplicationBuilder app) { app.UseExceptionHandler(applicationBuilder => { applicationBuilder.Run(async contexto => { contexto.Response.StatusCode = (int)HttpStatusCode.InternalServerError; var erroNoRequest = contexto.Features.Get<IExceptionHandlerFeature>(); if (erroNoRequest != null) { var detalheProblema = new ProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Type = "Erro", Title = "Erro no servidor", Detail = "Ocorreu um erro interno." }; await contexto.Response.WriteAsJsonAsync(detalheProblema); } }); }); } }
Aqui está uma explicação sobre como essa classe funciona:
public static void AdicionarTratamentoErroGlobal(this IApplicationBuilder app)
- Isso define um método de extensão para a interface
IApplicationBuilder
que adiciona o Middleware de tratamento de erro global.
- Isso define um método de extensão para a interface
app.UseExceptionHandler(applicationBuilder => { ... })
- Aqui, o método
UseExceptionHandler
é chamado noIApplicationBuilder
, configurando o Middleware de tratamento de exceção. O código dentro do bloco é uma função de Callback que lida com a exceção e cria uma resposta apropriada.
- Aqui, o método
contexto.Response.StatusCode = (int)HttpStatusCode.InternalServerError
- Define o status code da resposta HTTP para 500 (InternalServerError) para indicar um erro no servidor.
var erroNoRequest = contexto.Features.Get<IExceptionHandlerFeature>()
- Obtém as informações sobre a exceção que ocorreu durante o processamento da requisição.
var detalheProblema = new ProblemDetails{ ... }
- Aqui, criamos um objeto
ProblemDetails
, que é uma classe padrão do ASP.NET Core usada para representar detalhes de um problema. Definimos o status, o tipo, o título e os detalhes do erro.
- Aqui, criamos um objeto
await contexto.Response.WriteAsJsonAsync(detalheProblema)
- Escreve a resposta como JSON contendo os detalhes do problema (representados pelo objeto
ProblemDetails
), utilizando o método assíncronoWriteAsJsonAsync
.
- Escreve a resposta como JSON contendo os detalhes do problema (representados pelo objeto
Configurando a Injeção de Dependência do Middleware
Para configurar o Middleware de tratamento de exceção, precisamos adicionar o seguinte código em nossa classe Program.cs:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); var app = builder.Build(); app.AdicionarTratamentoErroGlobal(); app.MapControllers(); app.Run();
O método AdicionarTratamentoErroGlobal
é um método de extensão da classe TratamentoErroGlobal
. Isso significa que ele estende a funcionalidade da interface IApplicationBuilder
, permitindo adicionar um novo Middleware de tratamento de erros global à pipeline de processamento de solicitações do ASP.NET Core. Quando chamado no contexto da configuração da aplicação, ele configura o tratamento de erros global de forma apropriada.
Testando o Tratamento de Exceção Global
Para testar o tratamento de exceção global, podemos adicionar um código que gera uma exceção não tratada em uma de nossas Controllers. Quando executarmos a aplicação e acessarmos essa rota, o Middleware de tratamento de exceção retornará uma resposta em JSON para o usuário com os tratamentos que criamos anteriormente.
Crie uma classe chamada ExemploController.cs e adicione o seguinte código:
[ApiController] [Route("api/exemplo")] public class ExemploController : ControllerBase { [HttpGet] public Task ObterExemplo() { throw new Exception("Exceção causada intencionalmente"); } }
Podemos compilar e iniciar a API e, em seguida, através do Postman, fazer uma chamada GET para a rota http://localhost:[Porta]/api/exemplo. O retorno esperado deve ser o seguinte:
{ "type": "Erro", "title": "Erro no servidor", "status": 500, "detail": "Ocorreu um erro interno." }
Conclusão
O tratamento de exceção é uma parte importante do desenvolvimento de software. No Asp.Net Core, podemos usar o Middleware UseExceptionHandler
para lidar com exceções globalmente em toda a aplicação. Neste post, vimos como configurar o Middleware de tratamento de exceção e devolver uma resposta personalizada para o usuário.
Esta abordagem apresenta os seguintes benefícios:
- Simplicidade:
UseExceptionHandler
é simples de configurar. Você pode simplesmente fornecer um Middleware para tratamento de erros e o ASP.NET Core cuida do resto. - Recursos integrados: fornece suporte integrado para exibir páginas de erro amigáveis ao desenvolvedor ou retornar respostas de erro no formato JSON, dependendo do tipo de solicitação.
- Consistência: por ser um recurso padrão do ASP.NET Core, ele garante uma abordagem consistente de tratamento de erros em diferentes partes do seu aplicativo.
- Configuração centralizada: você pode configurar facilmente o tratamento de erros em um só lugar, facilitando o gerenciamento e a atualização.
Como contras desta abordagem, destaco o seguinte:
- Customização limitada: embora forneça algumas opções de personalização,
UseExceptionHandler
pode não cobrir todos os cenários específicos de tratamento de erros que seu aplicativo exige. - Controle de log limitado: você pode ter controle limitado sobre como os erros são logados. O comportamento de log personalizado pode exigir soluções alternativas adicionais.
Em resumo, se as necessidades de tratamento de erros do seu aplicativo puderem ser atendidas pelos recursos fornecidos pelo UseExceptionHandler Middleware, é uma abordagem conveniente e direta. Por outro lado, se você precisar de mais controle, personalização e flexibilidade, construir um Middleware customizado implementando a interface IMiddleware pode ser a melhor escolha (e tema para um próximo post). Tenha em mente a complexidade da sua aplicação, a familiaridade da sua equipe com a tecnologia e as considerações de manutenção a longo prazo ao tomar esta decisão.