Handling exceptions properly in your .NET Core applications is very important. It helps ensure your application runs smoothly, even when things go wrong. In .NET Core 8, Microsoft introduced a new way to handle exceptions using the IExceptionHandler interface, making global exception handling in .NET Core 8 more effective. Let’s see how this works and how you can use it.
What’s New in .NET Core 8?
.NET Core 8 has a new IExceptionHandler
interface to help manage exceptions. This interface is used by the built-in exception handler middleware to handle exceptions in the .NET Core pipeline. The IExceptionHandler
interface has one method called TryHandleAsync
.
The IExceptionHandler
Interface
The IExceptionHandler
interface lets you create custom exception handling logic. It includes the TryHandleAsync
method, which tries to handle an exception and returns true
if it succeeds and false
if it fails. Here’s what the method looks like:
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken
);
How to Implement the IExceptionHandler
Interface
To handle exceptions globally using the IExceptionHandler
interface, you need to create a class that implements this interface. Here’s an example:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
public sealed class GlobalExceptionHandler : IExceptionHandler
{
private readonly ILogger<GlobalExceptionHandler> _logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
_logger = logger;
}
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
_logger.LogError(exception, "Exception: {Message}", exception.Message);
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Server error"
};
httpContext.Response.StatusCode = problemDetails.Status.Value;
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true;
}
}
In this example:
- The
GlobalExceptionHandler
class implements theIExceptionHandler
interface. - The
TryHandleAsync
method logs the exception and returns a JSON response with the problem details.
Configuring Middleware
Here’s how you can set up your custom exception handler middleware in the Program.cs file:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
// Register services
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails();
var app = builder.Build();
// Use exception handler middleware
app.UseExceptionHandler();
// Other middleware registrations...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Run();
Here we need to call the AddExceptionHandler
 method to register the GlobalExceptionHandler
 as a service. It is registered with a Singleton lifetime. Also calling AddProblemDetails
 to generate a Problem Details response for common excception. And, finally calling the UseExceptionHandler
 to add the ExceptionHandlerMiddleware
 to the request.
You can add multiple IExceptionHandler
 implementations, and they’re called in the order they are registered. For example: NotFoundException
or BadRequestException
Â
Summary
Handling exceptions properly is a key part of building reliable applications. .NET Core 8 introduces the IExceptionHandler
interface, which allows you to create custom exception-handling logic. By implementing the TryHandleAsync
method, you can ensure your application handles exceptions gracefully and provides helpful responses to users.
Don’t forget to checkout: Quick C# | .NET Tip 💡: Null vs. Empty Collections