ASP.NETでのWebアプリケーションのエラー処理はじめに どんなアプリケーションにもエラー処理が必要です。そのことは誰でも知っています。しかし、我々開発者は、処理されないエラーがクライアントマシン上で発生した場合に、それを知ることができません。Webの良いところは、処理されないエラーが発生したときに、それを必ず知ることができるという点です。ASP.NETの登場により、エラーを処理するための優れた方法が新しく利用できるようになりました。.NETでは、エラーの処理方法や情報の提供方法に関していくつか違いがあります。たとえば、従来のASPでは 問題 アプリケーションではエラーが起こります。我々開発者は
問題を後からデバッグするためには、イベントログやデータベース、その他のログファイルなどのように、エラーを集中的に記録するための場所が不可欠です(私はこれを法医学的デバッグと呼んでいます)。 IISには優れたエラー処理機能があります(詳細についてはhttp://www.15seconds.com/issue/020821.htmに掲載されている私の記事を参照)。しかし、この機能にはいくつか問題があります。エラーの発生を予想できたとしても、そのエラーを洗練された方法でトラップするためには、サイトの既定のエラーリダイレクトページをオーバーライドしなければならない場合があります(このオーバーライドはIISのカスタムエラーページ内で行います。詳細は上記の記事を参照)。たとえば、認証が必要なリソースへのアクセスでエラーが発生した場合は、アプリケーションのログインページにリダイレクトすることが考えられます。また、Webホスティングに関しても問題があります。通常は、ホスティングしているWebサイトのIIS設定を制御できません。そのため、従来のASPでカスタムエラーページをセットアップすることはほぼ不可能です。ASP.NETでは、この問題が解決されています。以降ではこれについて説明します。 ソリューション問題はいくつかありますが、それに対するソリューションは非常に単純です。ASP.NETには、処理されないエラーへの対処を定義するための場所が3か所あります。
エラー処理イベントの実際の順序は次のとおりです。
注 Page_ErrorまたはApplication_Errorでエラーのバブルアップを取り消すには、サブルーチン内でServer.ClearError関数を呼び出します。詳しくは後述しますが、それぞれの方法にはそれぞれの用途があります。 アプリケーション内で発生した例外は、 System.Exceptionのパブリックプロパティ
Page_ErrorまたはOnErrorサブルーチンを使用する エラー処理の第一の防衛線はページレベルで実装します。次のようにして Private Sub Page_Error(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Error End Sub または Protected Overrides Sub OnError(ByVal e As System.EventArgs) End Sub これらのサブルーチンでエラーを処理するのは簡単です。
「global.asax」ファイルを使用する 「global.asax」ファイルでは、エラーに対する第二の防衛線を実装します。エラーが発生すると、 「web.config」ファイルを使用する 「web.config」ファイルの <customErrors defaultRedirect="url" mode="On|Off|RemoteOnly"> <error statusCode="statuscode" redirect="url"/> </customErrors> 既定では、Webアプリケーションを作成したときの
<customErrors mode="RemoteOnly" />
この場合、ユーザーには汎用ページが表示されます。独自に作成したページにリダイレクトするには、これを次のように変更します。
<customErrors mode="On" defaultRedirect="error.htm" />
こうすると、すべてのエラーに対して「error.htm」ページが表示されるようになります。 特定のエラーだけを処理し、それ以外のエラーはエラーページにリダイレクトするようにしたい場合は、特別な処理をするエラーコードを次の方法で指定します。 <customErrors mode="On" defaultRedirect="error.htm"> <error statusCode="500" redirect="error500.aspx?code=500"/> <error statusCode="404" redirect="filenotfound.aspx"/> <error statusCode="403" redirect="authorizationfailed.aspx"/> </customErrors> このソリューションには1つ問題があります。リダイレクトを行ったときに、リダイレクト先のページにエラー情報が渡されないのです。これは、IISは(.NET Frameworkを通じて)エラーページに対して古い単純なGET要求を実行するだけで、IIS組み込みのエラー処理のように リダイレクト先のページで利用できる情報は、エラーが発生したURLだけです。このURLは、クエリ文字列「aspxerrorpath」に格納されます(例:http://localhost/ErrorHandling/error500.aspx?aspxerrorpath=/ErrorHandling/WebForm1.aspx)。この情報を利用できるのは、前述の2つの場所だけです。 たとえば、ルートディレクトリの外に「Customers」というディレクトリがあるとします。このディレクトリは、ログインする顧客に固有のブランド情報を含んでいますが、独自のアプリケーション内には含まれていません。このような場合は、エラー用のページセットを別に定義する必要があるでしょう。ここで、 <configuration> <system.web> ... ... </system.web> <!-- Configuration for the "Customers" subdirectory. --> <location path="Customers"> <system.web> <customErrors mode="On" defaultRedirect="error.htm"> <error statusCode="500" redirect="CustomerError500.aspx"/> <error statusCode="401" redirect="CustomerAccessDenied.aspx"/> <error statusCode="404" redirect="CustomerPageNotFound.htm"/> <error statusCode="403" redirect="noaccessallowed.htm"/> </customErrors> <authorization> <allow roles="MYDOMAINCustomers" /> <deny users="*" /> </authorization> </system.web> </location> 注
開発していて気が付いたのは、これらのエラーには相続順位があるらしいということです。つまり、ルートサイトに500エラーを定義し、「Customers」ディレクトリにはエラーを何も定義せず、ただし「Customers」ディレクトリには
defaultRedirectを設定したという場合は、ルートレベルに定義した500エラーハンドラが呼び出されます。したがって、親ディレクトリにハンドラがある場合の話です。コードを使用する本稿のために設定付きのサンプルアプリケーションを作成しておいたので、これを見てコードの設定方法を勉強してください。サンプルのzipファイルは、2つのプロジェクトを含んだソリューションです。 そのうちの1つは、さまざまなエラーを発生させるボタンを備えたWebプロジェクトです。このプロジェクトは、ページ、「global.asax」ファイル、「web.config」ファイルでのエラー処理の例も示しています。さらに、クエリアナライザで実行できる「DotNetErrorLog.sql」も含まれています。このクエリは、エラーログ「ASAP」を開始するためのデータベース(およびユーザー)を作成します。 「web.config」ファイルには次のセクションが含まれています。 <appSettings> <add key="ErrorLoggingLogToDB" value="True" /> <add key="ErrorLoggingLogToEventLog" value="True" /> <add key="ErrorLoggingLogToFile" value="True" /> <add key="ErrorLoggingConnectString" value="Initial Catalog=DotNetErrorLog;Data Source=localhost;Integrated Security=SSPI;" /> <add key="ErrorLoggingEventLogType" value="Application" /> <add key="ErrorLoggingLogFile" value="c:ErrorManager.log" /> </appSettings> ここでは、アプリケーションの具体的な設定を定義しています。これらの設定をレジストリに登録する必要はありません。したがって、アプリケーションを開発環境、統合環境、本番環境の間で移行するときに便利です。セキュリティを高めるために、.NETに暗号化クラスを組み込んでデータベース接続情報を暗号化し、プレーンテキストの接続文字列ではなく暗号化した情報を「web.config」ファイルに格納することもできますが、これは明らかに本稿のテーマから外れています。これらの設定の内容は次のとおりです。
ログファイルまたはイベントログに記録される情報の例を次に示します。 -----------------12/20/2002 3:00:36 PM----------------- SessionID:qwyvaojenw1ad1553ftnesmq Form Data: __VIEWSTATE - dDwtNTMwNzcxMzI0Ozs+4QI35VkUBmX1qfHHH8i25a/4g4A=Button1 - Cause a generic error まず日付と時刻が記録されます。次にユーザーのセッションIDが記録されます。このセッションIDは、従来のASPセッションIDとは見た目が大きく異なります(以前はすべて数字でした)。次の行には、ページ上の任意のフォームデータが含まれます。このデータは、ページ上に入力された情報がアプリケーションのエラーの原因である場合に特に役立ちます。行頭に「1」とある行は、1番目のエラーを表しています。これらの行は、エラーの説明、ソース、スタックトレース、およびエラーの原因になった関数を示しています。「2」で始まる行は、エラー1の前に生成されたエラーです。この例でのエラー2は、エラー1の また、SMTPコンポーネントを使用してエラー発生時に電子メールを送信し、エラーにすばやく対処できるようにする、という使い方も考えられます。これを実現するには、上記の 補足ネットのどこかで、エラー発生時にはエラー番号を取得し、データベースから適切なメッセージをルックアップしてユーザーに表示するべきだ、という意見を見たことがあるのですが。それもいいアイデアだと思います。ただ、その方法の問題は、予想外のデータベースエラーが発生した場合にエラーページが機能しなくなるという点です。 try-catchブロック内でリダイレクトを実行する方法を手短に教えてください。 コードの 皆さんも、いろいろなエラーログ機能を試してみてください。 著者紹介Adam Tuliper(Adam Tuliper)
.NET、COM、VB、ASP、C、C++、およびSQL Serverによるビジネスソリューションとコンシューマアプリケーションの開発に従事。プログラム開発の仕事で6年以上のキャリアを持つ。インターネットセンターソフトウェアやシステム監視/セキュリティスキャンソフトウェアを開発するGecko Softwareのオーナーでもある。CISの学位を有す。いくつかの会社のセキュリティコンサルタントとしても活動している。メールの宛先はamt@gecko-software.com。
関連テーマ 最新トップニュース
|
|