ASP.NET 2.0のHTTPハンドラ(*.ashx)をデバッグするはじめに HTTPハンドラは、ブラウザからの要求に応える役割を担っています。ブラウザが管理する要求は、ファイル拡張子(またはその欠如)に基づいて処理されるか、ハンドラを直接呼び出すことによって処理されます。1つの要求で呼び出せるハンドラは1つだけです。ハンドラは、.aspxファイルや.ascxファイルのような静的なHTMLテキストで構成されるものではありません。ハンドラは、 ファイル拡張子によるハンドラの呼び出しハンドラは、「web.config」とIISファイル拡張子マッピングでマップされているファイル拡張子によって起動することができます。例えば「something.billybob」という名前のファイルが要求された場合は、「billybob」というファイル拡張子に基づいてハンドラが起動されます。「http://web/handler/file」のようにファイル拡張子がない要求が行われた場合は、「*.*」またはディレクトリ「*」にマップされているハンドラが起動されます。 ハンドラの直接呼び出しWebサーバー上でのハンドラのコードファイルの拡張子は「ashx」です。このファイルは、「web.config」やIISファイル拡張子マッピングを設定しなくても、例えば「http://web/handler/handler.ashx」と指定して直接呼び出すことができます。このタイプのハンドラの例としては、フォトアルバム、RSSフィード、ブログサイトなどがあります。これらは、標準のHTMLなしでも適切に実現できる機能の好例です。フォトアルバムは、ディレクトリのクロールを行って画像を返す処理を行います。RSSフィードは、必要な情報を適切な形式で返す処理を行います。 サンプルハンドラ(Trace.axd) ファイル拡張子で起動されるハンドラの例として、デバッグに使用される「Trace.axd」ファイルを考えてみましょう。「Trace.axd」ハンドラを起動するためには、「web.config」に <configuration> <system.web> <trace enabled="true"/> </system.web> </configuration> その後、「http://localhost/trace.axd」などと指定して、Webサイトのルートから「Trace.axd」ファイルを呼び出します。 ハンドラをファイル拡張子で起動するためのIISマッピング要求のファイル拡張子に基づいてハンドラを起動するためには、「web.config」およびIISファイル拡張子マッピングで設定を行う必要があります。「*.axd」ファイルのファイルマッピングを確認するには、IISマネージャを開き、アプリケーションを設定します。[Mappings]タブを表示し、下方向にスクロールして.axdファイル拡張子を表示します。 ![]() .axd拡張子をダブルクリックすると、このマッピングの詳細が表示されます。 ![]() ファイル拡張子(またはその欠如)に基づいてハンドラを起動する方法には、何をいつ呼び出すかを柔軟に制御できるというメリットがあります。ファイル拡張子ハンドラに関する記事はWeb上でいくつも紹介されているため、本稿では、直接呼び出されるハンドラに焦点を当てます。 ハンドラの作成ハンドラコードファイルを作成するには、Visual Studio 2005(.NET 1.xハンドラの場合はVisual Studio 2003)のWebサイトが必要です。新しいWebサイトとして、[ASP.NET Web Site]を選択します。 ![]() 「App_Data」ディレクトリと「default.aspx」ファイルから成るWebサイトが作成されます。「default.aspx」は使用しないので、そのまま残しておいても、削除しても構いません。 ![]() ソリューションエクスプローラでWebサイトをクリックして「web.config」とハンドラファイルを作成し、「web.config」と「Generic Handler」の新しいアイテムを追加します。 ![]() ハンドラコードファイルは、次のようになります。 <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; public class Handler : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } } ここでプロジェクトをビルドし、「handler.ashx」ファイルをスタートアップファイルとして設定します。デバッグを開始します。デバッグを可能にするよう「web.config」を変更してもよいかを確認するメッセージが表示されます。デバッグを可能にすることを自分自身で明示的に指定する( ![]() 筆者のデスクトップは「text/plain」をXMLとして解析するようにセットアップされているため、筆者のブラウザでは次のようなエラーが発生します。 ![]() 正しく動作させるためには、Visual Studioによって生成された「handler.ashx」を修正する必要があります。そこで、コンテンツタイプを「text/plain」から「text/html」に変更します。ビルドとデバッグを再び実行します。次のような応答が得られます。 ![]() Handler.ashx 「handler.ashx」ファイルは セッションステート 次に進む前に、「handler.ashx」のコードを変更して <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Web.SessionState; public class Handler : IHttpHandler , IReadOnlySessionState{ public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } } クラス内の先頭行にブレークポイントを設定し、デバッグを再び開始します。 デバッグビルドでのデバッグデバッグビルドを使用するときは、Visual Studioデバッガのすべてのリソース、すべての.NET Framework名前空間、およびすべてのユーティリティとアプリケーションを利用できます。Visual Studioデバッガでは、コールスタック、ローカル変数、ウォッチ変数などを確認できます。読者の皆さんは、これらの機能にある程度は精通していることでしょう。しかし、HTTPハンドラの場合、デバッグはこれまで以上に重要です。それは、目に見える形で現れるバグは、すべてコンテンツにコーディングした内容であるためです。 リリースビルドでのデバッグリリースビルドは、機能とパフォーマンスの両方の面でデバッグビルドとは異なります。リリースビルドを使用しているときは、おそらく運用環境にあります。そのような場合は、異なるツールセットを使用して問題箇所を見つける必要があります。 System.Diagnostics名前空間によるデバッグ Diagnostics名前空間には、リリースモードとデバッグモードでのデバッグに役立つクラスが数多く用意されています。リリースモードでデバッグする場合は、 これらのクラスの使い方を理解するために、この名前空間を使用して、無限ループを使用するようにコードを変更してみましょう。アサーション内の式がfalseのときにエラーがスローされるので、以下の例ではカウンタが10に達するとエラーがスローされます。 <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Web.SessionState; using System.Diagnostics; public class Handler : IHttpHandler , IReadOnlySessionState{ public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; context.Response.Write("Hello World"); int i=0; while (1!=0) { Debug.Assert(i<10); i++; } } public bool IsReusable { get { return false; } } } ビルドとデバッグを行ってみましょう。ブレークポイントが設定されていないため、アサーションがヒットするとデバッガが再びアクティブになります。発見しようとするエラーがあらかじめ分かっていて、それをテストできる場合には、この方法が適しています。まずアサーションウィンドウが表示され、アサーションに関する情報が表示されます。デバッガをアクティブにしたい場合は、[Retry]ボタンをクリックします。これによりデバッガが表示され、問題のアサーションコード行が示されます。 特定の <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Web.SessionState; using System.Diagnostics; public class Handler : IHttpHandler , IReadOnlySessionState{ public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; context.Response.Write("Hello World"); Debugger.Break(); int i=0; while (1!=0) { Debug.Assert(i<10); i++; } } public bool IsReusable { get { return false; } } } デバッグセッションの中で、 リリースビルドで問題の原因を突き止めるには、コードを調べる手段が必要です。1つの方法は、コードに <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Web.SessionState; using System.Diagnostics; public class Handler : IHttpHandler , IReadOnlySessionState{ public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; context.Response.Write("Hello World"); int i=0; // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = "HTTPHandler-DebugArticle"; while (i<100) { if (i/10==0) { // Write an informational entry to the event log. myLog.WriteEntry("Writing to event log: i is divisible by 10."); } i++; } } public bool IsReusable { get { return false; } } } ハンドラのリリースバージョンをビルドし、実際に呼び出してみましょう。出力には、「Hello World」というテキストだけが含まれます。それではイベントビューアを開き、アプリケーションログを開いてください。「HTTPHandler-DebugArticle」というソースからの多くの情報が表示されます。 ![]() このうちいずれかのイベントを開くと、簡単な出力が表示されます。 ![]() System.Diagnostics名前空間には、パフォーマンスモニタと連携するクラスや、ロジックフローのデバッグに役立つプロセスやクラスもあります。 プロセスにアタッチして実行中のHTTPハンドラをデバッグする 問題箇所を見つけるもう1つの方法として、HTTPハンドラを含むプロセスにアタッチする方法があります。複数のWebサイトを実行していて、各Webサイトがそれぞれ独自のプロセス空間にある場合は、プロセスIDを判別しなければならない可能性があります。ハンドラにこれを指定させるのが、最も簡単な方法です。System.Diagnostics名前空間には <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Web.SessionState; using System.Diagnostics; public class Handler : IHttpHandler , IReadOnlySessionState{ public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; context.Response.Write("Hello World"); int i=0; Process.GetCurrentProcess().Id.ToString(); // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = "HTTPHandler-DebugArticle"; myLog.WriteEntry("Process Id is " + Process.GetCurrentProcess().Id.ToString()); while (i<100) { if (i/10==0) { // Write an informational entry to the event log. myLog.WriteEntry("Writing to event log: i is divisible by 10."); } i++; } } public bool IsReusable { get { return false; } } } ここで重要なコード行は、ループ内のコード行と、 ![]() プロセスIDが分かったら、このIDをタスクマネージャで探す必要があります。タスクマネージャでプロセスIDを探すには、[プロセス]タブをクリックし、[表示]をクリックして、[列の選択]を選択します。[PID(プロセスID)]チェックボックスをオンにし、[OK]をクリックしてダイアログを閉じます。プロセスのリストに[PID]列が表示されるので、列名をクリックしてソートできます。リスト内で目的のプロセスIDを見つけたら、これを右クリックし、[デバッグ]を選択します。これによってVisual Studioが開始します。Visual Studioからコードファイルを開き、そこでデバッグを行います。 まとめASP.NET HTTPハンドラは単純なクラスであり、これを使用することで要求を処理し、ブラウザに応答を返すことができます。ハンドラによって、現在のWebコンテキストとセッションステートにアクセスできます。Visual Studio 2005で提供される既定の「Generic Handler」は、現在のコードでは動作しない可能性があります。いくつかの変更を加え、System.Diagnostics空間と連携することで、ビルドとデバッグが正しく行われるHTTPハンドラを作成することができます。 著者紹介Dina Fleet Berry(Dina Fleet Berry)
|