Global Error Handling in ASP.NET Core APIs

June 12, 2025

Summary

Error handling in APIs is tricky. If you don’t manage exceptions properly, users get cryptic errors, and developers waste hours debugging. In this post, we’ll look at how to set up a global error-handling middleware in ASP.NET Core to return clean responses and log issues.

Challenge

By default, unhandled exceptions in ASP.NET Core APIs bubble up and return raw stack traces or generic 500 errors. That’s:

  • Bad for security (you don’t want to leak internals).
  • Bad for users (they don’t know what went wrong).
  • Bad for devs (no structured logging).

Solution

The best practice is to use custom middleware for global exception handling. This ensures consistent error responses and integrates logging (like Azure Application Insights).

Code Example

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

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

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unhandled exception occurred");

            context.Response.StatusCode = 500;
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsJsonAsync(new { error = "Something went wrong." });
        }
    }
}

// Program.cs
app.UseMiddleware<ErrorHandlingMiddleware>();

Takeaways

  • Don’t rely on default exception handling → it’s messy and insecure.
  • Centralize logging & responses → much easier to debug.
  • This scales well in Azure with Application Insights integration.