DEV Community

Mo
Mo

Posted on

2

Globally Exception Handling using Exception Filters vs Middleware

In this blog post, I want to talk about using IExceptionFilter(IAsyncExceptionFilter) for globally handling exceptions in ASP.NET Core applications and compare it to using middleware for the same purpose.

Exception filters are classes that implement the IExceptionFilter interface and can be applied to controllers or actions using the [ExceptionFilter] attribute or you can register them globally in Program.cs. They provide a way to handle exceptions that occur during the execution of an action method and can perform custom logic such as logging, displaying error messages, or redirecting to another page.

Middleware are components that are invoked in a pipeline between the request and the response. They can also handle exceptions that occur in the application by using the app.UseExceptionHandler() extension method in the Startup class. They can perform similar tasks as exception filters, but they have access to the entire HTTP context, not just the action context.

One of the main differences between exception filters and middleware is that exception filters are executed after the action method, while middleware is executed before and after the action method. This means that exception filters can only handle exceptions that occur inside the action method, while middleware can handle exceptions that occur anywhere in the pipeline, including in other middleware components or in the framework itself.

Another difference is that exception filters are more granular and can be applied selectively to specific controllers or actions, while middleware is more global and apply to all requests. This means that exception filters can provide more fine-grained control over how to handle different types of exceptions, while middleware can provide a consistent way to handle all exceptions in the application.

Here is some sample code that shows how to use exception filters and middleware for handling exceptions:

For instance, I have created an error record like:

public sealed record Error(string StatusCode, string Message);
Enter fullscreen mode Exit fullscreen mode

and then I implemented IExceptionFilter in the GlobalExceptionFilter class:

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly IHostEnvironment _hostEnvironment;

    public GlobalExceptionFilter(IHostEnvironment hostEnvironment)
    {
        _hostEnvironment = hostEnvironment;
    }

    public void OnException(ExceptionContext context)
    {
        if (!_hostEnvironment.IsDevelopment())
        {
            var error = new Error("500", context.Exception.Message);

            context.Result = new JsonResult(error)
            {
                StatusCode = (int)HttpStatusCode.InternalServerError
            };
        }
        else
        {
            context.Result = new ContentResult
            {
                Content = context.Exception.ToString()
            };
        }            
    }
}
Enter fullscreen mode Exit fullscreen mode

Tip: context.Result accept IActionResult so you have plenty of options here, for instance, you can write new RedirectToPageResult("/Error") and redirect users to a generic error page etc.

Now the only remaining work is to register this class in the Program.cs file:

builder.Services
.AddControllers(c => c.Filters.Add(typeof(GlobalExceptionFilter)));
Enter fullscreen mode Exit fullscreen mode

Summery

  • Middleware runs before and after the action execution pipeline, so it cannot access the action context or the model state.
  • IExceptionFilter runs inside the action execution pipeline, so it has access to the action context and the model state, and it can change the response status code and headers before they are written to the response stream.
  • Exception filters are good for trapping exceptions that occur within actions.
  • Exception filters are not as flexible as error-handling middleware

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay