前回、NancyでModelBindingを使ってデータを受け取ったので、次はそのデータに対してチェックをしたいと考えました。
何か良いものがないかを探してみたところ、FluentValidation
を使ってデータチェックする、Nancy.Validation.FluentValidation
というNuGetパッケージがありました。
NuGet Gallery | Nancy.Validation.FluentValidation
stackoverflowを見ると、Nancy v0.12以降では特に設定することなく使えそうだったので、試してみることにしました。
configuration - Configure NancyFx with Fluent Validation - Stack Overflow
環境
- Windows7 x64
- Nancy 1.1
- 以下のプロジェクトテンプレートを使用
- Nancy.Validation.FluentValidation 1.1.0
- FluentValidation 5.5.0.0
インストール
NuGetよりNancy.Validation.FluentValidation
をインストールします。
上記のプロジェクトテンプレートには3つのプロジェクトが含まれますが、Nancy.Validation.FluentValidationはすべてのプロジェクトに必要です。
Modelを書く
NancyにModelBindingするModelを書きます。
public class HomeModel { public string Text { get; set; } public string TextArea { get; set; } public string Tel { get; set; } public string Url { get; set; } public string Email { get; set; } public DateTime DateFrom { get; set; } public DateTime DateTo { get; set; } public List<string> ErrorMessages { get; set; } }
一番最後のListは、エラーメッセージを表示するために使います。
Validatorを書く
まずは、
public class HomeValidator : FluentValidation.AbstractValidator<HomeModel>
のように、FluentValidation.AbstractValidator
を継承して、Validation対象のModelの型を指定します。
次にコンストラクタにて、Validation内容を記述します。
public HomeValidator() { // Emptyでないか RuleFor(model => model.Text).NotEmpty(); // Emptyでないか & 自作のメッセージを表示 RuleFor(model => model.Tel).NotEmpty().WithMessage("Required!!"); // 入力必須、かつ、文字長が1-10文字 RuleFor(model => model.TextArea) .NotEmpty() .Length(1, 10); // 正規表現にマッチしているか RuleFor(model => model.Url).Matches(@"^http://"); // メールアドレスの形式にマッチしているか RuleFor(model => model.Email).EmailAddress(); // 日付の大小関係は正しいか RuleFor(model => model.DateFrom).GreaterThan(DateTime.Parse("2015/01/01")); // 日付の大小関係を確認し、独自エラーメッセージ中に、Modelのプロパティ値を参照して表示 RuleFor(model => model.DateTo).LessThan(DateTime.Parse("2015/02/01")) .WithMessage("{0} is not less than '2015/2/1'", model => model.DateTo); // 2つの日付間の大小関係は正しいか RuleFor(model => model.DateFrom).LessThanOrEqualTo(model => model.DateTo); }
Moduleの追加
Moduleでは、
this.BindAndValidate<T>()
にて、ModelBindingとValidationを同時実行ModelValidationResult
にValidation結果が入るため、それを使ってValidationエラー時処理を実行
を以下のように実装します。
// ValidationとModelBindingを同時に実行 var model = this.BindAndValidate<HomeModel>(); if (!ModelValidationResult.IsValid) { // エラーがあった場合の処理 foreach (var error in ModelValidationResult.Errors) { var msg = error.Key + " - " + error.Value.FirstOrDefault().ErrorMessage; model.ErrorMessages.Add(msg); } }
これらにより、ModelBindingと同時にエラーチェックをすることができるようになりました。
実行結果
ソースコード
GitHubに上げました。
thinkAmi-sandbox/NancyFluentValidation-sample
参考
公式ドキュメント
FluentValidationの公式ドキュメントが充実していますので、参考になります。GitHubがメインのようですが、ドキュメントはまだ追いついていない部分もあるため、codeplexの方もリンクを貼っておきます。
- FluentValidation/index.md at master · JeremySkinner/FluentValidation · GitHub
- Fluent Validation for .NET - Documentation