Web API  

Global Exception Handling in ASP.NET Core Web API

Introduction

When building modern ASP.NET Core Web APIs, handling errors properly is very important for creating reliable, secure, and user-friendly applications. If exceptions are not handled correctly, they can crash the application, expose sensitive information, or confuse API consumers.

Global Exception Handling in ASP.NET Core Web API provides a centralized way to catch and manage all unhandled exceptions in one place. Instead of writing try-catch blocks everywhere, you can handle errors globally and return consistent, meaningful responses.

In this article, we will explain global exception handling in ASP.NET Core Web API in simple words, how it works, and how to implement it step by step with real-world examples.

What is Exception Handling?

Exception handling is the process of catching and managing runtime errors in an application.

In simple words, when something goes wrong (like a null reference, database error, or invalid input), exception handling ensures the application responds properly instead of crashing.

What is Global Exception Handling?

Global exception handling means handling all exceptions at a central place instead of handling them individually in each controller or method.

Why Use Global Exception Handling?

  • Avoid repetitive try-catch blocks

  • Maintain clean and readable code

  • Return consistent error responses

  • Improve API security

  • Easier debugging and logging

Default Exception Behavior in ASP.NET Core

By default, ASP.NET Core shows detailed error pages in development mode but hides them in production.

  • Development: Detailed error page

  • Production: Generic error message

This is not enough for real-world APIs, where structured error responses are required.

Ways to Handle Exceptions Globally in ASP.NET Core

There are multiple ways to implement global exception handling:

  • Using built-in middleware (UseExceptionHandler)

  • Creating custom middleware

  • Using filters (Exception Filters)

Using Built-in Exception Handling Middleware

ASP.NET Core provides a built-in middleware for handling exceptions.

Example

app.UseExceptionHandler("/error");

app.Map("/error", (HttpContext context) =>
{
    return Results.Problem("An unexpected error occurred");
});

This captures all unhandled exceptions and redirects them to a central handler.

Creating Custom Exception Handling Middleware

Custom middleware gives more control over error handling.

Step 1: Create Middleware Class

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = 500;

        var response = new
        {
            StatusCode = context.Response.StatusCode,
            Message = "Internal Server Error",
            Details = exception.Message
        };

        return context.Response.WriteAsJsonAsync(response);
    }
}

Step 2: Register Middleware

app.UseMiddleware<ExceptionMiddleware>();

Using Exception Filters in ASP.NET Core

Exception filters are used at the controller level.

Example

public class CustomExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        context.Result = new ObjectResult(new
        {
            Message = "Something went wrong"
        })
        {
            StatusCode = 500
        };
    }
}

Register Filter

builder.Services.AddControllers(options =>
{
    options.Filters.Add<CustomExceptionFilter>();
});

Standard Error Response Format

It is a good practice to return structured error responses.

Example JSON Response

{
  "statusCode": 500,
  "message": "Internal Server Error",
  "details": "Something went wrong"
}

Handling Different Types of Exceptions

You can customize responses based on exception types.

Example

if (exception is KeyNotFoundException)
{
    context.Response.StatusCode = 404;
}
else
{
    context.Response.StatusCode = 500;
}

Logging Exceptions

Logging is very important for debugging and monitoring.

Example

_logger.LogError(exception, "An error occurred");

You can use built-in logging or tools like Serilog.

Global Exception Handling vs Try-Catch

FeatureGlobal Exception HandlingTry-Catch
ScopeEntire applicationSpecific block
Code ReusabilityHighLow
MaintenanceEasyDifficult
Clean CodeYesNo

Real-World Example

In an e-commerce API:

  • User requests product data

  • Database fails

  • Exception is caught globally

  • API returns structured error response

This improves user experience and debugging.

Common Mistakes to Avoid

1. Exposing Sensitive Information

Do not return stack traces in production.

2. Not Logging Errors

Always log exceptions for analysis.

3. Overusing Try-Catch

Let global handler manage most errors.

Best Practices for Global Exception Handling

  • Use centralized middleware

  • Return consistent error format

  • Log all exceptions

  • Avoid exposing internal details

  • Handle specific exceptions differently

Summary

Global exception handling in ASP.NET Core Web API is essential for building robust, secure, and maintainable applications. It allows developers to manage all errors in a centralized way, ensuring consistent responses and better debugging. By using middleware, filters, and proper logging, you can create a reliable API that handles errors gracefully and efficiently.