japan.internet.com The Internet & IT Network


RSSニュース検索
カテゴリ
> トップページ
> Webビジネス
> Eコマース
> Webファイナンス
> Webマーケティング
> パブリック
> Webテクノロジー
> 携帯・ワイヤレス
> Linux Today
> Linux Tutorial
> J.I.C.ブログ
キャリア
> 転職ならen
> 派遣ならen
> アルバイトならen
> IT求人情報
ヘッドライン
> 今日のヘッドライン
> 週間ヘッドライン
Special Link
> フォトコミュニティ
> ストックフォト
> クリップアート
> イラスト
> フェリカ
> Web2.0
> 写真
イベント&セミナー
> イベントカレンダー
> 書評「IT の耳」
> 出張・接待検索
> ニュースガジェット 注目
無料ニュースメール
> 新規登録
> 変更・解除
> オプトインメールの登録・変更・解除
インフォメーション
> パートナーサイト
転職ならエン
就職ならen
求人ならen
履歴書ならen
アルバイトならエン
CRM/SFAならオラクル
> 会社概要地図
> グループ会社
株式会社アエリア
(株)サンゼロミニッツ
株式会社エアネット
> お問い合わせ
> 広告掲載について
> リンクについて
> 著作権について
> その他お問い合わせ
> 利用規約
> 個人情報保護方針
コラム コラム一覧へ戻る

japan.internet.com 編集部 japan.internet.com 編集部
米国 Jupitermedia が運営する、ASP と ASP ネットワーク情報に関するサイト。

 メール  著者にメールする
 ホーム  http://www.4guysfromrolla.com/

最新コラム

処理の例外への適切な対処法2:例外の詳細を開発者に通知する

著者: Scott Mitchell プリンター用 記事を転送
2007年1月9日 10:00 付の記事
■海外internet.com発の記事

はじめに

 ASP.NETアプリケーションで未処理の例外が発生すると、既定では訪問者に「ランタイムエラー」ページまたは例外の詳細ページが表示されます(どちらのページが表示されるかは、Webサイトの設定および訪問者がローカルホストから表示しているかどうかによります)。理想的なことを言えば、このような難解なエラーページは開発者だけに表示され、通常のユーザーにはユーザーフレンドリなカスタムエラーページが表示されるべきでしょう。前回の記事「未処理の例外への適切な対処法」では、未処理の例外への応答としてユーザーフレンドリなカスタムWebエラーページを表示するASP.NET Webアプリケーションの設定方法を紹介しました。

 ただし、前回の記事で紹介した方法では、未処理の例外が発生したときに内部的にResponse.Redirect()を使ってユーザーをカスタムエラーページにリダイレクトしています。ユーザーをリダイレクトすると、要求のコンテキストは失われます(リダイレクトによってブラウザがエラーページに新しい要求を送るからです)。そのため、ユーザーフレンドリなカスタムエラーページでは、発生したエラーについての情報を得ることができません。もっと詳しいエラーメッセージを表示するためには、こうした情報が必要になることもあります。

 未処理の例外がASP.NETランタイムに通知されると、アプリケーションレベルのErrorイベントがトリガされます。このイベントのためのイベントハンドラを作成することで、エラーの詳細にアクセスしたり、エラーを記録したり、開発者に通知したり、Server.Transfer()を使ってユーザーをカスタムエラーページに送ったりすることができます(コンテキストを維持して、カスタムエラーページから未処理の例外の詳細にアクセスできるようにします)。

 この記事では、Errorイベントのイベントハンドラを作成する方法を説明し、エラーの詳細を記録するためのフリーなオープンソースコンポーネントを紹介します。

Errorイベントを調べる

 HttpApplicationクラスは、すべてのASP.NET Webアプリケーションに共通のメソッド、プロパティ、イベントを表現するものです。このクラスのイベントの一つに、Errorイベントがあります。未処理の例外がASP.NETランタイムに通知されるたびに、このイベントがトリガされます。例えば、あるASP.NET Webページに、データベースに接続してDELETEステートメントを実行するコードがあるものとします。このページに訪問者があったときにデータベースがオフライン状態になっていると、SqlExceptionが発生します。コード内にエラー処理ロジックがなければ、この例外はASP.NETページの分離コードクラスからASP.NETランタイムに通知され、その時点でErrorイベントが発生します。

 未処理の例外が発生した場合、通常は次のいずれかを行います。

  • エンドユーザーにユーザーフレンドリなカスタムメッセージを表示する
  • そのエラーを「処理」する
  • この場合は、後で調査できるようにエラーを記録したり、電子メールを送ってエラーを開発者に通知したり、問題の「修正」を試みたりする必要があるかもしれません。

 エラーを「処理」するには、まずアプリケーションのErrorイベントのイベントハンドラを作成する必要があります。イベントハンドラは「Global.asax」で作成できます。あるいはHTTPモジュールで処理できます。イベントハンドラでは、Server.GetLastError()メソッドを使って未処理の例外の詳細を取得できます。エラーの詳細が得られたら、その情報を記録したり、開発者に通知したり、ユーザーフレンドリなカスタムエラーページに制御を渡したりできます。

