---
title: "What's the Best Way to Handle Global Exception Handling in .NET Core?"  
description: "What's the Best Way to Handle Global Exception Handling in .NET Core?"  
author: "Anubhav Sharma"  
published: 2024-12-17  
updated: 2026-07-22  
canonical: https://answers.mindstick.com/qa/113652/what-s-the-best-way-to-handle-global-exception-handling-in-dot-net-core  
category: "application"  
tags: ["c#", ".net programming"]  
reading_time: 5 minutes  

---

# What's the Best Way to Handle Global Exception Handling in .NET Core?

*I want to implement [global](https://www.mindstick.com/blog/68/a-role-of-global-assembly-cache-in-the-dot-net-framework) [exception handling](https://www.mindstick.com/articles/12240/introduction-of-exception-handling) in my .NET [Core API](https://www.mindstick.com/forum/159704/what-is-the-use-of-the-producesresponsetype-attribute-in-a-dot-net-core-api-controller-method). What are the [best practices](https://www.mindstick.com/articles/337208/best-practices-for-structuring-html-forms) for using [middleware](https://www.mindstick.com/forum/159733/what-is-the-role-of-middleware-in-dot-net-core-web-api) or [filters](https://www.mindstick.com/forum/1743/can-you-call-directory-getfiles-with-multiple-filters) for consistent [error](https://www.mindstick.com/forum/459/iis-7-error-503-service-unavailable) [responses](https://answers.mindstick.com/blog/387/how-ollama-generates-responses)? Should I [log](https://www.mindstick.com/articles/126269/the-main-uses-of-log-cabins) [errors](https://yourviews.mindstick.com/view/82824/5-doubts-you-should-clarify-about-facebook-errors) at the middleware level or elsewhere?*

## Answers

### Answer by ICSM Computer

Global exception handling in **.NET Core / ASP.NET Core** is a centralized mechanism for catching unhandled exceptions, logging them, and returning consistent error responses to clients. Instead of wrapping every controller action in `try-catch` blocks, you configure a single global exception handler that processes all unexpected errors.

## Why Use Global Exception Handling?

Implementing global exception handling provides several advantages:

- Reduces repetitive `try-catch` code.
- Keeps controllers and services clean.
- Returns consistent API responses.
- Logs errors in one place.
- Prevents sensitive exception details from being exposed.
- Improves application maintainability.

## Option 1: Use Built-in Exception Handler Middleware (Recommended)

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

### Program.cs (.NET 6+)

```cs
// Add middleware before routing
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/error");
}
else
{
    app.UseDeveloperExceptionPage();
}
```

Create an Error Controller:

```cs
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;

[ApiController]
public class ErrorController : ControllerBase
{
    [Route("/error")]
    public IActionResult HandleError()
    {
        // Get exception details
        var context = HttpContext.Features.Get<IExceptionHandlerFeature>();

        // Log exception here if needed

        return Problem(
            title: "An unexpected error occurred.",
            statusCode: 500
        );
    }
}
```

### Advantages

- Built into ASP.NET Core
- Easy to configure
- Works well for MVC and Web APIs
- Supports Problem Details (RFC 7807)

## Option 2: Custom Exception Middleware (Most Flexible)

For enterprise applications, creating custom middleware offers greater control.

### Custom Middleware

```cs
using System.Net;
using System.Text.Json;

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionMiddleware> _logger;

    // Constructor
    public ExceptionMiddleware(RequestDelegate next,
                               ILogger<ExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    // Middleware execution
    public async Task Invoke(HttpContext context)
    {
        try
        {
            // Continue request pipeline
            await _next(context);
        }
        catch (Exception ex)
        {
            // Log exception
            _logger.LogError(ex, ex.Message);

            // Set response
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            context.Response.ContentType = "application/json";

            var response = new
            {
                Success = false,
                Message = "Something went wrong.",
                StatusCode = 500
            };

            await context.Response.WriteAsync(
                JsonSerializer.Serialize(response));
        }
    }
}
```

### Register Middleware

```cs
app.UseMiddleware<ExceptionMiddleware>();
```

### Response

```plaintext
{
    "success": false,
    "message": "Something went wrong.",
    "statusCode": 500
}
```

## Option 3: Exception Filters

Exception filters work only within the MVC pipeline.

```cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public class GlobalExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        context.Result = new ObjectResult(new
        {
            Message = "Server Error"
        })
        {
            StatusCode = 500
        };

        context.ExceptionHandled = true;
    }
}
```

Register:

```plaintext
builder.Services.AddControllers(options =>
{
    options.Filters.Add<GlobalExceptionFilter>();
});
```

## Returning Different Status Codes

It's a good practice to map exception types to appropriate HTTP status codes.

```cs
switch (exception)
{
    case ArgumentException:
        statusCode = StatusCodes.Status400BadRequest;
        break;

    case UnauthorizedAccessException:
        statusCode = StatusCodes.Status401Unauthorized;
        break;

    case KeyNotFoundException:
        statusCode = StatusCodes.Status404NotFound;
        break;

    default:
        statusCode = StatusCodes.Status500InternalServerError;
        break;
}
```

Example responses:

## 400 Bad Request

```plaintext
{
    "message": "Invalid input."
}
```

## 404 Not Found

```plaintext
{
    "message": "Resource not found."
}
```

## 500 Internal Server Error

```plaintext
{
    "message": "Unexpected server error."
}
```

## Logging Exceptions

Use the built-in logging framework rather than writing logs manually.

```cs
_logger.LogError(exception,
    "Error occurred while processing request.");
```

You can integrate logging providers such as:

- Console Logger
- Debug Logger
- Event Log
- Azure Application Insights
- Serilog
- NLog

## Use ProblemDetails for APIs

ASP.NET Core supports RFC 7807 Problem Details, which provides a standard error format.

```cs
return Results.Problem(
    title: "Unexpected Error",
    detail: exception.Message,
    statusCode: 500
);
```

Example:

```plaintext
{
    "type": "about:blank",
    "title": "Unexpected Error",
    "status": 500,
    "detail": "Database connection failed."
}
```

In production, avoid returning internal exception messages to clients; log the detailed exception and return a generic `detail` instead.

## Best Practices

- Use centralized exception handling instead of repetitive `try-catch` blocks.
- Prefer middleware for application-wide exception handling.
- Return appropriate HTTP status codes for different exception types.
- Log full exception details, including stack traces, to a logging provider.
- Avoid exposing sensitive exception information in production responses.
- Use the standard `ProblemDetails` format for REST APIs.
- Handle expected business or validation errors separately from unexpected exceptions.
- Place exception handling middleware early in the request pipeline so it can catch downstream exceptions.

## Which Approach Should You Choose?

| Approach | Best For | Pros | Cons |
| --- | --- | --- | --- |
| Built-in Exception Handler | Most applications | Simple, reliable, integrates with ASP.NET Core | Less customizable |
| Custom Middleware | Enterprise APIs | Full control over logging and responses | More code to maintain |
| Exception Filters | MVC-specific scenarios | Easy for controller logic | Doesn't catch exceptions outside the MVC pipeline |

## Conclusion

For most modern ASP.NET Core applications, [**global exception handling through middleware**](https://www.youtube.com/watch?v=h3oKaV0x8i0) is the preferred solution. It centralizes error handling, produces consistent API responses, integrates cleanly with logging, and keeps business logic free from repetitive error-handling code. The built-in exception handler is sufficient for many applications, while a custom middleware is an excellent choice when you need custom error formats, exception mapping, or advanced logging behavior.


---

Original Source: https://answers.mindstick.com/qa/113652/what-s-the-best-way-to-handle-global-exception-handling-in-dot-net-core

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
