フォーム入力チェックに欠かせないValidation(バリデーション)ですが、「DataAnnotationsだけで大丈夫?」「ModelStateはどう使い分けるの?」「複雑なValidationはどこに書くべき?」と迷ったことはありませんか?
この記事では、C# / ASP.NET Core MVC における代表的な4つのValidation手法を整理し、実務での使いどころや選定のフローチャートまでを詳しく解説します。
✅ この記事でわかること
- Validationの種類とそれぞれの使い分け方
- 実務でのValidation選定フロー
- ASP.NET Core MVCにおけるValidation実装例
実務で役立つValidation選定ガイド
バリデーションを正しく使い分けることは、実務の効率化・品質向上に直結します。このセクションでは、どのValidation手法をいつ使うべきかを早見表とフローチャートで整理します。
✏️ Validation手法の使い分け早見表
シーン | 推奨Validation手法 | 理由 |
---|---|---|
単純な入力検証 | DataAnnotations | 宣言的で簡易 |
複数項目の整合性 | IValidatableObject | モデル内で完結可能 |
ステップ入力/動的UI | TryValidateModel | 部分検証に適応可能 |
外部連携や独自ロジック | ModelState.AddModelError | 柔軟なエラー制御 |
✏️ Validation手法の選定フローチャート
シンプルな検証?
├─ YES → DataAnnotations
└─ NO
└─ モデルで完結可能?
├─ YES → IValidatableObject
└─ NO
├─ 部分検証必要? → TryValidateModel
└─ 外部連携・複雑? → ModelState.AddModelError
DataAnnotationsによる属性ベースのValidation(バリデーション)
チェックタイミング
- ASP.NET Core MVCのモデルバインディング完了時に自動でValidationが実行されます。
- サーバー側では
ModelState.IsValid
で結果を確認できます。 - Razorビューと連携している場合、クライアントサイドでもリアルタイム検証が働きます。
ASP.NET Core MVCで最も基本的なValidation手法がDataAnnotationsです。モデルのプロパティにアノテーションを付与することでValidationルールを定義できます。
特徴とメリット
- ✅ シンプルな構文で基本的なValidation(必須、文字数、形式)に対応
- ✅ クライアントサイドのValidation(JavaScript)にも連携可能
- ✅ 小規模なフォームに適しており、実装も簡易
C#のValidation実装例(DataAnnotations)
public class UserViewModel
{
[Required(ErrorMessage = "メールアドレスは必須です")]
[EmailAddress(ErrorMessage = "正しいメールアドレス形式で入力してください")]
public string Email { get; set; }
[Required(ErrorMessage = "パスワードを入力してください")]
[StringLength(20, MinimumLength = 6, ErrorMessage = "パスワードは6~20文字で入力してください")]
public string Password { get; set; }
}
注意点
- 単項目しかチェックできない
- 条件付きValidationはカスタム属性が必要
IValidatableObjectによるクロスフィールドValidation
チェックタイミング
DataAnnotations
と同様に、モデルバインディング直後にValidate()
メソッドが自動で呼び出されます。- フォーム送信時に
ModelState.IsValid
をチェックすることで検証結果を利用します。
複数項目の整合性確認を行いたい場合、IValidatableObjectが有効です。たとえば「開始日 < 終了日」などのチェックに適しています。
特徴とメリット
- ✅ フィールド間の関係性をValidationできる
- ✅ モデル内部で完結し、凝集性が高く保守しやすい
C#のValidation実装例(IValidatableObject)
public class ReservationViewModel : IValidatableObject
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
if (StartDate > EndDate)
{
yield return new ValidationResult("開始日は終了日より前にしてください。",
new[] { nameof(StartDate), nameof(EndDate) });
}
}
}
注意点
- 外部サービスとの照合には不向き(DIが使えない)
TryValidateModelによる部分Validationの実装
チェックタイミング
TryValidateModel()
を呼び出したその時点で即時にValidationが実行されます。- コントローラ内の任意のタイミングで呼び出せるため、段階的な入力検証に適しています。
DataAnnotations
やIValidatableObject
に定義されたルールが適用されます。
フォームの一部のみを段階的にValidationしたい場合はTryValidateModelが有効です。
特徴とメリット
- ✅ 任意のオブジェクト・プロパティにValidationを適用可能
- ✅ ステップフォームやタブごとのValidationに対応
C#のValidation実装例(TryValidateModel)
if (!TryValidateModel(viewModel.AddressPart, "AddressPart"))
{
return View(viewModel); // エラーあり
}
補足
- 戻り値はbool
- ModelStateに自動でエラー追加
ModelState.AddModelErrorによる柔軟なValidationエラー追加
チェックタイミング
- 明示的に
ModelState.AddModelError()
を呼び出したその時点でModelStateにエラーが登録されます。 - 通常は
ModelState.IsValid
を確認する処理の前に、条件分岐で追加する形式になります。 - 自動検証ではなく**手動検証(ロジックによる判定)**に基づくタイミング制御が可能です。
API照合や業務ロジックを含む複雑なValidationには、手動でエラーを追加するModelState.AddModelErrorが適しています。
特徴とメリット
- ✅ 外部サービス照合や条件付きエラーに対応
- ✅ グローバルエラーや個別エラーの両方に対応
C#のValidation実装例(ModelState.AddModelError)
if (!db.UserExists(model.Email))
{
ModelState.AddModelError("Email", "このメールアドレスは登録されていません。");
}
if (externalService.HasIssue())
{
ModelState.AddModelError(string.Empty, "システムで一時的な問題が発生しています。");
}
まとめ:Validationの選定と併用が品質向上のカギ
Validationは単独ではなく、併用が基本です。DataAnnotationsで基本検証、IValidatableObjectで整合性チェック、ModelStateで外部連携や複雑ロジックを補完し、シーンに応じた設計を行いましょう。
ASP.NET Core MVCにおけるValidation設計を初期段階から明確にすることで、保守性と品質が大幅に向上します。
コメント