C#のFluent Validation - 強力かつ簡単なデータ検証ツール
データ検証は、信頼性の高いソフトウェア開発の柱の1つであり、最新 for .NETアプリケーションでは、それを処理するための堅牢で保守可能かつスケーラブルな方法が必要です。 そこで、強く型付けされた検証ルールを構築するための一般的な.NETライブラリであるFluentValidationの出番です。
彼の詳細なビデオチュートリアル"Fluent Validation in C# - The Powerful Yet Easy Data Validation Tool"で、ティム・コーリーは視聴者にFluentValidationを使用するプロセスを順を追って説明します。この記事では、Tim のウォークスルーに従って、カスタムバリデータ、チェーニングバリデータ、ASP.NET 統合、.NET Core 3.1 や .NET Standard 2.0 などの古いランタイムのサポートなどの関連する概念を統合しながら、重要なポイントとコード例を要約します。
はじめに:なぜFluentValidationなのか?
ティムはビデオの冒頭で、データ検証がしばしば繰り返しになり、面倒になることを説明します。 たとえば、プロジェクトのさまざまな部分で同じような検証ルールをコピー&ペーストすることは、DRY(Don't Repeat Yourself)の原則に違反します。 その代わりに、彼はFluentValidationを紹介します。FluentValidationは.NET検証ライブラリで、無料で、強力で、あなたが所有していないモデルでも動作するので、商用プロジェクトに理想的です。
Timは、学んだことを実践することの重要性を強調し、スキルを身につけるためのWeekly Challengeシリーズを視聴者に紹介しています。
デモ アプリの概要
Timは、ユーザーが入力できるWinFormsのデモ・アプリケーションを使用しています:
名
名字
アカウントバランス
- 生年月日
これはUIデモですが、検証の原則は.NET Core、APIテスト、さらにはコンソールアプリケーションにも同様に適用されます。
ユーザー入力を信頼することの危険性
このとき、ティムは開発者にこう念を押す:"ユーザーを信用してはいけない"。例えば、年齢を10ではなく "ten "と入力するなど、入力は予測できないことがよくあります。データベースに保存する前に、その入力を検証することは不可欠である。
検証ルールのサンプルを概説しています:
姓と名は空であってはなりません。
アカウントバランスは、財務スポンサーの最低要件など、財務規則に従う必要があります。
- 生年月日は、未来または120歳以上であってはなりません。
バリデーション ロジックはどこに行くべきか
Timは、バリデータを設定するためのオプションを探ります:
UIフォームの内部
データアノテーションを使用したモデルクラスで
- FluentValidation を使った別の検証クラスで
彼は、データアノテーションには制限があり、外部ライブラリを使用する場合や、よりカスタムな検証ロジックが必要な場合には適さないことが多いと指摘している。
FluentValidationのインストール
Visual Studio を使用して、Tim は NuGet を介してプロジェクトに FluentValidation を追加します。 彼はバージョン8.1.0をインストールしますが、FluentValidationはクロスプラットフォームで互換性があることに注意してください:
- .NET Standard2.0
*.NET Core
- ASP.NET
*WPF
ザマリン
- その他
Timの設定は、.NET Core 3.1以前をサポートするFluentValidation 11を含む、古いランタイムのサポートを必要とする人々にも有効です。
バリデータ クラスの作成
Timは、新しいクラスを作成することで、強く型付けされた検証ルールを構築することを実演します:
public class PersonValidator : AbstractValidator<Person>public class PersonValidator : AbstractValidator<Person>このクラスには、Person モデルのすべての検証ロジックが含まれています。 フルエント・インターフェースを使用して、検証ルールはコンストラクタの内部で定義されます。
最初のバリデーションルール:最初の名前
Timはラムダ式を使ってルールを書きます:
RuleFor(p => p.FirstName).NotEmpty();RuleFor(p => p.FirstName).NotEmpty();彼はPersonオブジェクトを検証するためにvarバリデータを使用しています:
var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);次に、検証の失敗をループして、ユーザーフレンドリーなメッセージをリストボックスに表示します。
文字列の長さとカスタムメッセージ
ティムは検証ルールを拡張します:
RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");チェイニングバリデータを使用して、このルールは名前が空でなく、短すぎたり長すぎたりしないことを保証します。 Timは、最初の失敗で検証を停止するCascade(CascadeMode.Stop)を紹介しています。
カスタムバリデーション:名前に有効な文字
というメソッドを使ってカスタムバリデータを実装します:
private bool BeAValidName(string name)private bool BeAValidName(string name)これは、スペースとダッシュを除去し、文字列がUnicode文字のみを含むようにし、国際的な文字のサポートを可能にします。
カスタムルールは次のように適用されます:
.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");このメソッド構造は、カスタムの郵便番号検証ロジック機能など、他のフィールドへの適応に最適です:
private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}このようなバリデータで使用することができます:
RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");これは、パブリッククラスのCustomerValidatorやその他のドメイン固有のバリデータを必要とする商用プロジェクトでよく見られます。
エラーメッセージで組み込み変数を使用する
Timは、次のようなプレースホルダを使用してメッセージを動的に強化する方法を示します:
{プロパティ名}。
全長
- {MinLength}と{MaxLength}。
その結果、次のような文脈に沿ったエラーメッセージが表示されます:
"Length of First Name is invalid (was 105)""Length of First Name is invalid (was 105)"これにより、ユーザーは入力エラーを修正しやすくなります。
姓とローカライゼーション
Timは、{PropertyName}による再利用可能な書式設定のおかげで、FirstNameの検証ロジックをLastNameにコピーしています。 また、ASP.NETや、多言語サポートが必要なグローバル アプリケーションのためのWithLocalizedMessage()にも言及しています。
重要: CascadeMode はルール固有です
Timは、CascadeMode.Stopは個々のルールに適用されるものであり、モデル全体にグローバルに適用されるものではないことを明確にしています。 FirstNameとLastNameの両方が空の場合、CascadeModeが設定されていても、両方のルールがトリガーされます。
生年月日の検証
次に、ティムは生年月日が現実的であることを保証するルールを追加します:
private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}このように使用されます:
RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");これは、日付や有効期限のような一時的なデータを検証するのに適したパターンです。
最終的な感想と推奨事項
Timは、FluentValidationの主な利点を要約して締めくくります:
検証ロジックの一元化
カスタムバリデータを簡単に作成
.NET 5と新しいランタイムおよび古いランタイムの両方と互換性があります。
複雑なモデル、リスト、非同期ルールに対応
- 趣味と商業プロジェクトの両方に最適
FluentValidation ドキュメントで、ネストされたルールや電子メール プロパティの検証など、高度な使い方を調べるよう視聴者に勧めています。
結論
FluentValidationは、.NET開発者が、再利用可能で、表現力があり、保守可能な、強く型付けされた検証ルールを構築できるようにします。 .NET Core、.NET 8で開発している場合でも、.NET Core 3.1でレガシーシステムを保守している場合でも、このライブラリを使用すれば、データ検証を簡単に行うことができます。
以下のような特徴があります:
ルール構築のための流暢なインターフェース
カスタム郵便番号検証ロジックのサポート
Visual Studioとの容易な統合
APIテスト、WinForms、ASP.NETとの互換性
- 検証失敗の堅牢な処理
FluentValidationは、あなた for .NETツールキットの必需品です。 詳細については、ビデオをご覧ください。また、C# に関する洞察に富んだビデオをもっと見たい方は、ティムのチャンネルをご購読ください。
ヒント: FluentValidation を使うのが初めてなら、public string Name や string Postcode などのプロパティのルールを持つ独自の CustomerValidator を実装してみてください。 模擬APIやUIフォームを使ってテストし、実際に体験してください。

