Roadmap › 1. .NET › Step 22
Err
Exception Handling & Custom Error Handling in .NET — Every Way, Every App Type
Exceptions from first principles to production — try/catch/finally, filters, rethrowing, custom exception hierarchies, exceptions vs Result pattern, async and parallel exceptions, global handlers (AppDomain, TaskScheduler, Application_Error), every way to handle errors in Web Forms, MVC 5, Web API 2, ASP.NET Core MVC and Web API (middleware, exception filters, IExceptionHandler, ProblemDetails, UseStatusCodePages), Blazor error boundaries, background services, SQL and HTTP error handling, retries with Polly, custom error pages, error codes and correlation ids.
What it is & where it is used
An exception is an object that represents an error and interrupts normal flow until some code catches it. Good error handling means:
- Prevent what you can (validate input, check state).
- Handle what you can recover from, close to where it happens (retry, fallback, user message).
- Let the rest bubble up to a global handler that logs everything and returns a safe, consistent response.
- Never hide errors (empty catch), leak details (stack traces) to users, or use exceptions for normal control flow.
| Layer | Strategy |
|---|---|
| Method | Guard clauses, try/catch only for errors you can handle, using for cleanup |
| Service / domain | Throw meaningful (custom) exceptions or return a Result for expected failures |
| Infrastructure | Translate low-level errors (SqlException, HttpRequestException), retry transient faults |
| Application boundary | Global handler: log with correlation id, map to HTTP status / friendly page |
| Process | Last-chance handlers for crashes (log and exit) |
Versions & history
| Year | .NET feature |
|---|---|
| 2002 | Structured exception handling in C#/VB.NET; Web Forms Page_Error, Application_Error, customErrors |
| 2009–2013 | MVC [HandleError], IExceptionFilter; Web API 2 IExceptionHandler, IExceptionLogger (2014) |
| 2012 | async/await — exceptions flow through Task; AggregateException from Task.Wait |
| 2015 | C# 6 exception filters (catch (X ex) when (...)) |
| 2016 | ASP.NET Core UseExceptionHandler, UseDeveloperExceptionPage, UseStatusCodePages |
| 2018 | [ApiController] automatic 400 ProblemDetails (Core 2.1) |
| 2019–2022 | ProblemDetails for errors; AddProblemDetails (.NET 7) |
| 2023 | .NET 8 IExceptionHandler, throw helpers (ArgumentNullException.ThrowIfNull, ArgumentOutOfRangeException.ThrowIfNegative) |
| 2024–2025 | .NET 9/10 refinements: StatusCodeSelector for exception handler, ProblemDetails improvements; RFC 9457 replaces RFC 7807 |
Lifecycle
What happens when an exception is thrown in an ASP.NET Core request:
throwcreates the exception object and captures the stack trace.- The CLR searches up the call stack for a matching
catch(exception filterswhenare evaluated during this search). - If found:
finallyblocks of the frames being unwound run, then the catch block runs. - If no catch in your code: the exception propagates out of the controller → MVC exception filters (if any) → middleware pipeline → exception handler middleware (
UseExceptionHandler/IExceptionHandler), which logs it and writes an error response (ProblemDetails or error page). - If nothing handles it (e.g. in a background thread),
AppDomain.UnhandledExceptionfires and the process terminates.
Tools used to develop
- Debugger: Exception Settings window (break when thrown), Call Stack,
$exception. - Logging:
ILogger+ Serilog/NLog → Seq, Application Insights, ELK (see the Logging course). - Error tracking: Sentry, Raygun, Application Insights Failures blade, ELMAH (.NET Framework).
- Resilience: Polly,
Microsoft.Extensions.Http.Resilience. - Analyzers: CA1031 (don't catch general exceptions), CA2200 (rethrow to preserve stack), CA1062 (validate arguments).