ASP.NET Core Web API - Tratando erros globalmente - II


Neste artigo veremos como realizar o tratamento de erros de forma global em aplicações ASP .NET Core Web API.

Continuando a primeira parte do artigo veremos agora como criar um middleware customizada para tratar os erros globalmente.

Podemos criar nosso próprio middleware para tratar exceções e ganhar mais flexibilidade adicionando um rastreamento de pilha, um nome de tipo de exceção, um código de erro ou qualquer outra coisa que gostaríamos de exibir na mensagem de erro.

Tratando os erros globalmente com um middleware customizado

Usando o mesmo projeto criado no artigo anterior vamos criar uma nova pasta no projeto chamada Suporte, e, nesta pasta vamos criar a classe CustomExceptionMiddleware.

Esta classe possui uma assinatura básica cujo código é mostrado a seguir:

using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace Api_GlobalErros.Suporte
{
    public class CustomExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        public CustomExceptionMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
               await HandleExceptionAsync(httpContext, ex).ConfigureAwait(false);
            }
        }
    }
}

Neste código estamos passando um delegate de request para qualquer middleware que a seguir o processa ou passa para o próximo middleware da cadeia.

Se um request não for bem-sucedido, uma exceção será lançada e o método HandleExceptionAsync será chamado no bloco catch.

Agora vamos atualizar o método InvokeAsync definindo o código do método HandleExceptionAsync
:

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Net;
using System.Threading.Tasks;
namespace Api_GlobalErros.Suporte
{
    public class CustomExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        public CustomExceptionMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(httpContext, ex).ConfigureAwait(false); 
            }
        }
        private static Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            context.Response.ContentType = "application/json";
            int statusCode = (int)HttpStatusCode.InternalServerError;
            var result = JsonConvert.SerializeObject( 
                new { StatusCode = statusCode, ErrorMessage = exception.Message });
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = statusCode;
            return context.Response.WriteAsync(result);
        }
    }
}

Se tudo correr bem, o delegate _next deve processar o request e a Action Get de nosso controlador deve gerar a resposta bem-sucedida.

Se um request não for bem-sucedido (por isso que estamos forçando uma exceção), nosso middleware acionará o bloco catch e chamará o método HandleExceptionAsync.

Nesse método, apenas configuramos o código de status de resposta e o tipo de conteúdo e retornamos uma resposta.

Agora vamos criar uma classe estática na pasta Suporte chamada ExceptionMiddlewareExtension com o seguinte código:

using Microsoft.AspNetCore.Builder;
namespace Api_GlobalErros.Suporte
{
    public static class ExceptionMiddlewareExtension
    {
        public static void UseCustomExceptionMiddleware(this IApplicationBuilder app)
        {
            app.UseMiddleware<CustomExceptionMiddleware>();
        }
    }
}

Agora para habilitar a utilização do nosso middleware basta ajustar o código do método Configure da classe Startup conforme mostrado a seguir:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }
            app.UseHttpsRedirection();

            app.UseCustomExceptionMiddleware();
            app.UseMvc();
        }

Executando o projeto novamente agora iremos obter o seguinte resultado para uma requisição GET:

1- No navegador

2- No Postman

Vimos assim como aproveitar o tratamento global de exceções na ASP .NET Core para garantir que todas as exceções sejam capturadas eliminando assim a necessidade de escrever código adicional nos métodos Actions dos Controllers.

Com o tratamento global de exceções, precisamos apenas escrever o código de manipulação de exceção para nosso aplicativo uma vez em um local.

Dessa forma é uma boa prática escrever seu próprio middleware personalizado para lidar com exceções globalmente.

Pegue o projeto completo aqui: Api_GlobalErros.zip

Referências:


José Carlos Macoratti