検証設定
それでは検証設定を行っていきます。設定項目は次のとおりです。
- マスタページにスクリプトの配置
- 検証を行うモデルの作成
- Helpers内に検証メソッドの作成
- モデルクラスに検証ルールを設定
- Controllerの設定(検証メソッド呼び出し)
- ViewPageの設定(ヘルパーメソッドの設定)
順に解説します。
マスタページにスクリプトの配置
xValの設定を行うためにクライアントサイドに下記のスクリプトを配置します。
<script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery-1.3.2.min.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery.validate.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/xVal.jquery.validate.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/xVal.Messages.ja-JP.js") %>"></script>
検証を行うモデルの作成
今回は動作を確認するためにシンプルなEmployeeクラスを作成します。
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using xVal.ServerSide;
using xValAndASP.NET.Helpers;
namespace xValAndASP.NET.Models
{
public class Employee
{
[Required()]
public string Name { get; set; }
[Required(ErrorMessage = "EmployeeIDを入力してください")]
[StringLength(6)]
public String EmployeeID { get; set; }
}
}
Employeeクラスでは名前とIDのみを属性として持たせています。また、DataAnnotationを利用して、属性で必須入力と文字列数2つの検証設定を行っています。
Helpersに検証メソッドの作成
今回は、xValのサンプルをそのまま利用します。
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using xVal.ServerSide;
namespace xValAndASP.NET.Helpers
{
// 検証ルールの作成
public static class DataAnnotationsValidationRunner
{
public static IEnumerable<ErrorInfo> GetErrors(object instance)
{
// (1)変数宣言部分
// 入力されたモデルの型を特定し、MetadataTypeAttributeの列挙子の最初の要素を代入、なければnullを代入
var metadataAttrib = instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault();
// metadataAttribがnullかどうかをチェックし、nullじゃなければメタデータクラスの型を、nullならば、入力されたモデルの型を代入
var buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : instance.GetType();
// buddyClassOrModelClassの型のプロパティのコレクションを取得後、PropertyDescriptor型に変換
var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();
// 入力されたモデルの型のプロパティのコレクションを取得後、PropertyDescriptor型に変換
var modelClassProperties = TypeDescriptor.GetProperties(instance.GetType()).Cast<PropertyDescriptor>();
// (2)LINQ部分
// 戻り値として、エラー情報を格納するErrorInfoオブジェクトを返す
return from buddyProp in buddyClassProperties
join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
// 検証属性のコレクションをattributeに代入
from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()
// 入力されたモデルの値が検証属性による検証で、エラーがあれば抽出
where !attribute.IsValid(modelProp.GetValue(instance))
// プロパティ名、エラーメッセージ、入力されたモデルの型を設定したErrorInfoオブジェクトを生成
select new ErrorInfo(buddyProp.Name, attribute.FormatErrorMessage(string.Empty), instance);
}
}
}
GetErrorsメソッドは、(1)変数宣言部分と(2)LINQ部分(戻り値)に分けて説明します。
(1)変数宣言部分
metadataAttrib変数には、パラメータとして渡され入力されたモデルの型をGetTypeメソッドで特定し、MetadataTypeAttribute属性の列挙子の最初の要素を代入します。もしMetadataTypeAttribute属性の列挙子がなければnullを代入します。
buddyClassOrModelClass変数には、metadataAttrib変数がnullかどうかをチェックし、nullじゃなければメタデータクラスの型を、nullならば入力されたモデルの型を代入します。
buddyClassProperties変数には、プロパティのコレクションを取得するGetPropertiesメソッドを使用して、buddyClassOrModelClassの型のプロパティのコレクションを取得後、指定した型に変換するCastメソッドによりPropertyDescriptor型に変換して代入します。
modelClassProperties変数には、入力されたモデルの型のプロパティのコレクションをGetPropertiesメソッドで取得後、CastメソッドでPropertyDescriptor型に変換して代入します。
(2)LINQ部分
from句では(1)で用意された変数をデータソースとし、各範囲変数に代入します。
重要なのは、buddyClassProperties変数の検証属性の基本クラスValidationAttributeクラスを受け皿にすべての検証属性のコレクションをattribute範囲変数に代入している点です。
where句では、attribute範囲変数を利用して、入力されたモデルの値を検証属性で検証し、エラーがあれば抽出します。
最後にselect句で、プロパティ名、エラーメッセージ、入力されたモデルの型を設定したErrorInfoオブジェクトを生成しています。
つまり、エラーがあった時のみ値を生成して返しています。
モデルクラスに検証ルールを設定
それでは上記で設定されたルールをモデルに適用します。
public void EmployeeValidate()
{
// 検証ルールの設定
var errors = DataAnnotationsValidationRunner.GetErrors(this).ToList();
// ルール違反があった場合はここで動作チェックし、例外を生成
if (errors.Any())
throw new RulesException(errors);
}
GetErrorsメソッドのパラメータとしてEmployeeモデルを渡し、その戻り値をerrors変数に代入し、Anyメソッドで、コレクション内に何か要素が含まれているか(ここでは検証エラーが含まれているかどうか)チェックします。何か検証エラーがあった場合に例外が発生します。
Controllerの設定(検証メソッド呼び出し)
続いてControllerの設定です。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult xVal(Employee emp)
{
try
{
emp.EmployeeValidate();
return RedirectToAction("Complete");
}
catch (RulesException ex)
{
ex.AddModelStateErrors(ModelState, "emp");
return View();
}
}
ポストされた時にEmployeeValidateメソッドを呼び出し、検証チェックします。エラーがなければ別ページにリダイレクトされ、もしエラーが発見された場合はModelStateコレクションにモデルを追加し、検証エラー結果と共に同一ページ上にViewを返します。
ViewPageの設定(ヘルパーメソッドの設定)
ViewPage上では、次のように設定します。
<%@ Import Namespace="xVal.Html"%>
<%@ Import Namespace="xVal.Rules"%>
<%@ Import Namespace="xValAndASP.NET.Models"%>
<中略>
<h1>従業員データ入力ページ</h1>
<br />
<div id="validationSummary">
<%= Html.ValidationSummary() %>
</div>
<% using(Html.BeginForm()) { %>
<div>
名前: <%= Html.TextBox("Emp.Name") %>
</div>
<div>
従業員ID: <%= Html.TextBox("Emp.EmployeeID")%>
</div>
<input type="submit" />
<% } %>
<%= Html.ClientSideValidation("Emp", typeof(Employee))
.UseValidationSummary("validationSummary", "お手数ですが以下の入力項目を再チェックお願いします。")%>
ここでのポイントは各TextBoxヘルパークラスの名前と、xValで提供されているClientSideValidationヘルパーメソッド、UseValidationSummaryメソッドです。
まず、TextBoxヘルパークラスの名前についてですが、xValをViewPage側で設定する際の命名規則は検証を行いたい要素に対して"一律のプレフィックス.検証したいプロパティ名"です。ここでは一律の名前としてEmpを指定し、モデルでEmployeeを指定しています。
次にClientSideValidationヘルパーメソッドと、UseValidationSummaryメソッドについてです。ClientSideValidationヘルパーメソッドは次のように使用します。
Html.ClientSideValidation("要素のプレフィックス", モデルの型)
行っていることは、第1パラメータで検証したいHTMLヘルパーメソッドにTextBoxヘルパークラスで指定したプレフィックスを、第2パラメータに検証を行うモデルの型を設定します。こうすることで、各ヘルパーに対してjQuery Validationを使用したクライアントサイドスクリプトが自動生成されます。
そして、自動生成されたスクリプトをサマリ情報として表示させるために、UseValidationSummaryヘルパーを使用します。
Html.ClientSideValidation("要素のプレフィックス", モデルの型).UseValidationSummary("ValidaionSummaryヘルパー要素名", "概要メッセージ")
UseValidationSummaryメソッドの第1パラメタにページ内のValidationSummaryヘルパーを指定し、第2パラメタに概要メッセージを設定します。
以上の設定で一通りの設定は完了です。実行結果は図2~3のようになります。
利用前の準備が少し煩雑ですが、ご覧頂いた通り、ASP.NET MVCにおける検証ツールとして非常に強力です。ASP.NET MVC V1でアプリケーションを構築する際の検証ツールとして利用を検討してみてはいかがでしょうか。
