ASP.NET Core - Fundamentals - Error Handling
Source: Dev.to
1. Use try‑catch block
Best practice when re‑throwing exceptions
throw ex;– loses the original stack trace on downstream layers.throw;– preserves the original stack trace, so the API layer receives detailed information.
Only re‑throw (throw;) at lower levels. Creating a new exception (throw new Exception() or a custom exception) also discards the original stack trace.
2. Use custom middleware to centralize exception handling
/// Step 1: Create a middleware class
public class CustomExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public CustomExceptionHandlerMiddleware(
RequestDelegate next,
ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while processing your request");
await HandleExceptionAsync(context, ex);
}
}
private Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return context.Response.WriteAsync(exception.Message);
}
}
/// Step 2: Create an extension method to use the middleware
public static class CustomExceptionHandlerMiddlewareExtensions
{
public static IApplicationBuilder UseCustomExceptionHandlers(this IApplicationBuilder app)
{
return app.UseMiddleware();
}
}
3. Centralize exception handling with IExceptionFilter
Implement an ExceptionFilter class

Register the filter (ASP.NET Core 3.0 sample)

Throw an exception when needed

4. Use IExceptionHandler (ASP.NET Core 8)
Implement IExceptionHandler
public class GlobalExceptionHandler : IExceptionHandler
{
private readonly ILogger _logger;
public GlobalExceptionHandler(ILogger logger)
{
_logger = logger;
}
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
_logger.LogError(exception, "Exception occurred: {Message}", exception.Message);
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Server error -- apply IExceptionHandler for Global"
};
httpContext.Response.StatusCode = problemDetails.Status.Value;
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true; // handled
}
}
Register and use the handler in Program.cs
// Register the exception handler
builder.Services.AddExceptionHandler();
builder.Services.AddProblemDetails();
var app = builder.Build();
// Activate the handler
app.UseExceptionHandler();