CodeZine(コードジン)

特集ページ一覧

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

Errorイベントのイベントハンドラを作成してエラーの詳細を記録する

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/11/22 00:00

Webアプリケーションで未処理の例外が発生した場合、通常はエンドユーザーにユーザーフレンドリなカスタムエラーページを表示し、例外を記録して開発者に通知します。前回の記事では、カスタムエラーページの表示方法を説明しました。今回は、Errorイベントのイベントハンドラの作成方法を説明します。

目次

はじめに

 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

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

著者プロフィール

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5