Global.asaxでErrorイベントハンドラを作成する

 「Global.asax」は、Webアプリケーションのルートディレクトリに追加できるオプションのファイルで、このファイルを使用してアプリケーションレベルおよびセッションレベルのイベントを処理することができます。アプリケーションのErrorイベントのイベントハンドラを作成するには、まず「Global.asax」ファイルを自分のプロジェクトに追加します。ソリューションエクスプローラで目的のプロジェクトを右クリックし、[Add New Item]を選択し、ダイアログボックスから[Global Application Class]を選択します(図1のスクリーンショットを参照)。

図1
図1

 これにより、メインアプリケーションレベルのイベント(ErrorStartEnd)に関するイベントハンドラと、セッションレベルのイベント(StartEnd)に関するイベントハンドラを含むダミーの「Global.asax」ファイルが作成されます。いま問題にしているのはErrorイベントだけなので、残りのイベントハンドラは削除してかまいません。

 Errorイベントハンドラでは、次のメソッドを呼び出すことにより、発生した例外に関する情報にアクセスできます。

HttpContext.Current.Server.GetLastError()

 このメソッドから返されるExceptionオブジェクトには、ランタイムに通知されたエラー(そのErrorイベントをトリガしたもの)に関する情報が入っています。その例外がASP.NETページによるものであれば、元の例外がHttpUnhandledException内にラップされています。ASP.NETページレベルの例外には、後ほど紹介するInnerExceptionプロパティを通じてアクセスできます。

 未処理の例外が発生したときには、電子メールで開発者に例外の詳細を知らせると共に、前回の記事「未処理の例外への適切な対処法」で説明したように、ユーザーをカスタムエラーページにリダイレクトするものとしましょう。これを行うためには、「Web.config」内で<customErrors>を適切に設定し、それから「Global.asax」内のErrorイベントハンドラに次のコードを追加します。

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
  ’Get exception details

  Dim ex As Exception = HttpContext.Current.Server.GetLastError()

  If TypeOf ex Is HttpUnhandledException AndAlso _

    ex.InnerException IsNot Nothing Then
    ex = ex.InnerException
  End If

  If ex IsNot Nothing Then

    Try
      ’Email the administrator with information
      ’that an error has occurred
      ’!!! UPDATE THIS VALUE TO YOUR EMAIL ADDRESS
      Const ToAndFromAddress As String = "’email address’"

      ’(1) Create the MailMessage instance
      Dim mm As New System.Net.Mail.MailMessage(ToAndFromAddress, _
        ToAndFromAddress)

      ’(2) Assign the MailMessage’s properties
      mm.Subject = "An unhandled exception occurred!"

      mm.Body = String.Format( _
        "An unhandled exception occurred:{0}Message: {1}{0}{0} Stack Trace:{0}{2}", _
        System.Environment.NewLine, ex.Message, ex.StackTrace)
      mm.IsBodyHtml = False

      ’(3) Create the SmtpClient object
      Dim smtp As New System.Net.Mail.SmtpClient

      ’(4) Send the MailMessage (will use the Web.config settings)

      smtp.Send(mm)
    Catch
      ’Whoops, some problem sending email!
      ’Just send the user onto CustomErrorPage.aspx...
    End Try
  End If

End Sub

 イベントハンドラの最初の数行に特に注意を払ってください。発生した例外にアクセスし(HttpContext.Current.Server.GetLastError())、必要に応じてInnerExceptionプロパティを調べています。それから、「Sending Email in ASP.NET 2.0」に掲載したコードを使って、例外の詳細を指定の電子メールアドレスに送ります(このコードで使用しているSMTPリレーサーバーの詳細は「Web.config」にあります)。

 ユーザーがデータ駆動型のページを訪れ、データベースに接続する際に問題があったします。このとき、ユーザーには設定されているエラーページが表示されますが、開発者には例外の詳細を記した電子メールが送られます。

図2
図2

リダイレクトではなく制御をカスタムエラーページに移す

 前回の記事「未処理の例外への適切な対処法」で説明したように、「Web.config」の<customErrors>セクションの設定によって、未処理の例外が発生したときにユーザーフレンドリなカスタムエラーページを表示することができます。あいにく、ASP.NETランタイムは未処理の例外が発生したときにユーザーをカスタムエラーページに「リダイレクト」します。ランタイムが呼び出すResponse.Redirect(customErrorPageUrl)は、HTTPのステータスコード302をブラウザに送信するのですが、これは指定のURL(customErrorPageUrl)を要求せよという意味です。このリダイレクトは新たなWeb要求なので、未処理の例外を持っていた要求とは何の関連もありません。そのため、カスタムエラーページからServer.GetLastError()を呼び出すと、null値が返されます。

 しかし、カスタムエラーページでエラーに関する情報を保持したいこともあります。おそらく、発生したエラーに応じたメッセージを表示したり、特定の役割を持つ認証された訪問者に例外の詳細を表示したいことがあるでしょう。これはErrorイベントハンドラ内でのServer.Transfer(customErrorPageUrl)の呼び出しによって達成できます。ドキュメントによれば、Server.Transfer(url)は「現在のページの実行を終了し、指定されたURLパスを使って新しいページの実行を開始」します。要するに、現在の要求の実行がサーバー上の別のページに委ねられるのです。クライアントに明示的なリダイレクトメッセージが返されることはなく、すべてがサーバー側で行われます。

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
    ’... Email details of exception to developer ...

    Server.Transfer("~/SmartCustomErrorPage.aspx")
