.NET TIPS

[ASP.NET]検証コントロールのエラー・メッセージを一元管理するには?

山田 祥寛
2005/04/22

 「Visual Studio .NETでプログラム・レス開発を学ぶ(前編)」などでも紹介しているように、ASP.NETでは検証コントロールを利用することで手軽にページに検証機能を実装することができる。ただし、そんな検証コントロールにもメッセージ管理といった観点で見た場合には、ちょっとした弱点がある。

 それは、ASP.NETの検証コントロールではエラー・メッセージを一元的に管理できないという点だ。多くの場合、検証時のエラー・メッセージに個性は必要ない。必須チェックのエラーであれば「○●は必須入力です」であるとか、範囲チェックであれば「○●は0〜999までの値で入力してください」など、読者諸兄も多くの場合は決まりきった文言を設定しているはずだ。

 しかし、同じ必須チェックに対するエラー・メッセージなのに、あるページでは「○●は必須入力です」、またあるページでは「○●は必ず入力しなければなりません」、はたまたあるページでは「○●は空にすることはできません」などとメッセージに一貫性がない場合、かえってエンド・ユーザーを混乱させてしまう原因となる。ASP.NETの検証コントロールでは、こうしたメッセージの一貫性を管理するのはあくまで開発者の手に委ねられているのだ。

 そこで本稿では、検証コントロールにおいて、メッセージ・リソースを一元的に管理する仕組みを紹介する。

 本稿のサンプルを利用すれば、本来はエラー・メッセージを設定するErrorMessage属性に、メッセージそのものではなくエラー・メッセージに最低限必要な文言部分を指定するだけでし、後は検証の種類に応じて適切なメッセージを動的に生成できるようになる。

 それではさっそく、具体的なコードを見ていくことにしよう。

<%@ Page ContentType="text/html" Language="C#" %>
<script runat="Server">
void Page_Load(Object sender, EventArgs e){

  // ページ内の検証コントロールを順番に走査。
  // もともと設定されていたErrorMessage属性(項目名)や
  // そのほかのパラメータから、
  // それぞれの検証型に応じたメッセージを動的に生成する
  if (!Page.IsPostBack) {
    foreach (BaseValidator valid in Page.Validators) {

      switch (valid.GetType().Name) {

        case "RequiredFieldValidator" :
          valid.ErrorMessage = String.Format(
            "{0}は必須です。", valid.ErrorMessage);
          break;

        case "CompareValidator" :
          // CompareValidatorでは、項目名は「項目1,項目2」の
          // 形式で指定されているものとする。
          // 項目名をカンマで分割し、配列aryMsgにセット
          String[] aryMsg = valid.ErrorMessage.Split(',');

          // Operator属性の値によって、メッセージを分岐
          switch (((CompareValidator)valid).Operator) {

            case ValidationCompareOperator.Equal :
              valid.ErrorMessage = String.Format(
                "{0}は{1}と等しい値でなければなりません。",
                aryMsg[0], aryMsg[1]);
              break;

            case ValidationCompareOperator.NotEqual :
              valid.ErrorMessage = String.Format(
                "{0}は{1}と異なる値でなければなりません。",
                aryMsg[0], aryMsg[1]);
              break;

            case ValidationCompareOperator.GreaterThan :
              valid.ErrorMessage = String.Format(
                "{0}は{1}より大きい値でなければなりません。",
                "c", "x");
              break;

            case ValidationCompareOperator.GreaterThanEqual :
              valid.ErrorMessage = String.Format(
                "{0}は{1}以上でなければなりません。",
                aryMsg[0], aryMsg[1]);
              break;

            case ValidationCompareOperator.LessThan :
              valid.ErrorMessage = String.Format(
                "{0}は{1}より小さい値でなければなりません。",
                aryMsg[0], aryMsg[1]);
              break;

            case ValidationCompareOperator.LessThanEqual :
              valid.ErrorMessage = String.Format(
                "{0}は{1}以下でなければなりません。",
                aryMsg[0], aryMsg[1]);
              break;

            case ValidationCompareOperator.DataTypeCheck :
              valid.ErrorMessage = String.Format(
                "{0}は正しい型でありません。",
                aryMsg[0]);
              break;
          }
          break;

        case "RangeValidator" :
          valid.ErrorMessage = String.Format(
            "{0}は{1}〜{2}の間でなければなりません。",
            valid.ErrorMessage,
            ((RangeValidator)valid).MinimumValue,
            ((RangeValidator)valid).MaximumValue);
          break;

        case "RegularExpressionValidator" :
          valid.ErrorMessage = String.Format(
            "{0}は正しい形式ではありません。",
            valid.ErrorMessage);
          break;
      }
    }
  }
}
</script>
<html>
<head>
<title>エラー・メッセージの一元管理</title>
</head>
<body>
<h1>エラー・メッセージの一元管理</h1>
<form runat="server">

  名前:<asp:TextBox id="txtNam" runat="Server" Size="20" />

  <asp:RequiredFieldValidator id="reqNam" runat="Server"
    ControlToValidate="txtNam" ErrorMessage="名前" /><br />

  年齢:<asp:TextBox id="txtOld" runat="Server" Size="3" />歳

  <asp:RangeValidator id="rngOld" runat="Server"
    ControlToValidate="txtOld"
    MinimumValue="0" MaximumValue="150"
    Type="Integer" ErrorMessage="年齢" />

  <asp:CompareValidator id="cmpOld" runat="Server"
    ControlToValidate="txtOld"
    Type="Integer" Operator="DataTypeCheck"
    ErrorMessage="年齢" /><br />

  E-Mail:<asp:TextBox id="txtMail" runat="Server" Size="40" />

  <asp:RegularExpressionValidator id="regMail" runat="Server"
    ControlToValidate="txtMail"
    ErrorMessage="E-Mail"
    ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" /><br />

  <asp:Button id="btnSend" runat="Server" Text="送信" />

