🚨 エラーハンドリングデモ

カスタム例外クラスと ExceptionHandlingMiddleware の動作を体験できるデモ

📚 例外クラスの設計

このアプリでは ApplicationException(抽象基底クラス)を継承した4種類のカスタム例外を定義しています。

Exception(.NET標準)
└── ApplicationException(抽象・独自定義)
    ├── ValidationException    → 400
    ├── NotFoundException      → 404
    ├── BusinessRuleException  → 400
    └── InfrastructureException→ 500
例外クラス HTTP 用途
ValidationException 400 入力値エラー
NotFoundException 404 リソース未存在
BusinessRuleException 400 ビジネスルール違反
InfrastructureException 500 DB・外部API障害
Exception(その他) 500 予期しないエラー

🔥 例外を意図的に発火してみる

ボタンを押すと API エンドポイントを呼び出し、ExceptionHandlingMiddleware が例外をキャッチして JSON レスポンスに変換します。

ValidationException

入力値が不正な場合。複数フィールドのエラーをまとめて返す。

NotFoundException

指定IDのリソースが存在しない場合。resourceType・resourceId を返す。

BusinessRuleException

技術的には正常でもビジネスルール違反の場合。ruleName を返す。

InfrastructureException

DB・外部API障害など、システム起因のエラー。service名を返す。

予期しない例外

NullReferenceException 等のランタイムエラー。INTERNAL_ERROR を返す。

💻 レスポンス

← ボタンを押すとここにレスポンスが表示されます

⚙️ ExceptionHandlingMiddleware の仕組み

例外ハンドリングを Controller ごとに書く代わりに、Middleware で一括管理しています。

❌ Bad: Controller 個別に try-catch
// 全 Controller に同じコードが重複する
public async Task<IActionResult> GetUser(int id)
{
    try {
        var user = await _service.GetUser(id);
        return Ok(user);
    }
    catch (NotFoundException ex) {
        return NotFound(new { error = ex.Message });
    }
    catch (Exception ex) {
        return StatusCode(500, ...);
    }
}
✅ Good: Middleware で一括管理
// Controller は業務ロジックに集中できる
public async Task<IActionResult> GetUser(int id)
{
    var user = await _service.GetUser(id);
    return Ok(user);
    // 例外は Middleware がキャッチして
    // JSON レスポンスに変換する
}
ログレベルの方針
例外の種類ログレベル理由
Validation / NotFound / BusinessRule Warning ユーザー起因のため(システムは正常)
Infrastructure / その他 Error システム障害のため(調査・対応が必要)

🔗 参考リンク