Session is null in IRouteHandler.GetHttpHandler with Asp.net routing

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-01 05:29:16
Jan Kukacka

I have explained reason behind this problem in this answer. And now I have found a solution to the problem!

  1. You create a custom HttpHandler class:

    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(); }
      }
    }
    

It is important to add IRequiresSessionState interface, otherwise IIS does not load session for this request. We do not need to implement logic of ProcessRequest and IsReusable, but class must implement the IHttpHandler interface.

  1. You change your RouteHandler implementation:

    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...
      }
    }
    

You simply move your original, Session dependent logic to DelayedGetHttpHandler function and in the GetHttphandler function you return an instance of the helping MyHttpHandler class.

  1. Then, you hook your handling logic to the HttpApplication.PostAcquireRequestState event, e.g. in the Global.asax:

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

For more reference, check this page: https://msdn.microsoft.com/en-us/library/bb470252(v=vs.140).aspx. It explains the request lifecycle and why I use the PostAcquireRequestState event.

  1. In the event handler, you invoke your custom RouteHandling function:

    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);
       }
    }
    

And that's it. Works for me.

Rob Levine

I am not sure that you can do this (although I may be wrong). My recollection is that IRequiresSessionState indicates that an HttpHandler needs session state, rather than the route handler (which is responsible for giving you a handler appropriate to the route).

Do you really need the session in the route handler itself and not the handler it gives out?

DotNetUser

Well I know this is old thread but just putting up the answer here if anyone like me falls in the same scenario, I found an answer here

What you do is just add a runAllManagedModulesForAllRequests="true" attribute to your modules tag in web.config like below

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

However this is not a good solution as it calls managed module everytime, i am using

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

add it in modules section of web.config, this a better solution than the previous one.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!