【问题标题】:HttpApplication.Context null in Global.asaxGlobal.asax 中的 HttpApplication.Context 为空
【发布时间】:2016-04-04 14:38:13
【问题描述】:

引用此answer regarding regenerating new SessionID

我在 Global.asax.cs 中创建了这段代码:

        protected void Application_Start(object sender, EventArgs e)
        {
            Bootstrapper.Initialized += new EventHandler<ExecutedEventArgs>(Bootstrapper_Initialized);
        }

        void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        {
            if (e.CommandName == "Bootstrapped")
            {
                EventHub.Subscribe<ILoginCompletedEvent>(LoginCompletedEventVerification);
            }
        }


        private void LoginCompletedEventVerification(ILoginCompletedEvent evt)
        {
            if (evt.LoginResult == UserLoggingReason.Success)
            {
                var manager = new SessionIDManager();
                var oldId = manager.GetSessionID(Context);
                var newId = manager.CreateSessionID(Context);
                bool isAdd = false, isRedir = false;
                manager.SaveSessionID(Context, newId, out isRedir, out isAdd);
                var ctx = HttpContext.Current.ApplicationInstance;
                var mods = ctx.Modules;
                var ssm = (SessionStateModule)mods.Get("Session");
                var fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                SessionStateStoreData rqItem = null;
                SessionStateStoreProviderBase store = null;
                FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
                foreach (var field in fields)
                {
                    if (field.Name.Equals("_store")) store = (SessionStateStoreProviderBase)field.GetValue(ssm);
                    if (field.Name.Equals("_rqId")) rqIdField = field;
                    if (field.Name.Equals("_rqLockId")) rqLockIdField = field;
                    if (field.Name.Equals("_rqSessionStateNotFound")) rqStateNotFoundField = field;
                    if ((field.Name.Equals("_rqItem")))
                    {
                        rqItem = (SessionStateStoreData)field.GetValue(ssm);
                    }
                }
                var lockId = rqLockIdField.GetValue(ssm);
                if ((lockId != null) && (oldId != null))
                {
                    store.ReleaseItemExclusive(Context, oldId, lockId);
                    store.RemoveItem(Context, oldId, lockId, rqItem);
                }
                rqStateNotFoundField.SetValue(ssm, true);
                rqIdField.SetValue(ssm, newId);
            }
        }

请记住,我正在使用 Sitefinity Web 应用程序进行开发。 每次我的应用程序在成功登录期间点击 LoginCompletedEventVerification 时,Context 都会显示为 null。现在,我最初想将这个 sn-p 添加到 Sitefinity LoginWidget,但实现它是另一回事。

我没有将它包含在代码示例中,但我确实有 Session_Start 触发来创建我的应用程序的“购物车”。我只是想在身份验证后为购物车创建一个新的 SessionID。

在此活动期间我无法获得Context 的值有什么原因吗?

提前致谢。我感谢任何建议或批评!

编辑: Sitefinity knowledge base article where I got my Bootstrapper_Initialized code

【问题讨论】:

    标签: c# asp.net session sitefinity


    【解决方案1】:

    LoginCompletedEvent 事件是同步的——它不是在后台线程中触发的,而是身份验证请求的一部分。您可以通过直接调用 HttpContect.Current 来访问当前上下文,或者由于您处于 Sitefinity 应用程序的上下文中,因此您可以将 Sitefinity 包装器用于当前上下文:

    var currentContext = SystemManager.CurrentHttpContext;
    

    【讨论】:

      【解决方案2】:

      我没有将它包含在代码示例中,但我确实有 Session_Start 触发以创建我的应用程序的“购物车”。我只是想 身份验证后为购物车创建一个新的 SessionID。

      不。忘记在 Application_Start 事件中访问 HttpContext。

      您也可以在Application_BeginRequest

      private static object syncRoot = new object();
      private static bool initialized = false;
      public void Application_BeginRequest(object sender, EventArgs e)
      {
          if (!initialized)
          {
              lock (syncRoot)
              {
                  if (!initialized)
                  {
                      // Do your stuff here with HttpContext
      
                      initialized = true;
                  }
              }
          }
      }
      

      您应该注意的另一件事是 HttpContext 在您可能已生成且 HTTP 请求已完成执行的任何后台线程中均不可用。因此,您在尝试访问此 HttpContext 时应格外小心。

      【讨论】:

      • 我没有在 Application_Start 中访问 HttpContext,但可能我理解不正确。并感谢您的及时回复!
      • 是的,我可以看到您正在某个后台线程中访问它。由于明显的原因,这也不起作用。 HttpContext 只能从 HTTP 请求的主要执行管道访问。尝试在任何其他不受 ASP.NET 控制的事件处理程序中访问它只会惨遭失败。因此,请确保此 LoginCompletedEventVerification 不会在某些后台线程上触发。如果是这种情况,您将无法使用 HttpContext。
      • 如果您尝试在后台线程中访问 HttpContext,Application_BeginRequest 的解决方案将无济于事。只有当您需要直接在 Application_Start 中访问 HttpContext 时,它才会对您有所帮助(这是不允许的,因此在第一个 Begin_Request 中这样做是一种解决方法)。
      • 好的。我应该提到我正在关注 Sitefinity 关于LoginCompletedEventVerification 的文章。我将不得不看看这是否是在后台线程上触发的。谢谢你的信息。
      • 如果HttpContext.Current 为空,很明显它是在后台线程上触发的,与任何 ASP.NET 上下文无关。就像您尝试在控制台应用程序中访问 HttpContext.Current 一样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多