Exception Handling in .NET 8.0

IExceptionHandler is an interface introduced in .NET 8 for handling exceptions globally. ASP.NET Core applications use this interface internally for their built-in exception handling. This method is better than other approaches we've seen.

The IExceptionHandler interface requires you to implement one method, TryHandleAsync, which works with the HTTP context and the error. A benefit is that you don't need to write extra middleware because it uses the existing UseExceptionHandler middleware in .NET.

This lets you define error handling for each error separately if needed, making your code more modular and easier to maintain.

Tools that I have used for this tutorial.

  • VS 2022 Community Edition 17.10
  • .NET 8.0
  • Minimal API

Source Code can be downloaded from GitHub

Let us create a minimal API with the below endpoint. For demo purposes, I have added this endpoint to the Program.cs file.

app.MapGet("/ExceptionHandler/", () =>
{
    throw new Exception("Testing the IExceptionHandler in .NET 8.0");
})
.WithName("ThrowException")
.WithOpenApi();

Global Exception Handler class.

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

namespace IExceptionHandlerTutorial.Infrastructure
{
    public class GlobalExceptionHandler(
        
        ILogger<GlobalExceptionHandler> logger

        ) : IExceptionHandler
    {

        public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, 
                                              Exception exception, 
                                              CancellationToken cancellationToken)
        {
            logger.LogError(exception, "An unhandled exception has occurred.");

            var problemDetails = new ProblemDetails
            {
                Title = "An error occurred",
                Status = StatusCodes.Status500InternalServerError,
                Detail = exception.Message
            };

            return true;
        }
    }
}

The TryHandleAsync method is where you put all your exception-handling code. This method should return true if the exception is handled properly. If the exception isn't handled or for specific use cases, it can return false. This is useful when you want to use multiple IExceptionHandler implementations for different errors.

After you've finished implementing IExceptionHandler, go to Program.cs and add the following code.

//Exception handling
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails();

This ensures that your IExceptionHandler implementation is registered in the application's service container along with ProblemDetails. Additionally, you need to add the built-in exception middleware to the pipeline, as mentioned earlier.

Now, run the application and call the minimal API endpoint we created before.

API endpoint

Conclusion

By implementing IExceptionHandler and integrating it into your application, you streamline exception handling, making your code more modular and maintainable. Registering your IExceptionHandler with the service container and adding the built-in exception middleware ensures that your application can effectively manage errors. Now, with everything set up, you can run your application and test the error handling through the minimal API endpoint we created. This approach not only simplifies your exception-handling process but also enhances the robustness and clarity of your code.