Skip to main content
Global Exception Handling in ASPNET Core WEB API

Global Exception Handling in ASP.NET Core WEB API

Exception handling is one of the most important part of any application that needs to addressed and implemented properly. With ASP.NET Core, things have changed and are in better shape to implement exception handling. Implementing exception handling for every action method in API, is quite time-consuming and requires extra efforts. So in this post, find out how to implement global exception handling in ASP.NET Core WEB API.

The benefit of implementing global exception handling is that you need to implement in at one place. Any exception occurs in your application will be handled, even when you add new controllers or new methods. That’s cool. Isn’t it? Let’s see how to implement it.

Global Exception Handling in ASP.NET Core WEB API

There are a couple of ways to implement exception handling globally. You might know the introduction of Middleware in ASP.NET Core and ASP.NET Core is shipped with some inbuilt middleware components. And one of the inbuilt ASP.NET Core diagnostic middleware is UseExceptionHandler. Read more about Various ASP.NET Core Diagnostics Middleware

The middleware UseExceptionHandler can be used to handle exceptions globally. You can get all the details of the exception object (Stack Trace, Inner exception, message etc..) and display them on-screen. You can implement like this.

app.UseExceptionHandler(
 options => {
    options.Run(
    async context =>
    {
      context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
      context.Response.ContentType = "text/html";
      var ex = context.Features.Get<IExceptionHandlerFeature>();
      if (ex != null)
      {
        var err = $"<h1>Error: {ex.Error.Message}</h1>{ex.Error.StackTrace }";
        await context.Response.WriteAsync(err).ConfigureAwait(false);
      }
    });
 }
);

You need to put this inside configure() of startup.cs file. Let’s throw some exception to test it. I am using the default template of ASP.NET Core Web API project. So open ValuesController.cs, modify the Get() method to throw an exception.

// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
    string[] arrRetValues = null;
    if(arrRetValues.Length > 0)
    { }
    return arrRetValues;
}

Run the application and you should see following. You can also debug and check in case of exception, it is hitting the app.UseExceptionHandler() code.

UseExceptionHandler() error

This is simple and all good. Another way to implement it using IExceptionFilter and by creating your own custom exception handler. The interface looks like,

namespace Microsoft.AspNetCore.Mvc.Filters
{
    public interface IExceptionFilter : IFilterMetadata
    {
        void OnException(ExceptionContext context);
    }
}

As you can see, there is only one method which needs to be implemented. This method gets called in case of any unhandled exception. So let’s create a class which implements IExceptionFilter.

public class CustomExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        HttpStatusCode status = HttpStatusCode.InternalServerError;
        String message = String.Empty;

        var exceptionType = context.Exception.GetType();
        if (exceptionType == typeof(UnauthorizedAccessException))
        {
            message = "Unauthorized Access";
            status = HttpStatusCode.Unauthorized;
        }
        else if (exceptionType == typeof(NotImplementedException))
        {
            message = "A server error occurred.";
            status = HttpStatusCode.NotImplemented;
        }
        else if (exceptionType == typeof(MyAppException))
        {
            message = context.Exception.ToString();
            status = HttpStatusCode.InternalServerError;
        }
        else
        {
            message = context.Exception.Message;
            status = HttpStatusCode.NotFound;
        }
        context.ExceptionHandled=true;

        HttpResponse response = context.HttpContext.Response;
        response.StatusCode = (int)status;
        response.ContentType = "application/json";
        var err = message + " " + context.Exception.StackTrace;
        response.WriteAsync(err);
    }
}

Here, the code checks for the exception type and set the message and status properties accordingly. You will see a custom exception type MyAppException (line no. 19) is also used. You can create a custom exception class via inheriting the Exception class.

public class MyAppException : Exception
{
    public MyAppException()
    { }

    public MyAppException(string message)
        : base(message)
    { }

    public MyAppException(string message, Exception innerException)
        : base(message, innerException)
    { }
}

Finally, add the filter in the ConfigureServices method of Startup class.

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddMvc(
        config => { 
            config.Filters.Add(typeof(CustomExceptionFilter));
        }
    );
}

Now when you run the application and exception occurs, then it will be handled by onException method. To test custom exception, update Get(int id) method to throw a custom exception.

// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
    string sMessage = "test";
    if (sMessage.Length > 0)
    {
        throw new MyAppException("My Custom Exception");
    }
    return sMessage;
}

Summary

