5

IRouteHandler クラスの GettHttpHandler メソッドでセッションを有効にしようとしていますが、セッションは常に null です。誰かが私が間違っていることを教えてもらえますか?

global.asax には

RouteTable.Routes.Add("All", new Route("{*page}", new MyRouteHandler()));

Session が null の MyRouteHandler クラスは次のようになります。

public class MyRouteHandler : IRouteHandler, IRequiresSessionState
{
    public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        string test = HttpContext.Current.Session["test"].ToString();
        return BuildManager.CreateInstanceFromVirtualPath("~/Page.aspx", typeof(Page)) as Page;
    }
}

問題を示す小さなテストアプリを作成しました。

誰かが私が間違っていることを教えてもらえますか?

追加するために編集:

はい、ルート ハンドラにセッション データが必要です。多くの理由がありますが、簡単に説明できる理由の 1 つは、ユーザーがプレビュー モードでサイトを閲覧するように切り替えることができる場合です。

このサイトは、データベース内の動的ページ (/page1/page2...) の階層で構成されており、通常は公開またはプレビューできます。サイトを閲覧するコンテンツ プロデューサーは、通常のページだけを表示するか、プレビュー用に公開されたページも表示するかを選択できます。ブラウジング モードはユーザーのセッションに保存されるため、ルート ハンドラは要求されたページを解決できるようにブラウジング モードを知る必要があります。

だから私は本当にその段階ですでにセッションが必要です.

4

3 に答える 3

8

この回答で、この問題の背後にある理由を説明しました。そして今、私は問題の解決策を見つけました!

  1. カスタムHttpHandlerクラスを作成します。

    class MyHttpHandler : IHttpHandler, IRequiresSessionState
    {
      public MyRequestHandler RequestHandler;
      public RequestContext Context;
      public MyHttpHandler(MyRequestHandler routeHandler, RequestContext context)
      {
        RequestHandler = routeHandler;
        Context = context;
      }
    
      public void ProcessRequest(HttpContext context)
      {
        throw new NotImplementedException();
      }
    
      public bool IsReusable
      {
        get { throw new NotImplementedException(); }
      }
    }
    

IRequiresSessionStateインターフェイスを追加することが重要です。そうしないと、IIS はこの要求のセッションをロードしません。ProcessRequestandのロジックを実装する必要はありませんがIsReusable、クラスは IHttpHandler インターフェイスを実装する必要があります。

  1. RouteHandler の実装を変更します。

    public class MyRequestHandler : IRouteHandler
    {
      public IHttpHandler GetHttpHandler(RequestContext requestContext)
      {
          return new MyHttpHandler(this, requestContext);
      }
    
      public IHttpHandler DelayedGetHttpHandler(RequestContext requestContext)
      {
          // your custom routing logic comes here...
      }
    }
    

元のセッション依存のロジックをDelayedGetHttpHandler関数に移動するだけで、GetHttphandler関数内で補助 MyHttpHandler クラスのインスタンスを返します。

  1. HttpApplication.PostAcquireRequestState次に、 Global.asax などで処理ロジックをイベントにフックします。

    public class Global : HttpApplication
    {
        public override void Init()
        {
            base.Init();
            PostAcquireRequestState += Global_PostAcquireRequestState;
        }
     }
    

詳細については、https ://msdn.microsoft.com/en-us/library/bb470252(v=vs.140).aspx のページを確認してください。PostAcquireRequestStateリクエストのライフサイクルと、イベントを使用する理由について説明しています。

  1. イベント ハンドラーで、カスタム RouteHandling 関数を呼び出します。

    void Global_PostAcquireRequestState(object sender, EventArgs e)
    {
       if (HttpContext.Current.Handler is MyHttpHandler) {
         var handler = HttpContext.Current.Handler as MyHttpHandler;
         HttpContext.Current.Handler = handler.RouteHandler.DelayedGetHttpHandler(handler.Context);
       }
    }
    

以上です。私のために働きます。

于 2015-02-08T20:14:56.890 に答える
1

これができるかどうかはわかりません (間違っているかもしれませんが)。私の記憶では、IRequiresSessionState は、ルート ハンドラー (ルートに適したハンドラーを提供する役割を果たします) ではなく、HttpHandler がセッション状態を必要としていることを示しています。

ルート ハンドラ自体にセッションが必要であり、それが提供するハンドラではありませんか?

于 2010-06-18T08:11:15.783 に答える
1

これが古いスレッドであることはわかっていますが、私のような人が同じシナリオに陥った場合にここに答えを出すだけです。ここで答えを見つけまし

以下のように、web.config のモジュール タグに runAllManagedModulesForAllRequests="true" 属性を追加するだけです。

    <system.webServer>
    .....
       <modules runAllManagedModulesForAllRequests="true">
       ........
       </modules>
    ......
    </system.webServer>

ただし、これはマネージド モジュールを毎回呼び出すため、良い解決策ではありません。

    <remove name="Session" />
    <add name="Session" type="System.Web.SessionState.SessionStateModule"/>

web.config のモジュール セクションに追加します。これは前のソリューションよりも優れたソリューションです。

于 2011-12-28T21:49:50.943 に答える