Introduction
Handling errors properly is one of the most important parts of building a robust ASP.NET Core Web API. If exceptions are not handled correctly, your application may crash, expose sensitive data, or provide a poor user experience.
Global exception handling allows you to manage all errors in one place instead of writing try-catch blocks in every controller or service. This makes your code cleaner, easier to maintain, and more secure.
In this article, you will learn how to implement global exception handling in ASP.NET Core Web API step by step using simple language and real-world examples.
What is Global Exception Handling?
Global exception handling is a centralized way to catch and handle all runtime errors (exceptions) in your application.
Instead of writing this everywhere:
try
{
// logic
}
catch(Exception ex)
{
// handle error
}
You define a single place that handles all exceptions automatically.
Benefits:
Cleaner code (no repetitive try-catch)
Better error management
Consistent API responses
Improved security
Types of Exceptions in ASP.NET Core
Common types of exceptions you may encounter:
System exceptions (NullReferenceException, DivideByZeroException)
Custom exceptions (business logic errors)
Validation errors
Unauthorized access errors
Understanding these helps you handle them properly.
Approach 1: Using Built-in Exception Handling Middleware
ASP.NET Core provides a built-in middleware to handle global exceptions.
Step 1: Configure Exception Handling in Program.cs
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error");
}
This redirects all exceptions to a specific endpoint.
Step 2: Create Error Controller
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error")]
public IActionResult HandleError()
{
var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
var exception = context?.Error;
return Problem(
detail: exception?.Message,
title: "An error occurred",
statusCode: 500
);
}
}
This ensures a consistent response format.
Approach 2: Custom Middleware for Global Exception Handling
This is the most recommended and flexible approach.
Step 1: Create Custom Middleware
Create a new file: ExceptionMiddleware.cs
using System.Net;
using System.Text.Json;
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionMiddleware> _logger;
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled Exception");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var response = new
{
StatusCode = context.Response.StatusCode,
Message = "Something went wrong",
Detailed = exception.Message
};
return context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
Join the conversation! Your thoughts help the community grow.