Quante volte ti sei sentito come gli astronauti dell’Apollo 13 mentre affrontavi eccezioni non gestite nelle applicazioni? Le eccezioni non gestite possono mandare in tilt i sistemi, generare risposte di errore criptiche e rendere i log incomprensibili. Ma non temere, ASP.NET Core fornisce uno strumento potente per gestire queste situazioni: IExceptionHandler.

Per gli sviluppatori impazienti di buttarsi nel codice, il progetto completo è disponibile su GitHub: ExceptionsHandler.NET

Perché IExceptionHandler?

Le eccezioni non gestite possono rovinare l’esperienza degli utenti delle applicazioni e rendere difficile il debug e la risoluzione dei problemi. IExceptionHandler consente di centralizzare la gestione delle eccezioni e fornire risposte coerenti e informative.

Ecco alcuni vantaggi dell’utilizzo di IExceptionHandler:

  • Risposte di errore strutturate e facili da comprendere per gli utenti dell’applicazione.
  • Logging centralizzato delle eccezioni per semplificare il debug.
  • Possibilità di personalizzare la gestione in base al tipo di eccezione.
  • Mantenimento di un codice più pulito e leggibile separando la logica di gestione delle eccezioni.

Implementazione

Creazione del Progetto

Per creare il progetto, apri Visual Studio e crea un nuovo progetto di tipo ASP.NET Core Web API. Assegna un nome al progetto, ad esempio ExceptionsHandler.NET, e scegli la versione di .NET disponibile. Successivamente, crea una nuova cartella chiamata “Handlers” nella radice del progetto e al suo interno aggiungi un nuovo file denominato GlobalExceptionHandler.cs

using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;

namespace ExceptionsHandler.NET.Handlers;

public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        logger.LogError(exception, "Houston, we have a problem! Our code decided to go skydiving without a parachute: {Message}", exception.Message);

        var problemDetails = new ProblemDetails
        {
            Title = "Houston, we have a problem!",
            Status = StatusCodes.Status500InternalServerError,
            Detail = exception.Message
        };

        httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
        await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);

        return true;
    }
}

Il gestore riceve l’eccezione, la registra con un messaggio di errore e restituisce una risposta ProblemDetails strutturata con i dettagli dell’errore.

Configurazione dei servizi

Ora, modifica il file Program.cs per registrare il gestore di eccezioni, il middleware e abilitare ProblemDetails.

using ExceptionsHandler.NET.Handlers;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails();

builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapControllers();

app.UseExceptionHandler();

app.UseHttpsRedirection();

app.Run();

Creazione API

Crea una nuova cartella chiamata Controllers nella radice del progetto e al suo interno aggiungi un nuovo file denominato HoustonController.cs. In questo controller, puoi implementare un’API di esempio per testare il gestore di eccezioni.

using Microsoft.AspNetCore.Mvc;

namespace ExceptionsHandler.NET.Controllers;

[ApiController]
[Route("[controller]/[action]")]
public class HoustonController : ControllerBase
{
    [HttpGet]
    public IActionResult Error()
    {
        throw new Exception("Oxygen leak in our API ship!");
    }
}

Avvia l’applicazione in modalità debug, apri il browser e vai all’URL https://localhost:5000/swagger, dove vedrai l’interfaccia di Swagger UI con l’elenco degli endpoint disponibili; trova l’endpoint /Houston/Error che genera un’eccezione, clicca su “Try it out” e poi su “Execute”, verificando che la risposta sia una ProblemDetails con i dettagli dell’errore e lo status code 500.

Conclusione

La gestione delle eccezioni è spesso vista come un aspetto tecnico e un po’ sottovalutato nello sviluppo delle applicazioni, ma in realtà è fondamentale per garantire la robustezza e la user experience di un sistema. Implementare un gestore di eccezioni ben strutturato, come quello che abbiamo visto con ASP.NET Core, non solo aiuta a mantenere il codice pulito e gestibile, ma permette anche di rispondere agli errori in modo chiaro e coerente.