Pular para o conteúdo
.NETMiddleware global de exceções
Módulo 03Construindo a Web API

Middleware global de exceções

intermediario 30 min de leitura·Atualizado · .NET 9
Resumo

Em vez de try/catch espalhados por cada ação, centralizamos o tratamento de erros num único ponto usando UseExceptionHandler e retornamos respostas padronizadas com ProblemDetails (RFC 7807/9457).

1. Objetivos de Aprendizagem#

  • Configurar tratamento global de exceções.
  • Retornar respostas de erro padronizadas com ProblemDetails.
  • Diferenciar detalhes de erro entre Development e Production.

2. Pré-requisitos#

  • Serviço de logging (Módulo 16) e endpoints GET (Módulo 18).

3. Conceito#

Tratamento global significa que qualquer exceção não capturada em qualquer camada é interceptada por um único middleware. O porquê: consistência (todo erro sai no mesmo formato), zero repetição e um único lugar para logar. O padrão ProblemDetails define um corpo JSON padronizado para erros HTTP.

O ASP.NET Core oferece duas abordagens modernas:

  • UseExceptionHandler(...) com um handler inline, ou
  • IExceptionHandler (a partir do .NET 8) registrado com AddExceptionHandler.

4. Mão na Massa#

4.1. Setup#

Nenhum pacote extra.

4.2. Implementação Passo a Passo#

  1. Habilite ProblemDetails e um IExceptionHandler:
C#
builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
  1. Implemente o handler:
C#
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;

public sealed class GlobalExceptionHandler : IExceptionHandler
{
    private readonly ILoggerManager _logger;
    public GlobalExceptionHandler(ILoggerManager logger) => _logger = logger;

    public async ValueTask<bool> TryHandleAsync(
        HttpContext context, Exception exception, CancellationToken ct)
    {
        _logger.LogError($"Erro não tratado: {exception.Message}");

        var (status, title) = exception switch
        {
            NotFoundException => (StatusCodes.Status404NotFound, "Recurso não encontrado"),
            _ => (StatusCodes.Status500InternalServerError, "Erro interno do servidor")
        };

        context.Response.StatusCode = status;
        await context.Response.WriteAsJsonAsync(new ProblemDetails
        {
            Status = status,
            Title = title,
            Detail = "Ocorreu um erro ao processar a requisição.",
            Instance = context.Request.Path
        }, ct);

        return true;
    }
}
  1. Registre no pipeline (bem no início):
C#
app.UseExceptionHandler();

4.3. Executando#

Lance uma exceção proposital numa ação e observe a resposta JSON 500 padronizada, com o erro registrado no log.

5. Exemplo Completo#

C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.ConfigureLoggerService();
builder.Services.AddControllers();

var app = builder.Build();
app.UseExceptionHandler();
app.MapControllers();
app.Run();

6. Boas Práticas e Armadilhas#

FaçaEvite
Centralizar o tratamento em um IExceptionHandlertry/catch repetido em cada ação
Mapear exceções de negócio para status codes específicosRetornar sempre 500 para tudo
Registrar o middleware de erro como o primeiro do pipelineColocá-lo depois do roteamento
Atenção

nunca devolva exception.ToString() ou a stack trace ao cliente em produção — isso vaza detalhes internos e caminhos do servidor.

7. Segurança e Produção#

  • Em Development, UseDeveloperExceptionPage() pode mostrar detalhes; em Production, apenas mensagens genéricas.
  • Logue a exceção completa internamente, mas exponha ao cliente somente title/detail seguros.
  • Correlacione erros com um traceId (o ProblemDetails do ASP.NET Core já inclui um) para diagnóstico sem vazar dados.

8. Exercícios#

  • Fácil: adicione o traceId ao corpo do ProblemDetails.
  • Médio: crie uma NotFoundException de domínio e mapeie-a para 404.
  • Desafio: implemente um segundo IExceptionHandler para exceções de validação e ordene a cadeia de handlers.

9. Resumo#

Centralizamos o tratamento de erros com IExceptionHandler + ProblemDetails, mapeando exceções de domínio para status codes e protegendo detalhes internos em produção.

10. Próximos Passos#

Módulo 20: recurso único, requisições inválidas e relacionamentos pai/filho.

11. Referências#

19-01 — Middleware global de exceções | Curso ASP.NET Core