ジェネリック ハンドラーでRouteDataを取得する - ASP.NET

ジェネリック ハンドラーにURLルーティングをして、RouteDataを取得するコードを紹介します。

概要

ASP.NETではURLルーティングを利用して、URLを書き換えて別のWebフォームへのアクセスに指定することができます。Webフォームにルーティングすする場合は大きな問題はありませんが、ジェネリックハンドラーにルーティングした場合、ジェネリックハンドラー内ではRouteDataが取得できないため、対策が必要です。

対応方法

URLルーティングのルーティング先をURLの文字列で書き換えた先のURLにすることが多いですが、IRouteHandlerを継承したクラスを直接指定します。クラスをルーティング先に指定するとルーティングによりURLの書き換えと、ルーティング先に指定したオブジェクトの GetHttpHandler が実行されます。
GetHttpHandler メソッドに引数としてRequestContext が渡されます。この、RequestContext オブジェクト内にルーティング情報である RouteDataが格納されており、ルーティング情報にアクセスできます。
GetHttpHandlerハンドラ内でジェネリックハンドラーのオブジェクトを作成することで、ジェネリックハンドラーの処理を呼び出すことができます。ジェネリックハンドラへのRouteDataの情報の受け渡しは、ジェネリックハンドラ側に、RequestContext 型のメンバ変数を用意し、ジェネリックハンドラ作成時に、メンバ変数に、RequestContext を代入することで情報を渡します。

プログラム例

コード

下記のコード、ファイルを準備します。
プロジェクトの新しい項目の追加で、"グローバル アプリケーション クラス"を選択し、Global.asaxファイルを追加します。


Global.asaxにルーティングのコードを記述します。
Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;

namespace AspNetRoutingGenericHandler
{
  public class Global : System.Web.HttpApplication
  {

    protected void Application_Start(object sender, EventArgs e)
    {
      Route myRoute = new Route("action/{*productid}", null);
      myRoute.RouteHandler = new MyHttpHandler();
      RouteTable.Routes.Add("", myRoute);
    }

    protected void Session_Start(object sender, EventArgs e)
    {

    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {

    }

    protected void Application_Error(object sender, EventArgs e)
    {

    }

    protected void Session_End(object sender, EventArgs e)
    {

    }

    protected void Application_End(object sender, EventArgs e)
    {

    }
  }
}

ルーティングにより呼び出されるクラスです。このクラスは、IRouteHandlerの派生クラスである必要があります。プロジェクトの新しい項目の追加で"ASP.NET ハンドラー"を選択して追加し、派生元クラスのIHttpHandlerIRouteHandlerに書き換えるか、新しい項目の追加で"クラス"を追加して下記のコードを記述します。
MyHttpHandler.cs
using System;
using System.Web;
using System.Web.Routing;

namespace AspNetRoutingGenericHandler
{
  public class MyHttpHandler : IRouteHandler
  {
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
      return new MyHandler() { RequestContextRouting = requestContext };
    }
  }
}

ジェネリックハンドラを作成します。プロジェクトの新しい項目の追加で"ジェネリック ハンドラー"を選択して追加し下記のコードを記述します。
MyHandler.ashx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;


namespace AspNetRoutingGenericHandler
{
  /// <summary>
  /// MyHandler の概要の説明です
  /// </summary>
  public class MyHandler : IHttpHandler
  {
    public RequestContext RequestContextRouting;

    public void ProcessRequest(HttpContext context)
    {
      context.Response.ContentType = "text/plain";
      if (RequestContextRouting.RouteData != null) {
        string pid = RequestContextRouting.RouteData.Values["productid"].ToString();
        context.Response.Write(pid);
      }
    }

    public bool IsReusable
    {
      get
      {
        return false;
      }
    }
  }
}

解説

Global.asax

ASP.NETのURLルーティングの実装コードを記述します。多くの場合、URLルーティングではルーティング先のURLを指定しますが、今回はURLではなくIRouteHandler を実装したクラスMyHttpHanderを指定します。

MyHttpHandler.cs

URLルーティングにより呼び出されるクラスです。このクラスでは処理をせず、GetHttpHandler メソッドの戻り値で処理を実行するジェネリックハンドラのインスタンスを返します。

MyHandler.ashx.cs

処理のロジックが実装されたジェネリックハンドラです。今回の例では、ルーティング元のURLの末尾部分の階層名を取得し画面に表示しています。

実行結果

プロジェクトを実行しWebブラウザが表示されますので、下記のURLにアクセスします。
http://localhost:57587/action/PenguinCookie

ページが表示されます。ページにURLのaction以下の"productid"の値が表示されます。MyHandler.ashxでの処理によりRouteDataの取得ができていることが確認できます。


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2024-01-06
作成日: 2018-01-31
iPentec all rights reserverd.