4.エラー処理

初めに

 ここで議論するのは、次の二つです。

  • どのようなエラーに対処するか
  • エラーをどうやってユーザに知らせるか
    この方法は、 Web Form と MVC とでは異なります

 まず、第一項目です。エラーの発生元には、以下の場合があります。

  • アプリケーションの動作以前のエラー
    IIS が遭遇したエラーなどですが、ここではこの種のエラーは議論しません
    IIS 用のエラーページを用意するなどを検討してください
  • アプリケーションの動作中のエラー
    このエラーには、エラー発生元により、さらに以下の2つに分類されます
    • サーバーで発生したエラー
      例えば、データベース検索時に発生したエラーなどが該当します
    • ブラウザで発生したエラー
      例えば、数字だけが有効な欄に文字を入力した場合などが該当します

 サーバーで発生したエラーは、サーバー側で対処するしかありません。この場合の残る問題は、そのエラーをどうやってユーザに知らせるかとなります。

 一方、ブラウザで発生したエラーは次の3通りの対処方法があります。

  • ブラウザで対処する
    ブラウザ上でエラーを検査する方法です
  • サーバーで対処する
    エラーの検査なしにサーバーにデータを送信し、サーバーでエラーを検査する方法です
  • ブラウザとサーバーで対処する
    ブラウザでエラーを検査し、さらに送信された先のサーバーで2重に検査する方法です

 このプログラムでは、上記の一番目の方法を採用します。ブラウザ上で jQuery を使用して検査しますので、サーバーにデータを送信して、その結果を受信するのと比較して、応答時間が短くなります。 また、三番目のブラウザとサーバーでの2重チェックが必要なほど、重要度が高いデータを扱っているわけでもないからです。こうした方針は、そのプロジェクト毎に異なるでしょう。
 金銭や個人情報を扱うようなアプリケーションの場合は、慎重な検討が必要でしょう。

 ここまでの結論を踏まえて、第二項目の「エラーをどうやってユーザに知らせるか」を議論すると、問題は次の2つになります。

  • サーバーで発生したエラーをどうやってユーザに知らせるか
  • ブラウザで発生したエラーをどうやってユーザに知らせるか
    ブラウザで発生したエラーは、ブラウザ上で検査することにしました
    そのため、ブラウザで発生したエラーは Web Form と MVC に係わらず対処方法は同じになります

Web Form の場合

 議論しなければいけないエラー処理は、次の2つにまとまりました。

  • サーバーで発生したエラーをどうやってユーザに知らせるか
  • ブラウザで発生したエラーをどうやってユーザに知らせるか

 どのようなエラーであっても、ユーザにエラーの発生を伝えるためには、ブラウザ上にエラーを表示するしかありません。 そこで、エラーの表示はすべて次のようにします。

            		
  エラー内容を、画面のタイトルの直下に、薄い赤を背景に赤文字で表示する
            		
            		

サーバーで発生したエラー

 次のような、エラーを表示する専用のタグを用意します。このタグは、サーバーで発生したエラーだけでなく、ブラウザで発生したエラーの表示にも使用します。
 サーバーで発生したエラーは、 id 属性値 Mrror-Message を持つこのタグに埋め込みます。一方、ブラウザで発生したエラーは jQuery を使用して、このタグにエラー内容を埋め込みます。

					
1    <div id="Error-Message" class="bg-danger text-danger">
2    </div>
					
					

 ここで、id 属性の値「 Error-Message 」は固定です。 bg-danger と text-danger は bootstrap で定義された CSS の値で、 それぞれ背景色と文字色を指定しています。

 このタグにサーバーでエラー内容を表示するために、以下のメソッドを利用します。

					
1    protected void DisplayErrors(string txt, bool flag = true, string selector = "#Error-Message")
2    {
3        String[] lines;
4        String[] limit = { "。" };

5        if (flag)
6            lines = txt.Split(limit, StringSplitOptions.None);
7        else
8        {
9            lines = new String[1];
10           lines[0] = txt;
11       }

12       String text = lines[0].Replace("\"", "\\\"");
13       text = text.Replace("\'", "\\\'");

14       ClientScript.RegisterClientScriptBlock(this.GetType(),
15           "",
16           String.Format("<script type='text/javascript'>" +
17               "$('{0}').append('<p>{1}</p>');" +
18               "</script>", selector, text));
19    }
    
    				

 1行目:引数 txt はエラーメッセージの本文、 flag はメッセージ中に句点があるとき1行目だけを有効とするかどうか、selector は表示用タグの id 属性値で上記の説明のように Error-Message 固定です
 3~11行目:メッセージ中に句点がある場合の処理。句点も含めて全体を表示するか、句点の前だけを表示するかを切り分けています
 12~13行目:メッセージ中にダブルクウォートやシングルクウォートがある場合の特殊処理
 14~18行目:エラー表示エリアにメッセージを表示するための jQuery プログラムの埋め込み

 上記メッセージの中心部分は、14~18行目になります。

