Tratando erros em uma API ASP.NET Core com Middleware | Blog TreinaWeb
Tratamento de erros é uma parte importante de qualquer aplicação. No ASP.NET Core, isso pode ser facilitado com o uso de Middlewares.
Toda aplicação pode gerar uma exceção, mesmo com vários testes, é impossível prever todos os possíveis cenários. Assim é imprescindível que a aplicação esteja preparada para comportamentos inesperados. Isso é obtido com a implementação de tratamento de erros.
Cada aplicação possui uma melhor forma de tratar os erros, estratégias adotadas em uma aplicação Desktop, pode não ser a ideal para uma aplicação web. E quando estamos falando de uma API ASP.NET Core, o ideal é obter isso com o uso de middlewares.
Tratando erros apenas com try..catch
Geralmente quando uma aplicação C# necessita tratar erros ela implementa um bloco try..catch, como abaixo:
public ActionResult<IEnumerable<Pessoa>> Get()
var pessoas = _repository.GetAll();
return Ok(pessoas);
Mas quando estamos falando de uma API ASP.NET Core, definir blocos try..catch em todas as actions gera códigos duplicados, dificultando futuras manutenções. Além de que a não implementação do bloco try..catch fará a aplicação gerar uma mensagem de erro não amigável e insegura, já que irá expor aspectos internos do código.
Para evitar este cenários podemos definir um tratamento de erro global com o uso de middleware.
Tratando erros com o middleware nativo error handling
No meu artigo sobre o pipeline do ASP.NET Core e o funcionamento dos middlewares cito a existência de um middleware fornecido pelo framework para tratamento de erros. Em alguns projetos do ASP.NET Core este middleware já vem ativado por padrão, algo que não ocorre em uma API ASP.NET Core.
Assim, neste tipo de projeto caso queira fazer uso deste middleware é necessário configurá-lo. Isso pode ser feito diretamente no método Configure da classe Startup, mas o ideal é criar um método de extensão:
public static class ErrorHandlerExtensions
return appBuilder.UseExceptionHandler(builder =>
var exceptionHandlerFeature = context
if (exceptionHandlerFeature != null)
var logger = loggerFactory.CreateLogger("ErrorHandler");
logger.LogError($"Error: {exceptionHandlerFeature.Error}");
Message = "Internal Server Error",
await context.Response.WriteAsync(JsonConvert.SerializeObject(json));
E chamá-lo no método Configure:
app.UseErrorHandler(logger);
É importante que o error handling seja definido no início do pipeline dos middlewares, assim ele irá tratar todos os erros da aplicação.
Caso necessite/queira ter um controle maior sobre o tratamento das exceções, também é possível definir um middleware customizado.
Tratando erros com um middleware customizado
Um middleware customizado é uma classe que recebe por parâmetro um objeto RequestDelegate e define um método Invoke:
public ErrorHandler(RequestDelegate next, ILoggerFactory log){
this._log = log.CreateLogger("MyErrorHandler");
private async Task HandleErrorAsync(HttpContext context, Exception exception)
var errorResponse = new ErrorResponse();
errorResponse.StatusCode = HttpStatusCode.InternalServerError;
errorResponse.Message = exception.Message;
_log.LogError($"Error: {exception.Message}");
_log.LogError($"Stack: {exception.StackTrace}");
context.Response.StatusCode = (int) errorResponse.StatusCode;
await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
Note que nesta implementação é utilizado um bloco try..catch para interceptar qualquer exceção gerada no pipeline dos middlewares. Quando isso ocorrer, a exceção é registrada no log e uma mensagem de erro é retornada ao usuário.
Assim, como o middleware nativo, este também precisa ser registrado na classe Startup e isso será feito com um método de extensão:
public static IApplicationBuilder UseMyErrorHandler(this IApplicationBuilder appBuilder)
return appBuilder.UseMiddleware<ErrorHandler>();
Que deve ser aplicado no início do pipeline:
app.UseMyErrorHandler();
Devido a imprevisibilidade das exceções, elas não podem ser menosprezadas. Nenhuma aplicação está imune e ignorá-las não deve ser uma opção, mesmo que isso seja realidade em alguns projetos.
A implementação de um procedimento global com middlewares, customizado ou não, facilita (e muito) o tratamento e log das exceções da aplicação. Assim, não tenha medo os erros, importando o escopo do projeto, procure tratá-los e forneça repostas amigáveis para seus usuários.