To conclude, this post shows 2 different approaches for handling exception globally either via inbuilt middleware or using an exception filter. The post also talks about creating a custom exception class to help you create your own custom exceptions based on the requirements.

Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.

PS: If you found this content valuable and want to return the favour, then Buy Me A Coffee

31 thoughts to “Global Exception Handling in ASP.NET Core WEB API”

  1. This is not working.

    I am throwing the exception like this and it says unhandled exception
    throw new BadRequestException(errorResponse);

  2. I have created custom exception handling but when i set Environment as “Production” i am not getting error page:

    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    else
    {
    app.UseExceptionHandler(“/Home/Error”);
    }

    Is there something else i need to do ? I tried with throwing error from controller and from API but in both cases , it is showing Json error detail on page instead of Error page view.

  3. Hi. Great post, trying to make it work.
    I get a warning in this line:

    public class CustomExceptionFilter : IExceptionFilter

    That says: “The type ‘IExceptionFilter’ from ‘..\Interfaces\IExceptionFilter.cs’ is in conflict with imported type ‘Microsoft.AspNetCore.Mvc.Abstractions’
    Any Idea? Thanks

    1. It seems you have an interface with the name IExceptionFilter.cs in interfaces folder of your project. Due to the same interface names this error is coming. You should avoid using inbuilt interfaces names while creating your custom interface. There are 2 fixes for this:
      1. Change the name of your custom interface
      2. Or Use complete interface namespace while inheriting.

  4. SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data – im seeing this

  5. Hi, Have tried same way but not working for me. OnException is not calling when an exception throw….

      1. Yes. Its working fine when we change like this in .Net Core
        namespace Microsoft.AspNetCore.Mvc.Filters
        {
        public interface IExceptionFilter : IExceptionFilter // IFilterMetadata
        {
        void OnException(ExceptionContext context);
        }
        }
        and when we run through swagger/getaway , Exception is not returning.. Just we got response as no content.. I think it seems to be becoz of this line response.WriteAsync(err).. any idea?? But its working fine without swagger/gateway integration…. Pls sugget.. thanks MK….

  6. The CustomExceptionFilter example doesn’t appear to work reliably with asp.net core webapi project: With Postman or with Integration tests via System.Net.HTTP.HttpClient. In both cases there are errors, in Postman it says there is no response, in XUnit tests it has a similar error saying it could not process the response. Whereas in Swagger API console it *does* appear to work for some unknown reason.

    I’m guessing the response is not being sent properly but I can’t see why, might be time to break out fiddler on this one.

    1. Found it: You need to add a line of code to the CustomExceptionFilter example:
      context.ExceptionHandled=true;
      Or else it doesn’t work in various clients.

  7. This is really good, thanks for sharing. Just a quick thought about this: “var err = message + ” ” + context.Exception.StackTrace;”
    You’re returning the full stack trace to the client here. That’s not generally going to be good practice. Depending on the severity of the exception, it might be better to log that to a file instead of including it with your response.
    Also, is this the best practice for calling an async method within a synchronous method? It might be relatively safe in this case, but you can be at risk of deadlock calling async code like this. It might be better to call .Wait() as well (and specify a short timeout as this method call should execute very quickly).

  8. I can’t seem to be able to my web api to throw exception through AJAX request.
    I get “net::ERR_INCOMPLETE_CHUNKED_ENCODING” in Chrome Console Log.
    I’m not about to catch the error status code and message with jqXHR

    However, if I directly access the api url in the browser, the exception message can be displayed in view.

  9. this is not working if an exception occurs while serving static files.. its only working for errors in the controller. Can you please help

  10. That’s really a great example. I tried to run it but I got 1 problem, It looks like my web api return nothing if I tried to throw any exception.

    The postman said “Could not get any response”. I debugged it, and it already gone to the “OnException”. But the response does not send back.

    Can you help me out ?

    Marcus.

  11. await context.Response.WriteAsync(err).ConfigureAwait(false);

    gives me an error httpResponse does not contain a definition for WriteAsync. What am I missing here

    Thanks

  12. At the time of Writing

    “`app.UseExceptionHandler()“` I am getting a red squiggle. I don’t know what to import.
    can you help me .

    I code in Visual Studio Code. I am learning by doing things manually. All By Myself. But Doing things Manually is a cumbersome process. Can you please give me series of blog posts or tutorial about this topic.

    It will be a great HELP. TIA

Leave a Reply

Your email address will not be published. Required fields are marked *