5

我试图在我的 IRouteHandler 类的 GettHttpHandler 方法中启用 Session,但 session 始终为空。有人可以告诉我我做错了什么吗?

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

我制作了一个显示问题的小型测试应用程序。

有人可以告诉我我做错了什么吗?

编辑添加:

是的,我确实需要路由处理程序中的会话数据。原因有很多,但一个很容易解释的原因是用户可以切换到以预览模式浏览网站。

该站点由数据库中的动态页面(/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 不会为此请求加载会话。我们不需要实现 and 的逻辑ProcessRequestIsReusable但是类必须实现 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...
      }
    }
    

您只需将原始的 Session 相关逻辑移动到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

好吧,我知道这是旧线程,但是如果像我这样的人遇到相同的情况,请在这里提出答案,我在这里找到了答案

您只需在 web.config 中的 modules 标记中添加一个 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 回答
1

我不确定你能做到这一点(尽管我可能错了)。我记得 IRequiresSessionState 表明 HttpHandler 需要会话状态,而不是路由处理程序(它负责为您提供适合路由的处理程序)。

您真的需要路由处理程序本身中的会话而不是它提供的处理程序吗?

于 2010-06-18T08:11:15.783 回答