使用Asp.net路由的IRouteHandler.GetHttpHandler中的会话为空

Mat*_*und 5 asp.net session null routing iroutehandler

我正在尝试在我的IRouteHandler类的GettHttpHandler方法中启用Session,但session始终为null.有人能告诉我我做错了什么吗?

在global.asax我有

RouteTable.Routes.Add("All", new Route("{*page}", new MyRouteHandler()));
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我做了一个小测试应用程序来显示问题.

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

编辑添加:

是的,我真的需要路由处理程序中的会话数据.有许多原因,但可以轻松解释的是当用户可以切换到以预览模式浏览网站时.

该站点由数据库中的动态页面层次结构(/ page1/page2 ...)组成,可以正常发布或预览.浏览网站的内容制作者可以选择仅查看普通页面或查看发布到预览的页面.浏览模式存储在用户的会话中,因此路由处理程序需要知道浏览模式才能解析所请求的页面.

所以我真的需要在那个阶段的会议.

Jan*_*cka 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(); }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

添加IRequiresSessionState接口很重要,否则IIS不会为此请求加载会话.我们不需要实现ProcessRequest和的逻辑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...
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

您只需将原始的Session依赖逻辑移动到DelayedGetHttpHandler函数中,并在GetHttphandler函数中返回帮助MyHttpHandler类的实例.

  1. 然后,您将处理逻辑挂钩到HttpApplication.PostAcquireRequestState事件,例如在Global.asax中:

    public class Global : HttpApplication
    {
        public override void Init()
        {
            base.Init();
            PostAcquireRequestState += Global_PostAcquireRequestState;
        }
     }
    
    Run Code Online (Sandbox Code Playgroud)

有关更多参考,请查看此页面: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);
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)

就是这样.适合我.


Rob*_*ine 1

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

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