ASP.NET会话提前完成

时间:2011-11-22 23:35:53

标签: asp.net

我实现了从a control by Kenneth Scott派生的自定义ASP.NET会话超时控件。它由.NET 4中的.NET 4托管。

长话短说,它是我在网站母版页中包含的服务器控件(实现System.Web.UI.WebControls.WebControl)。该控件是不可见的,并在呈现页面时启动计时器。在X分钟过去之后,会显示一个DIV,告诉用户他们的会话超时,如果他们想要保持登录状态,则为他们提供一个单击按钮。

单击该按钮只会触发标准回发到服务器。除了重置会话的滑动到期外,它不会在服务器上执行任何有用的工作。

超时控件配置为在会话到期前一分钟启动。当它达到0时,会话也应该到期,我将用户重定向到登录页面并通知他们由于不活动而超时。

大部分时间都很好用,但有时“不起作用”。该按钮似乎仍然适用于用户,但在尝试单击站点上的任何其他控件后,它们会立即转储到登录页面(web.config中定义的标准ASP.NET行为)。

我在click事件处理程序中添加了一些日志记录语句,发现它没有触发。我的假设是客户端向服务器发送请求,但由于会话过期,我的事件处理程序永远不会触发。

我确信我的应用程序池没有被回收(它被配置为每天回收一次,并且没有进程或粘性指令管理员正在编辑应用程序目录中的文件)。这种失败是间歇性发生的。我们正在使用表单身份验证。

我在web.config中的system.web部分:

<sessionState mode="InProc" timeout="20" />
<authentication mode="Forms">
  <forms path="/" loginUrl="Pages/LoginPage.aspx" protection="All" timeout="20" slidingExpiration="true" />
</authentication>

我目前的解决方法是增加会话并将表单超时设置为30分钟,并为超时引入新的配置设置,该设置仍会在20分钟后将用户注销。额外的10分钟提供足够的填充,我的控件按预期工作。

我不喜欢这个解决方案,因为它最好是解决方法。我觉得我不能充分理解ASP.NET会话超时机制(尽管已阅读并重读了MSDN文档)。任何人都可以解释我所看到的行为,或者指出我正在做的任何错误的假设吗?

1 个答案:

答案 0 :(得分:3)

您可以尝试记录任何应用程序结尾以及结束的原因,只是为了排除它与此有关。我总是使用这个脚本(只需将它放在global.asax中):

protected void Application_End()
  {
     Type httpRuntimeType = typeof (HttpRuntime);

     HttpRuntime runtime =
        (HttpRuntime)
        httpRuntimeType.InvokeMember("_theRuntime", BindingFlags.NonPublic
                                                    | BindingFlags.Static |
                                                    BindingFlags.GetField,
                                     null, null,
                                     null);

     if (runtime == null)
        return;

     string shutDownMessage =
        (string) runtime.GetType().InvokeMember("_shutDownMessage",
                                                BindingFlags.NonPublic
                                                | BindingFlags.Instance
                                                | BindingFlags.GetField,
                                                null,
                                                runtime,
                                                null);

     string shutDownStack =
        (string) runtime.GetType().InvokeMember("_shutDownStack",
                                                BindingFlags.NonPublic
                                                | BindingFlags.Instance
                                                | BindingFlags.GetField,
                                                null,
                                                runtime,
                                                null);

     EventLog log = new EventLog();
     log.Source = ".NET Runtime";
     log.WriteEntry(
        String.Format(
           "\r\n\r\n_shutDownMessage={0}\r\n\r\n_shutDownStack={1}",
           shutDownMessage,
           shutDownStack),
        EventLogEntryType.Information);
  }