ブラウザで発生したエラー

 次のような、エラーを表示する専用のタグを <body> タグの後のタイトルの直後に用意します。 このタグは、サーバーで発生したエラーの表示にも使用します。

					
1    <div id="Error-Message" class="bg-danger text-danger">
2    </div>
					
					

 例えば、追加ボタン(AddButton)をクリックした場合のエラー検査は次のようにします。

					
1   <script>
2       $(function () {
3           $("#AddButton").click(function () {
4               $("#Error-Message").text("");

5               if ($("#InputId").isNull()) {
6                   $("#Error-Message").append("<p>IDは必須項目です。</p>");
7               }

8               return $("#Error-Message").text().length == 0;
9           });
10      });
11   </script>

				

 5行目:未入力かどうかの検査。 isNull() はそのための jQuery の自作関数。 jQuery の自作関数に関しては、 こちら を参照してください
 6行目:エラーの場合に、エラー表示エリアにメッセージを追加
 8行目: true を返すと、サーバーにサブミットし、 false を返すとサブミットしないので、エラーメッセージが空文字列かどうかを検査する

MVC の場合

 Web Form と同じく、議論しなければいけないエラー処理は、次の2つにまとまりました。

  • サーバーで発生したエラーをどうやってユーザに知らせるか
  • ブラウザで発生したエラーをどうやってユーザに知らせるか

 どのようなエラーであっても、ユーザにエラーの発生を伝えるためには、ブラウザ上にエラーを表示するしかありません。 そこで、エラーの表示はすべて次のようにします。これも、 Web Form と同じ結論です。

       				
  エラー内容を、画面のタイトルの直下に、薄い赤を背景に赤文字で表示する
       				
           			

サーバーで発生したエラー

 次のような、エラーを表示する専用のタグを <body> タグの後の、タイトルの直後に用意します。このタグは、ブラウザで発生したエラーの表示にも使用します。

					
    @Html.ValidationSummary(false, "", new { id = "error-Message", @class = "text-danger bg-danger" })						
					
					

 これは、 MVC の html 記述用言語である Razor で用意されているエラー用タグの記述になります。

 このタグにエラーメッセージを追加するには、Controller クラスのメソッドから以下のようにします。

					
   ModelState.AddModelError(エラー本文のキーとなる文字列, エラーの本文);
					
					

 ここで、 ModelState は標準の Controller クラスで定義されているオブジェクトです。そのオブジェクトに AddModelError() メソッドで エラーを追加すると、上記の @Html.ValidationSummary に表示されます。

ブラウザで発生したエラー

 ブラウザで発生したエラーも、上記の @Html.ValidationSummary に表示することにしました。そこで、 @Html.ValidationSummary がどのように html に変換されるかを見てみます。ただし、何もエラーが発生していない状態です。

					
    <div class="validation-summary-valid text-danger bg-danger" data-valmsg-summary="true" id="error-Message">
        <ul>
            <li style="display:none"></li>
        </ul>
    </div>
					

 <ul> タグに変換されていることが分かります。とすれば、 jQuery の関数は簡単です。ただし、このやりかたは @Html.ValidationSummary の実装に依存しています。 Web MVC の実装に依存しないようにするには、サーバーのエラーを表示するためのタグと、ブラウザのエラーを表示するためのタグを分ければよいです。2つのエラー表示用タグを上下に並べて配置すれば 表示上の違和感はないと思います。
 エラー処理をどうするのかは、プロジェクト毎に判断してください。

					
1   <script>
2       $(function () {
3           $("#createButton").click(function () {
4               $("#error-Message > ul").text("");

5               if ($("#inputId").isNull()) {
6                   $("#error-Message > ul").append("<li>IDは必須項目です。</li>");
7               }

8               return $("#error-Message > ul").text().length == 0;
9           });
10      });
11  </script>
					
					

 <li> タグで整形したエラーメッセージを追加するだけです。

 大分類を操作する画面でエラーが発生した場合の例を示します。(画像をクリックすると、拡大表示します)
必須項目である ID と名前が未入力の状態で、「追加」ボタンをクリックした時の画面になります。

画面1