ASP.NET UpdatePanel コントロールのエラー処理のカスタマイズ
更新 : 2007 年 11 月
UpdatePanel コントロールで部分ページ更新の処理中にエラーが発生した場合、既定ではブラウザのメッセージ ボックスにエラー メッセージが表示されます。このチュートリアルでは、ユーザーに対するエラーの表示方法をカスタマイズする方法と、エラー メッセージをカスタマイズする方法を説明します。
前提条件
この手順を各自の開発環境で実行するには、以下が必要です。
Microsoft Visual Studio 2005 または Microsoft Visual Web Developer Express Edition。
AJAX 対応の ASP.NET Web サイト。
サーバー コードでのエラー処理のカスタマイズ
まず始めに、ページ内でサーバー コードを使用してエラー処理をカスタマイズします。
サーバー コードでエラー処理をカスタマイズするには
新しいページを作成し、デザイン ビューに切り替えます。
ツールボックスの [AJAX Extensions] タブで、ScriptManager コントロールと UpdatePanel コントロールをダブルクリックしてページに追加します。
UpdatePanel コントロール内に次のコントロールを追加します。
2 つの TextBox コントロール
Label コントロール。
Button コントロール。Text プロパティを Calculate に設定します。
UpdatePanel 内になんらかのテキスト。
Calculate をダブルクリックし、イベント ハンドラに次のコードを追加します。
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Try Dim a As Int32 a = Int32.Parse(TextBox1.Text) Dim b As Int32 b = Int32.Parse(TextBox2.Text) Dim res As Int32 = a / b Label1.Text = res.ToString() Catch ex As Exception If (TextBox1.Text.Length > 0 AndAlso TextBox2.Text.Length > 0) Then ex.Data("ExtraInfo") = " You can't divide " & _ TextBox1.Text & " by " & TextBox2.Text & "." End If Throw ex End Try End Sub
protected void Button1_Click(object sender, EventArgs e) { try { int a = Int32.Parse(TextBox1.Text); int b = Int32.Parse(TextBox2.Text); int res = a / b; Label1.Text = res.ToString(); } catch (Exception ex) { if (TextBox1.Text.Length > 0 && TextBox2.Text.Length > 0) { ex.Data["ExtraInfo"] = " You can't divide " + TextBox1.Text + " by " + TextBox2.Text + "."; } throw ex; } }
このコードには try-catch ステートメントが含まれています。try ブロックでは、テキスト ボックスに入力された値に対して除算が実行されます。この演算が失敗すると、catch ブロックのコードによって ExtraInfo 内の追加の文字列情報が例外に追加され、その例外が処理されることなく再度スローされます。
デザイン ビューに切り替え、ScriptManager コントロールを選択します。
[プロパティ] ウィンドウのツール バーの [イベント] をクリックし、[AsyncPostBackError] ボックスをダブルクリックして、このイベントのハンドラを作成します。
AsyncPostBackError イベント ハンドラに次のコードを追加します。
Protected Sub ScriptManager1_AsyncPostBackError(ByVal sender As Object, ByVal e As System.Web.UI.AsyncPostBackErrorEventArgs) If (e.Exception.Data("ExtraInfo") <> Nothing) Then ScriptManager1.AsyncPostBackErrorMessage = _ e.Exception.Message & _ e.Exception.Data("ExtraInfo").ToString() Else ScriptManager1.AsyncPostBackErrorMessage = _ "An unspecified error occurred." End If End Sub
protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { if (e.Exception.Data["ExtraInfo"] != null) { ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message + e.Exception.Data["ExtraInfo"].ToString(); } else { ScriptManager1.AsyncPostBackErrorMessage = "An unspecified error occurred."; } }
このコードは、例外に対して ExtraInfo データ項目が定義されているかどうか確認します。定義されている場合は、AsyncPostBackErrorMessage プロパティがその文字列値に設定されます。定義されていない場合は、既定のエラー メッセージが作成されます。
変更内容を保存し、Ctrl キーを押しながら F5 キーを押して、ブラウザでページを表示します。
各テキスト ボックスに 0 を超える数値を追加し、Calculate をクリックして、ポストバックが正常に行われるかどうか確認します。
2 番目のテキスト ボックスの値を 0 に変更し、Calculate をクリックしてエラーを発生させます。
ブラウザに、サーバー コードで設定したメッセージを含むメッセージ ボックスが表示されます。
メモ : メッセージ ボックスのスタイルは使用しているブラウザによって異なりますが、メッセージの内容はどのブラウザでも同じです。
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Try Dim a As Int32 a = Int32.Parse(TextBox1.Text) Dim b As Int32 b = Int32.Parse(TextBox2.Text) Dim res As Int32 = a / b Label1.Text = res.ToString() Catch ex As Exception If (TextBox1.Text.Length > 0 AndAlso TextBox2.Text.Length > 0) Then ex.Data("ExtraInfo") = " You can't divide " & _ TextBox1.Text & " by " & TextBox2.Text & "." End If Throw ex End Try End Sub Protected Sub ScriptManager1_AsyncPostBackError(ByVal sender As Object, ByVal e As System.Web.UI.AsyncPostBackErrorEventArgs) If (e.Exception.Data("ExtraInfo") <> Nothing) Then ScriptManager1.AsyncPostBackErrorMessage = _ e.Exception.Message & _ e.Exception.Data("ExtraInfo").ToString() Else ScriptManager1.AsyncPostBackErrorMessage = _ "An unspecified error occurred." End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Partial-Page Update Error Handling Example</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:TextBox ID="TextBox1" runat="server" Width="39px"></asp:TextBox> / <asp:TextBox ID="TextBox2" runat="server" Width="39px"></asp:TextBox> = <asp:Label ID="Label1" runat="server"></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="calculate" /> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
<%@ 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) { try { int a = Int32.Parse(TextBox1.Text); int b = Int32.Parse(TextBox2.Text); int res = a / b; Label1.Text = res.ToString(); } catch (Exception ex) { if (TextBox1.Text.Length > 0 && TextBox2.Text.Length > 0) { ex.Data["ExtraInfo"] = " You can't divide " + TextBox1.Text + " by " + TextBox2.Text + "."; } throw ex; } } protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { if (e.Exception.Data["ExtraInfo"] != null) { ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message + e.Exception.Data["ExtraInfo"].ToString(); } else { ScriptManager1.AsyncPostBackErrorMessage = "An unspecified error occurred."; } } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Partial-Page Update Error Handling Example</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:TextBox ID="TextBox1" runat="server" Width="39px"></asp:TextBox> / <asp:TextBox ID="TextBox2" runat="server" Width="39px"></asp:TextBox> = <asp:Label ID="Label1" runat="server"></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="calculate" /> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
クライアント スクリプトを使用したエラー処理のカスタマイズ
前の手順では、ScriptManager コントロールのプロパティを設定することによって、部分ページ レンダリングの処理中に発生するエラーをカスタマイズする方法を示しました。次の手順では、クライアントの PageRequestManager クラスを使用して、ブラウザのメッセージ ボックスではなく <div> 要素にエラー メッセージを表示することによってカスタマイズを行う方法を示します。
クライアント スクリプトを使用してエラー処理をカスタマイズするには
前に作成したページで、ソース ビューに切り替えます。
ページに次のマークアップを追加します。
<div id="AlertDiv"> <div id="AlertMessage"> </div> <br /> <div id="AlertButtons"> <input id="OKButton" type="button" value="OK" runat="server" onclick="ClearErrorState()" /> </div> </div> </div>
<div id="AlertDiv"> <div id="AlertMessage"> </div> <br /> <div id="AlertButtons"> <input id="OKButton" type="button" value="OK" runat="server" onclick="ClearErrorState()" /> </div> </div> </div>
このマークアップには、部分ページ レンダリングのエラー メッセージを表示するために使用できる要素が含まれています。ここでは、AlertDiv という名前の <div> 要素が定義されており、この要素には別の <div> 要素が 2 つ含まれています。入れ子になった <div> 要素のうちの 1 つには、ユーザーが <div> 要素を非表示にできる <input> コントロールが含まれています。
<head> 要素に次のスタイル マークアップを追加します。
<style type="text/css"> #UpdatePanel1 { width: 200px; height: 50px; border: solid 1px gray; } #AlertDiv{ left: 40%; top: 40%; position: absolute; width: 200px; padding: 12px; border: #000000 1px solid; background-color: white; text-align: left; visibility: hidden; z-index: 99; } #AlertButtons{ position: absolute; right: 5%; bottom: 5%; } </style>
<style type="text/css"> #UpdatePanel1 { width: 200px; height: 50px; border: solid 1px gray; } #AlertDiv{ left: 40%; top: 40%; position: absolute; width: 200px; padding: 12px; border: #000000 1px solid; background-color: white; text-align: left; visibility: hidden; z-index: 99; } #AlertButtons{ position: absolute; right: 5%; bottom: 5%; } </style>
このスタイルにより、エラー情報が他のページ コンテンツよりも視覚的に目立つように表示されます。
デザイン ビューに切り替えて、ページが次のようになっているか確認します。
[プロパティ] ウィンドウの最上部にあるドロップダウン リストの DOCUMENT 要素 (ページ上の <body> 要素を表します) をクリックし、Id プロパティを bodytag に設定します。
ソース ビューに切り替えます。
次の <script> ブロックを <asp:ScriptManager> 要素の後の任意の場所に追加します。
<script type="text/javascript" language="javascript"> var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; var bodyTag = 'bodytag'; Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler); function ToggleAlertDiv(visString) { if (visString == 'hidden') { $get(bodyTag).style.backgroundColor = 'white'; } else { $get(bodyTag).style.backgroundColor = 'gray'; } var adiv = $get(divElem); adiv.style.visibility = visString; } function ClearErrorState() { $get(messageElem).innerHTML = ''; ToggleAlertDiv('hidden'); } function EndRequestHandler(sender, args) { if (args.get_error() != undefined) { var errorMessage; if (args.get_response().get_statusCode() == '200') { errorMessage = args.get_error().message; } else { // Error occurred somewhere other than the server page. errorMessage = 'An unspecified error occurred. '; } args.set_errorHandled(true); ToggleAlertDiv('visible'); $get(messageElem).innerHTML = errorMessage; } } </script>
<script type="text/javascript" language="javascript"> var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; var bodyTag = 'bodytag'; Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler); function ToggleAlertDiv(visString) { if (visString == 'hidden') { $get(bodyTag).style.backgroundColor = 'white'; } else { $get(bodyTag).style.backgroundColor = 'gray'; } var adiv = $get(divElem); adiv.style.visibility = visString; } function ClearErrorState() { $get(messageElem).innerHTML = ''; ToggleAlertDiv('hidden'); } function EndRequestHandler(sender, args) { if (args.get_error() != undefined) { var errorMessage; if (args.get_response().get_statusCode() == '200') { errorMessage = args.get_error().message; } else { // Error occurred somewhere other than the server page. errorMessage = 'An unspecified error occurred. '; } args.set_errorHandled(true); ToggleAlertDiv('visible'); $get(messageElem).innerHTML = errorMessage; } } </script>
このスクリプトにより、以下の処理が実行されます。
PageRequestManager クラスの endRequest イベントのハンドラを定義します。このハンドラでは、エラーが発生すると AlertDiv <div> 要素が表示されます。
ToggleAlertDiv 関数を定義します。この関数は、AlertDiv 要素の表示と非表示を切り替え、エラーの状況に応じてページの色を変更します。
エラー メッセージ UI を非表示にする ClearErrorState 関数を定義します。
変更内容を保存し、Ctrl キーを押しながら F5 キーを押して、ブラウザでページを表示します。
各テキスト ボックスに 0 を超える数値を追加し、Calculate をクリックして、ポストバックが正常に行われるかどうか確認します。
2 番目のテキスト ボックスの値を 0 に変更し、Calculate をクリックして、エラーを発生させます。
ブラウザのメッセージ ボックスではなく、カスタムの AlertDiv 要素が表示されます。エラー発生時の例を次の図に示します。
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Try Dim a As Int32 a = Int32.Parse(TextBox1.Text) Dim b As Int32 b = Int32.Parse(TextBox2.Text) Dim res As Int32 = a / b Label1.Text = res.ToString() Catch ex As Exception If (TextBox1.Text.Length > 0 AndAlso TextBox2.Text.Length > 0) Then ex.Data("ExtraInfo") = " You can't divide " & _ TextBox1.Text & " by " & TextBox2.Text & "." End If Throw ex End Try End Sub Protected Sub ScriptManager1_AsyncPostBackError(ByVal sender As Object, ByVal e As System.Web.UI.AsyncPostBackErrorEventArgs) If (e.Exception.Data("ExtraInfo") <> Nothing) Then ScriptManager1.AsyncPostBackErrorMessage = _ e.Exception.Message & _ e.Exception.Data("ExtraInfo").ToString() Else ScriptManager1.AsyncPostBackErrorMessage = _ "An unspecified error occurred." End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>UpdatePanel Error Handling Example</title> <style type="text/css"> #UpdatePanel1 { width: 200px; height: 50px; border: solid 1px gray; } #AlertDiv{ left: 40%; top: 40%; position: absolute; width: 200px; padding: 12px; border: #000000 1px solid; background-color: white; text-align: left; visibility: hidden; z-index: 99; } #AlertButtons{ position: absolute; right: 5%; bottom: 5%; } </style> </head> <body id="bodytag"> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager> <script type="text/javascript" language="javascript"> var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; var bodyTag = 'bodytag'; Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler); function ToggleAlertDiv(visString) { if (visString == 'hidden') { $get(bodyTag).style.backgroundColor = 'white'; } else { $get(bodyTag).style.backgroundColor = 'gray'; } var adiv = $get(divElem); adiv.style.visibility = visString; } function ClearErrorState() { $get(messageElem).innerHTML = ''; ToggleAlertDiv('hidden'); } function EndRequestHandler(sender, args) { if (args.get_error() != undefined) { var errorMessage; if (args.get_response().get_statusCode() == '200') { errorMessage = args.get_error().message; } else { // Error occurred somewhere other than the server page. errorMessage = 'An unspecified error occurred. '; } args.set_errorHandled(true); ToggleAlertDiv('visible'); $get(messageElem).innerHTML = errorMessage; } } </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:TextBox ID="TextBox1" runat="server" Width="39px"></asp:TextBox> / <asp:TextBox ID="TextBox2" runat="server" Width="39px"></asp:TextBox> = <asp:Label ID="Label1" runat="server"></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="calculate" /> </ContentTemplate> </asp:UpdatePanel> <div id="AlertDiv"> <div id="AlertMessage"> </div> <br /> <div id="AlertButtons"> <input id="OKButton" type="button" value="OK" runat="server" onclick="ClearErrorState()" /> </div> </div> </div> </form> </body> </html>
<%@ 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) { try { int a = Int32.Parse(TextBox1.Text); int b = Int32.Parse(TextBox2.Text); int res = a / b; Label1.Text = res.ToString(); } catch (Exception ex) { if (TextBox1.Text.Length > 0 && TextBox2.Text.Length > 0) { ex.Data["ExtraInfo"] = " You can't divide " + TextBox1.Text + " by " + TextBox2.Text + "."; } throw ex; } } protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { if (e.Exception.Data["ExtraInfo"] != null) { ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message + e.Exception.Data["ExtraInfo"].ToString(); } else { ScriptManager1.AsyncPostBackErrorMessage = "An unspecified error occurred."; } } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>UpdatePanel Error Handling Example</title> <style type="text/css"> #UpdatePanel1 { width: 200px; height: 50px; border: solid 1px gray; } #AlertDiv{ left: 40%; top: 40%; position: absolute; width: 200px; padding: 12px; border: #000000 1px solid; background-color: white; text-align: left; visibility: hidden; z-index: 99; } #AlertButtons{ position: absolute; right: 5%; bottom: 5%; } </style> </head> <body id="bodytag"> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager> <script type="text/javascript" language="javascript"> var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; var bodyTag = 'bodytag'; Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler); function ToggleAlertDiv(visString) { if (visString == 'hidden') { $get(bodyTag).style.backgroundColor = 'white'; } else { $get(bodyTag).style.backgroundColor = 'gray'; } var adiv = $get(divElem); adiv.style.visibility = visString; } function ClearErrorState() { $get(messageElem).innerHTML = ''; ToggleAlertDiv('hidden'); } function EndRequestHandler(sender, args) { if (args.get_error() != undefined) { var errorMessage; if (args.get_response().get_statusCode() == '200') { errorMessage = args.get_error().message; } else { // Error occurred somewhere other than the server page. errorMessage = 'An unspecified error occurred. '; } args.set_errorHandled(true); ToggleAlertDiv('visible'); $get(messageElem).innerHTML = errorMessage; } } </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:TextBox ID="TextBox1" runat="server" Width="39px"></asp:TextBox> / <asp:TextBox ID="TextBox2" runat="server" Width="39px"></asp:TextBox> = <asp:Label ID="Label1" runat="server"></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="calculate" /> </ContentTemplate> </asp:UpdatePanel> <div id="AlertDiv"> <div id="AlertMessage"> </div> <br /> <div id="AlertButtons"> <input id="OKButton" type="button" value="OK" runat="server" onclick="ClearErrorState()" /> </div> </div> </div> </form> </body> </html>
レビュー
このチュートリアルでは、部分ページ レンダリング中のエラー処理を拡張する方法を説明しました。サーバー コードでエラー処理をカスタマイズするには、ScriptManager コントロールの AsyncPostBackErrorMessage プロパティを設定し、AsyncPostBackError イベントを処理します。クライアント コードでエラー処理をカスタマイズするには、PageRequestManager クラスの endRequest イベントを処理します。