Roadmap › Exception Handling & Custom Error Handling in .NET — Every Way, Every App Type › Module: Exceptions in C#
Lessons in this course (9)
2. Custom exceptions and exception hierarchies
Basic★ Must knowLesson 2 of 9
csharp
// A small hierarchy for the application's expected failures
public abstract class AppException : Exception
{
protected AppException(string message, Exception? inner = null) : base(message, inner) { }
public abstract string ErrorCode { get; }
}
public sealed class NotFoundException(string entity, object key)
: AppException($"{entity} '{key}' was not found.")
{
public override string ErrorCode => "not_found";
}
public sealed class BusinessRuleException(string message, string code) : AppException(message)
{
public override string ErrorCode => code; // e.g. "credit_limit_exceeded"
}
public sealed class ConflictException(string message) : AppException(message)
{
public override string ErrorCode => "conflict";
}
// Usage in a service
public async Task ApproveAsync(int orderId)
{
var order = await db.Orders.FindAsync(orderId) ?? throw new NotFoundException("Order", orderId);
if (order.Total > order.Customer.CreditLimit)
throw new BusinessRuleException("Order exceeds the customer's credit limit.", "credit_limit_exceeded");
}The global handler maps NotFoundException → 404, BusinessRuleException → 422/400, ConflictException → 409, anything else → 500.