ASP.NET Core - Tratamento global de exceções (.NET 8)
Neste artigo veremos como realizar o tratamento global de exceções em aplicações ASP.NET Core no .NET 8. |
O bloco try-catch-finally é usado para envolver o código onde existe a possibilidade de uma exceção/erro ocorrer e é constituído das seguintes seções :
Agora ter que definir blocos try-catch em todos os métodos Action de um controlador em sua API pode ser uma tarefa trabalhosa e sujeita a erros, além de deixar o código mais difícil de manter.
Par evitar isso podemos capturar todas as exceções não tratadas usando um manipulador de exceção em um único lugar e não vamos precisar usar o bloco try-catch nos métodos dos controladores. Para isso precisamos criar um middleware customizado que vai fazer o tratamento de exceções.
Usar um middleware permite introduzir lógica antes ou depois da execução de solicitações HTTP e podemos estender isso facilmente para implementar o tratamento de exceções adicionando uma instrução try-catch no middleware e retornar uma resposta HTTP de erro.
Usando middleware no .NET 8
A ASP.NET Core 8
apresenta uma nova abstração através da interface IExceptionHandler para
gerenciar exceções, e, o middleware integrado do manipulador de exceções usa
implementações de IExceptionHandler para lidar com exceções.
Esta interface possui apenas o método TryHandleAsync
que tenta manipular a exceção especificada no pipeline do ASP.NET Core. Se a
exceção puder ser tratada, ela deverá retornar verdadeiro, e se a exceção não
puder ser tratada, ela deverá retornar falso. Isso permite implementar uma
lógica personalizada de tratamento de exceções para diferentes cenários.
A seguir temos uma implementação para uma classe GlobalExceptionHandler :
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; namespace APICatalogo.Exceptions;
public class GlobalExceptionHandler :
IExceptionHandler
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
var problemDetails = new ProblemDetails httpContext.Response.StatusCode = problemDetails.Status.Value;
await httpContext.Response
return true; |
Configurando a implementação de IExceptionHandler
Precisamos de duas
coisas para adicionar uma implementação IExceptionHandler
ao pipeline de solicitação do ASP.NET Core:
1- Registrar o serviço IExceptionHandler com injeção de
dependência;
2- Registrar o ExceptionHandlerMiddleware com o pipeline de solicitação;
... builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails(); |
Podemos chamar o método AddExceptionHandler para registrar GlobalExceptionHandler como um serviço e isso é feito com o tempo de vida Singleton, por isso tenha cuidado ao injetar serviços com um tempo de vida diferente.
Também estamos invocando AddProblemDetails para gerar uma resposta de detalhes do problema para exceções comuns.
Além disso precismos também chamar UseExceptionHandler para adicionar ExceptionHandlerMiddleware ao pipeline de solicitação:
app.UseExceptionHandler(); ... app.Run(); |
Encadeando manipuladores de exceção
Podemos adicionar várias implementações de
IExceptionHandler e elas são chamadas na ordem em que são registradas. Um
possível caso de uso para isso é usar exceções para controle de fluxo.
Você pode definir exceções personalizadas como
BadRequestException e NotFoundException. Elas correspondem ao código de
status HTTP que você retornaria da API.
Aqui está uma implementação de BadRequestExceptionHandler:
public class
BadRequestExceptionHandler :
IExceptionHandler { private readonly ILogger<BadRequestExceptionHandler> _logger;
public BadRequestExceptionHandler(ILogger<BadRequestExceptionHandler>
logger)
if(exception is not BadHttpRequestException badRequestException)
_logger.LogError(
var problemDetails = new ProblemDetails httpContext.Response.StatusCode = problemDetails.Status.Value;
await httpContext.Response
return true; |
Não esqueça que temos que registrar a exceção usando AddExceptionHandler na classe Program:
builder.Services.AddExceptionHandler<BadRequestExceptionHandler>(); |
Desta forma , usar um middleware para tratamento de exceções é uma excelente solução no ASP.NET Core. No entanto, é ótimo termos novas opções usando a interface IExceptionHandler.
A seguir temos as vantagens e desvantagens desta abordagem:
Podemos considerar também a utilização do padrão Result como uma alternativa mais robusta para realizar o tratamento de exceções. (Iremos abordar este assunto em outro artigo)
Este padrão
oferece as seguintes vantagens e desvantagens:
Em muitos casos, uma abordagem combinada pode ser eficaz.
Você pode usar um middleware para capturar exceções globais e realizar ações de nível de aplicação, enquanto utiliza o padrão Result nos controladores para um tratamento mais granular e específico.
E estamos conversados
"(Disse Jesus)
Em verdade, em verdade vos digo que vem a hora e já chegou, em que os mortos
ouvirão a voz do Filho de Deus; e os que a ouvirem viverão."
João 5:25
Referências:
C# - Tasks x Threads. Qual a diferença
DateTime - Macoratti.net
Null o que é isso ? - Macoratti.net
Formatação de data e hora para uma cultura ...
C# - Calculando a diferença entre duas datas
NET - Padrão de Projeto - Null Object Pattern
C# - Fundamentos : Definindo DateTime como Null ...
C# - Os tipos Nullable (Tipos Anuláveis)