End Sub

 Server.Transfer()でコンテキストが維持されるので、カスタムエラーページではServer.GetLastError()を使って未処理の例外に関する情報を取得できます。ブラウザから見ると、コンテキストに変化はありません。つまり、ブラウザのアドレスバーには、Server.Transfer()された先のURLではなく、未処理の例外を発生させたページのURLが引き続き表示されるわけです。

 この記事のダウンロードサンプルを使用すると、もっと高度なカスタムエラーページ(SmartCustomErrorPage.aspx)を表示できます。このエラーページは例外の詳細を調べて、発生した例外のタイプに応じてメッセージを組み立てます。

HTTPモジュールでErrorイベントを処理する

 HTTPモジュールは、ASP.NETランタイムが発生させたイベントに応答できるマネージドコンポーネントです。代わりに、Errorイベントに応答するイベントハンドラをHTTPモジュール内に置くことができます。HTTPモジュールを使用することの利点は、HTTPモジュールアセンブリを「/bin」ディレクトリにドロップし、アプリケーションの「Web.config」に1行か2行の設定を追加するだけで既存のASP.NETアプリケーションに追加できる「プラグ可能な」コンポーネントを提供することにあります。

 エラー処理のためにHTTPモジュールを作成し設定するのは本稿の守備範囲を超えるので、ここで説明することはできません。代わりに、Atif Azizが提供しているフリーなオープンソースライブラリ、ELMAH(Error Logging Modules And Handlers)をお勧めします。ELMAHは、未処理の例外をデータストアに記録するためのHTTPモジュールと、例外の詳細をWebページまたはRSSフィードに表示するためのHTTPハンドラから成ります。

 ELMAHは、GotDotNet Workspaceからダウンロードできます。ELMAHのセットアップとインストールの詳細については、「Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components」を参照してください。ELMAHのセットアップに要する時間は60秒くらいです。これにより、例外の詳細な記録、開発者への充実した通知、および例外の詳細をオンラインで見られるユーザーフレンドリなWebページが提供されます。ぜひ試してください。

 この記事のダウンロードサンプルでは、ELMAHライブラリを使ってSQL Server 2005 Express Editionデータベースにエラーを記録します。

まとめ

 Webアプリケーションで未処理の例外が発生した場合、通常はエンドユーザーにユーザーフレンドリなカスタムエラーページが表示され、例外の詳細が「処理」されるようにしたいと思うでしょう。例外をどのように処理するかはアプリケーションごとに違ってくるでしょうが、通常は例外を記録し、開発者に通知します。前回の記事「未処理の例外への適切な対処法」では、カスタムエラーページの表示方法を説明し、今回の記事では、アプリケーションのErrorイベントのためのイベントハンドラの作成方法を説明しました。

 例外の記録と通知を行うシステムを独自に作成するよりも、フリーなオープンソースライブラリのELMAHを試してみるようお勧めします。ELMAHには、未処理の例外を記録するためのHTTPモジュールと、例外の詳細を電子メールで送るためのオプションが含まれています。

 それでは、ハッピープログラミング!

参考資料

著者紹介

Scott Mitchell(Scott Mitchell)

過去コラム集
未処理の例外への適切な対処法
Webページ上に状況依存ヘルプを作成する
Webページ上の状況依存ヘルプの自動作成
CreateUserWizardコントロールのマルチステッププロセス化
クライアントサイドスクリプトを使ってGridView上のすべてのチェックボックスをオンにする方法
GridView上のすべてのチェックボックスをオンにする方法
大量の結果セットをさらに効率的にページングする方法
ASP.NET 2.0とSQL Server 2005によるカスタムのページング処理
SQL Server 2000で大量の結果セットを効率的にページングする方法
ASP.NET 2.0でカスタムのページング処理と並び替えを併用する
海外のインターネットコム アメリカ韓国ドイツトルコ
関連企業のサイト:ストックフォト イラスト ネットストリート ホテル予約サイト タウン情報 出張 事業継承 シミュレーション トランクルーム 優待映画チケット 田舎暮らしガイド オリジナルTシャツ ニタコエ
Copyright 2008 Jupitermedia Corporation All Rights Reserved. http://www.internet.com/
space.gif space.gif