はじめに
HTTPハンドラは、ブラウザからの要求に応える役割を担っています。ブラウザが管理する要求は、ファイル拡張子(またはその欠如)に基づいて処理されるか、ハンドラを直接呼び出すことによって処理されます。1つの要求で呼び出せるハンドラは1つだけです。ハンドラは、.aspxファイルや.ascxファイルのような静的なHTMLテキストで構成されるものではありません。ハンドラは、IHttpHandler
インターフェイスを実装するクラスです。セッション情報をやり取りする必要がある場合は、IRequiresSessionState
も実装する必要があります。また、非同期ハンドラが必要な場合は、IHttpHandler
インターフェイスではなく、IHttpAsyncHandler
インターフェイスを実装しなければなりません。
ファイル拡張子によるハンドラの呼び出し
ハンドラは、「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」にtrace
セクションを追加することによって、Webサイトにトレースを設定します。
<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」を変更してもよいかを確認するメッセージが表示されます。デバッグを可能にすることを自分自身で明示的に指定する(<compilation debug="true"/>
とします)場合を除いては、ここで変更を受け入れます。

筆者のデスクトップは「text/plain」をXMLとして解析するようにセットアップされているため、筆者のブラウザでは次のようなエラーが発生します。

正しく動作させるためには、Visual Studioによって生成された「handler.ashx」を修正する必要があります。そこで、コンテンツタイプを「text/plain」から「text/html」に変更します。ビルドとデバッグを再び実行します。次のような応答が得られます。

Handler.ashx
「handler.ashx」ファイルはIHttpHandler
インターフェイスを実装しており、ProcessRequest
とIsReusable
という2つのメソッドを備えています。ProcessRequest
は、必要な処理コードを記述するメインのメソッドです。IsReusable
メソッドは、別の要求がIHttpHandler
インスタンスを使用できるかどうかを指定するメソッドであり、既定はtrueに設定されています。インスタンスが再利用可能な場合はtrueに設定します。これによって、ハンドラの処理速度が向上し、サーバーが実行しなければならない処理が削減されます。しかし、ステートや非同期が原因でインスタンスを再利用できない場合は、IsReusable
をfalseに設定する必要があります。
セッションステート
次に進む前に、「handler.ashx」のコードを変更してIRequiresSessionState
インターフェイスを実装します。セッションに対して読み取り専用のアクセスが必要な場合は、IReadOnlySessionState
インターフェイスを実装します。どちらのインターフェイスもSystem.Web.SessionState名前空間にあり、using
構文を使用して追加する必要があります。コードは次のようになります。
<%@ 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; } } }
クラス内の先頭行にブレークポイントを設定し、デバッグを再び開始します。