2017/3/31 追記
ASP.NET 4.5 でクライアント側での検証用スクリプトが大幅に変更されており、この記事の要である Page_Validators はインラインでページには埋め込まれませんが、WebResource.axd ハンドラでダウンロードされるスクリプトファイルに定義されており、以下の記事のコードをそのまま利用して「クライアント側での検証結果の表示」は可能です。
RequiredFieldValidator, RegularExpressionValidator 等の検証コントロールを利用してユーザー入力の検証を行う場合、クライアント側(ブラウザ)で行われた検証結果をチェックする方法を備忘録として書いておきます。
検証コントロールをページに配置すると、デフォルト(即ち、EnableClientScript プロパティが true)では、クライアント側(ブラウザ)でユーザー入力を検証するためのスクリプトを ASP.NET が自動的に生成してくれます。
検証用のスクリプト本体は、検証コントロールのアセンブリに埋め込まれており、それを外部ファイルとして HTTP ハンドラ(WebResource.axd)を利用して取得する仕組みになっています。(ちなみに、インラインでページに埋め込まないのは、ブラウザでキャッシュできるようにするためです)
さらに、form 要素の onsubmit 属性に以下のようにスクリプトが設定されます。
onsubmit="javascript:return WebForm_OnSubmit();"
WebForm_OnSubmit メソッドの定義は ASP.NET が自動生成し、インラインで html コードに含めます。今回のサンプルコード(この記事の一番下にアップしたもの)の場合は以下のようなスクリプトが生成されます。
<script type="text/javascript">
//<![CDATA[
function WebForm_OnSubmit() {
OnClientValidation();
if (typeof(ValidatorOnSubmit) == "function" &&
ValidatorOnSubmit() == false) return false;
return true;
}
//]]>
</script>
上のコードで、if (typeof(ValidatorOnSubmit) から return true; までは、検証コントロールによって追加された検証用のスクリプトです。これにより、WebForm_OnSubmit メソッドは、クライアント側(ブラウザ)でのユーザー入力の検証結果が NG の場合 false を返すので、submit イベントがキャンセルされます(結果、ポストバックはかかりません)。
その前にある OnClientValidation(); は、Page_Load メソッドの中で RegisterOnSubmitStatement メソッドを使って登録した、自作のメソッドです。head 要素内にインラインで定義してあります。一番下のサンプルコードを参照してください。これが今回の記事のテーマです。
OnClientValidation メソッドで使っている Page_Validators は、ASP.NET が検証コントロールからレンダリングした span 要素の DOM の配列で、これに検証結果その他の情報が含まれています。今回のサンプルコードでは以下のようにインラインで定義されます。
Page_Validators の定義以外にもクライアント側(ブラウザ)での検証に必要なスクリプトがインラインで多々定義されています。詳細は、この記事の一番最後にアップしたサンプルコードを実行したときにレンダリングされる html ソースを見てください。
<script type="text/javascript">
//<![CDATA[
var Page_Validators = new Array(
document.getElementById("RequiredFieldValidator1"),
document.getElementById("RegularExpressionValidator1"),
document.getElementById("RequiredFieldValidator2"),
document.getElementById("RegularExpressionValidator2"),
document.getElementById("RequiredFieldValidator3"),
document.getElementById("CustomValidator1"));
//]]>
</script>
この Page_Validators を使って、全ての検証用コントロールのクライアント側(ブラウザ)での検証結果を取得し、alert を使って表示してみました。この記事の一番上の画像がその結果です。
なお、Page_Validators という名前は Microsoft の公式文書で公開されているわけではなく、将来、予告なしで変更される可能性もありますので注意してください。(ASP.NET 3.5, ASP.NET 4 は Page_Validators という名前であることを確認しましたが)
上の画像を表示したサンプルコードは以下の通りです。実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
// クライアント側での検証が OK となって初めてポスト
// バックがかかり、このメソッドに制御が飛んでくる。
// ブラウザで JavaScript が有効になっており、クライ
// アント側で検証が行われている限り、Page.IsValid
// が false になることはない("Page is NOT valid"
// という文字が Label に表示されることはない)はず。
if (Page.IsValid)
{
Label1.Text = "Page is valid";
}
else
{
Label1.Text = "Page is NOT valid";
}
}
protected void Page_Load(object sender, EventArgs e)
{
// RegisterOnSubmitStatement メソッドにより form 要素
// の onsubmit 属性に以下のスクリプトが設定される。
//
// onsubmit="javascript:return WebForm_OnSubmit();"
//
// この WebForm_OnSubmit メソッドの中に、第三引数(以
// 下の例では cstext)に渡したスクリプトが設定される。
// これにより、ポストバックする直前にクライアントスク
// リプトを起動し、必要があればポストバックをキャンセ
// ルすることもできる。
string csname = "OnSubmitScript";
Type cstype = this.GetType();
ClientScriptManager cs = Page.ClientScript;
if (!cs.IsOnSubmitStatementRegistered(cstype, csname))
{
string cstext = "OnClientValidation();";
cs.RegisterOnSubmitStatement(cstype, csname, cstext);
}
// 注:
// Validator を Page に配置すると WebForm_OnSubmit
// メソッドの中には検証用のクライアントスクリプトも
// 追加される。順序は、まず上記 cstext に指定した
// スクリプト、次に Validator の検証用スクリプトと
// なる。
}
// CustomValidator のサーバー側での検証用
protected void CustomValidator1_ServerValidate(
object source, ServerValidateEventArgs args)
{
string membership = args.Value.ToLower();
if (membership == "gold" || membership == "silver")
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>WebSurfer's Page - 実験室</title>
<script type="text/javascript">
//<![CDATA[
// CustomValidator のクライアント側での検証用
function CustomValidator1_ClientValidate(sender, args) {
var membership = args.Value.toLowerCase();
if (membership === "gold" || membership === "silver") {
args.IsValid = true;
} else {
args.IsValid = false;
}
}
// クライアント側全 Validator の検証結果を取得。
// Page_Validators は ASP.NET が Validator から
// レンダリングした span 要素の DOM の配列。
// 詳しくは html ソースに含まれる定義を参照。
// 将来、Page_Validators と言う名前その他は予告
// なしで変更される可能性もあるので注意。
function OnClientValidation() {
var msg = "クライアント側での検証結果:\n";
for (var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
var ctrl =
document.getElementById(validator.controltovalidate);
if (ctrl != null) {
if (validator.isvalid) {
msg += "○: " + validator.id + "/" +
ctrl.id + "/\"" + ctrl.value + "\"\n";
}
else {
msg += "×: " + validator.id + "/" +
ctrl.id + "/\"" + ctrl.value + "\"\n";
}
}
}
alert(msg);
}
//]]>
</script>
</head>
<body>
<form id="form1" runat="server">
<table>
<tr>
<td>
User Name
</td>
<td>
<asp:TextBox ID="username" runat="server">
</asp:TextBox>
</td>
<td>
<asp:RequiredFieldValidator
ID="RequiredFieldValidator1"
runat="server"
ErrorMessage="ユーザー名は必須入力です。"
ControlToValidate="username"
ForeColor="Red"
Display="Dynamic">
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator
ID="RegularExpressionValidator1"
runat="server"
ErrorMessage=
"半角アルファベットで 40 文字以内にしてください。"
ControlToValidate="username"
ForeColor="Red"
ValidationExpression="^[a-zA-Z''-'\s]{1,40}$"
Display="Dynamic">
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
Email
</td>
<td>
<asp:TextBox ID="email" runat="server">
</asp:TextBox>
</td>
<td>
<asp:RequiredFieldValidator
ID="RequiredFieldValidator2"
runat="server"
ErrorMessage="メールアドレスは必須入力です。"
ControlToValidate="email"
ForeColor="Red"
Display="Dynamic">
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator
ID="RegularExpressionValidator2"
runat="server"
ErrorMessage=
"メールアドレスの形式が正しくありません。"
ControlToValidate="email"
ForeColor="Red"
ValidationExpression=
"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
Display="Dynamic">
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
Membership
</td>
<td>
<asp:TextBox ID="membership" runat="server">
</asp:TextBox>
</td>
<td>
<asp:RequiredFieldValidator
ID="RequiredFieldValidator3"
runat="server"
ErrorMessage="メンバーシップは必須入力です。"
ControlToValidate="membership"
ForeColor="Red"
Display="Dynamic">
</asp:RequiredFieldValidator>
<asp:CustomValidator
ID="CustomValidator1"
runat="server"
ErrorMessage=
"Gold または Silver でなければなりません。"
ControlToValidate="membership"
ForeColor="Red"
OnServerValidate="CustomValidator1_ServerValidate"
Display="Dynamic"
ClientValidationFunction=
"CustomValidator1_ClientValidate" >
</asp:CustomValidator>
</td>
</tr>
</table>
<asp:Button ID="Button1"
runat="server"
Text="送信"
OnClick="Button1_Click" />
<br />
<asp:Label ID="Label1" runat="server">
</asp:Label>
</form>
</body>
</html>