というわけで今回はサーバーサイド編です。サーバーサイドでの基本的な検証はモデルに検証用の属性をつけることで実装します。独自に定義したい場合は「ValidationAttribute」 を継承した属性を作成するか、モデルに「IValidatableObject」インターフェースを実装します。
とりあえず基本的な属性付けから。前回使用したUserモデルを流用します。…といか元々はこれように作ったモデルだったりする。
Userモデル
public class User { public int UserId { get; set; } public string UserName { get; set; } [Column("Gender", TypeName = "int")] public Genders Gender { get; set; } public DateTime Birthday { get; set; } public string Email { get; set; } public string CompareEmail { get; set; } public string Tell { get; set; } }
これに検証を設ける場合、ぱっと見思いつくのは…
- UserNameの文字列数
- Emailの正規表現
- CompareEmailのEmailとの差異
- Tellの正規表現
ってとこでしょうか?
Userモデル(検証属性追加)
public class User { public int UserId { get; set; } [StringLength(50)] public string UserName { get; set; } [Column("Gender", TypeName = "int")] [EnumDataType(typeof(Genders))] public Genders Gender { get; set; } public DateTime Birthday { get; set; } [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "アドレスが不正です。")] public string Email { get; set; } [Compare("Email", ErrorMessage = "入力されたアドレスと異なっています。")] public string CompareEmail { get; set; } [RegularExpression(@"[0-9]*$", ErrorMessage = "半角数値のみで入力して下さい。")] public string Tell { get; set; } }
こんな感じになります。各属性の詳細はこちら(System.ComponentModel.DataAnnotations 名前空間)。んで下図が全部引っかかってみた例です。
Createビュー実行結果(Post発生後)
当然ながらサーバーサイドなのでPost発生後に検証されます。実にシンプルで簡単です。次に「ValidationAttribute」は置いておいて「IValidatableObject」を使ってみます。検証内容は「入力されたUserNameが既にデータベースに登録されていないか?」です。
IValidatableObject実装
public class User : IValidatableObject { //・・・中略 public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { using (var context = new MyContext()) { var overlap = context.Users.Where((p) => p.UserName == this.UserName).FirstOrDefault(); if(overlap !=null) { yield return new ValidationResult("そのユーザー名は既に使われています。", new[] { "UserName" }); } } } }
中身は見ての通りです。この検証は必ず実行され、下図の通りに検証されます。
Createビュー実行結果(Post発生後)
これまた期待通りに動作しています。このインターフェースを使えば異なるメンバの比較等の検証を行うことも可能ですね。
さて、本日はこの辺でお仕舞いで、ValidationAttributeに関してはサーバーサイドでの検証にも利用するのでサーバーサイド編で…。