</form>
</body>
</html>
検証メッセージを動的に生成するためのWebフォーム(C#版:ValidateManage_cs.aspx)
 
<%@ Page ContentType="text/html" Language="VB" %>
<script runat="Server">
Sub Page_Load(sender As Object, e As EventArgs)
  ' ページ内の検証コントロールを順番に走査。
  ' もともと設定されていたErrorMessage属性(項目名)や
  ' そのほかのパラメータから、
  ' それぞれの検証型に応じたメッセージを動的に生成する
  If Not Page.IsPostBack Then
    For Each valid As BaseValidator In Page.Validators
      Select Case valid.GetType().Name
        Case "RequiredFieldValidator"
          valid.ErrorMessage= _
            String.Format("{0}は必須です。",valid.ErrorMessage)
        Case "CompareValidator"
          ' CompareValidatorでは、項目名は「項目1,項目2」の形式で
          ' 指定されているものとする。
          ' 項目名をカンマで分割し、配列aryMsgにセット
          Dim aryMsg As String()=valid.ErrorMessage.Split(New Char(){","})
          Dim objCmp As CompareValidator=CType(valid,CompareValidator)
          Select Case objCmp.Operator
            Case ValidationCompareOperator.Equal
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}と等しい値でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.NotEqual
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}と異なる値でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.GreaterThan
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}より大きい値でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.GreaterThanEqual
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}以上でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.LessThan
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}より小さい値でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.LessThanEqual
              objCmp.ErrorMessage=String.Format( _
                "{0}は{1}以下でなければなりません。", _
                aryMsg(0),aryMsg(1))
            Case ValidationCompareOperator.DataTypeCheck
              objCmp.ErrorMessage=String.Format( _
                "{0}は正しい型でありません。",aryMsg(0))
          End Select
        Case "RangeValidator"
          Dim objRng As RangeValidator=CType(valid,RangeValidator)
          valid.ErrorMessage=String.Format( _
            "{0}は{1}〜{2}の間でなければなりません。", _
            objRng.ErrorMessage, _
            objRng.MinimumValue, _
            objRng.MaximumValue)
        Case "RegularExpressionValidator"
          valid.ErrorMessage=String.Format( _
            "{0}は正しい形式ではありません。", _
            valid.ErrorMessage)
      End Select
    Next
  End If
End Sub
</script>
<html>
<head>
<title>エラーメッセージの一元管理</title>
</head>
<body>
<h1>エラーメッセージの一元管理</h1>
<form runat="server">
名前:<asp:TextBox id="txtNam" runat="Server" Size="20" />
<asp:RequiredFieldValidator id="reqNam" runat="Server"
  ControlToValidate="txtNam" ErrorMessage="名前" /><br />
年齢:<asp:TextBox id="txtOld" runat="Server" Size="3" />歳
<asp:RangeValidator id="rngOld" runat="Server"
  ControlToValidate="txtOld" MinimumValue="0" MaximumValue="150"
  Type="Integer" ErrorMessage="年齢" />
<asp:CompareValidator id="cmpOld" runat="Server"
  ControlToValidate="txtOld" Type="Integer" Operator="DataTypeCheck"
  ErrorMessage="年齢" /><br />
E-Mail:<asp:TextBox id="txtMail" runat="Server" Size="40" />
<asp:RegularExpressionValidator id="regMail" runat="Server"
  ControlToValidate="txtMail" ErrorMessage="E-Mail"
  ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" /><br />
<asp:Button id="btnSend" runat="Server" Text="送信" />
</form>
</body>
</html>
検証メッセージを動的に生成するためのWebフォーム(VB.NET版:ValidateManage_vb.aspx)

 検証コントロールの型によって処理を分岐しているため、必要以上にコードが複雑に見えるかもしれないが、行っていることは非常にシンプルだ。検証コントロールの型に従って、元のErrorMessage属性(項目名)をあらかじめ定義しておいたメッセージ・フォーマットに従って整形しているだけにすぎない。

 以上が理解できたら、さっそくサンプルを実行してみよう。ErrorMessage属性には項目名しか定義していないのに、画面上には正しく整形されたエラー・メッセージが出力されるはずだ。

サンプル・プログラム(ValidateManage_cs.aspx/ValidateManage_vb.aspx)の実行結果

 なお、このような処理は(当然のことながら)個々のページ単位に実装しても意味がないものだ。仕組み自体はPage派生クラスとして一元的に管理しておき、個々の.aspxファイルはこのPage派生クラスを継承して実装するのが好ましい。Page派生クラスを利用する方法については、「TIPS:[ASP.NET]アプリケーション共通の処理をPage派生クラスで実装するには?」で紹介している。End of Article

カテゴリ:Webフォーム 処理対象:検証
使用ライブラリ:RequiredFieldValidatorコントロール(System.Web.UI.WebControls名前空間)
使用ライブラリ:CompareValidatorコントロール(System.Web.UI.WebControls名前空間)
使用ライブラリ:RangeValidatorコントロール(System.Web.UI.WebControls名前空間)
使用ライブラリ:RegularExpressionValidatorコントロール(System.Web.UI.WebControls名前空間)
関連TIPS:アプリケーション共通の処理をPage派生クラスで実装するには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]複数のボタンを持つフォームで検証コントロールを利用するには?
[ASP.NET]CustomValidatorコントロールでクライアント検証を有効にするには?
[ASP.NET]アプリケーション共通の処理をPage派生クラスで実装するには?
[ASP.NET]CustomValidatorコントロールでマスタ重複チェックを実装するには?
[ASP.NET]検証コントロールで条件付きの検証処理を行うには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間