c# - 根据自定义条件防止个别 session 过期?

标签 c# asp.net session-variables session-state global-asax

我正在做的一个网站非常以数据为中心。有些报告需要一个多小时才能完成。每当用户提交报告请求时,都会创建一个新线程来生成报告。然后用户被重定向到一个页面,上面写着报告正在进行中,请刷新以下载报告。如果用户再次刷新页面并且报告仍在进行中,则显示相同的消息;否则提供下载链接。

所有报告/用户关系都保存在应用程序变量中。这工作正常,除非用户不活动超过 20 分钟(在处理报告时),然后用户注销;如果用户再次登录,报告仍然可以下载。

我不想增加 session 过期时间,但如果用户在后台进行某些操作(例如正在处理报告),我需要停止过期。

在 Session_End 中,我能够检索 userid 并在 Application["work"] 中匹配它以查看用户是否有待处理的工作。

但是,我不知道如何在上述情况下延迟 session 结束?


编辑:每个人都建议将“保持联系”改为“使用查询字符串”作为解决方法。 “保持联系”对我来说看起来是最有希望的,但在以下情况下它会失败:当浏览器关闭/计算在午餐期间进入待机模式等 b。当用户转到另一个非 asp.net 部分(这是一个旧站点)时。

不是可以取消Session_End事件本身吗?

最佳答案

简短回答

目前(据我所知)没有简单的方法可以延长单个 ASP.NET session 的生命周期。有一种可能的解决方案:使用自定义 session 状态存储提供程序!


长答案

要事第一:从已经构建好的东西开始!使用示例 Session-State Store Provider ( and its tutorial ) 由 Microsoft 提供。这个 Session-State Store Provider 示例使用 Microsoft Access 作为其后端;虽然,因为它使用 ODBC 连接,您实际上可以通过安装的 ODBC 驱动程序支持任何数据库后端。

此示例 session 状态存储提供程序只是 ASP.NET 内部使用的自定义版本(ASP.NET 在内存中运行除外)。


其次:让我们准备 Access 数据库要求和配置。

按照教程和文件注释中的说明创建表:

CREATE TABLE Sessions
(
    SessionId       Text(80)  NOT NULL,
    ApplicationName Text(255) NOT NULL,
    Created         DateTime  NOT NULL,
    Expires         DateTime  NOT NULL,
    LockDate        DateTime  NOT NULL,
    LockId          Integer   NOT NULL,
    Timeout         Integer   NOT NULL,
    Locked          YesNo     NOT NULL,
    SessionItems    Memo,
    Flags           Integer   NOT NULL,

    CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)

注意:如果您想使用 SQL Server,只需将 Text(...) 替换为 varchar(...)YesNo 使用 bitMemo 使用 varchar(MAX)

使用以下内容添加/更新您的 web.config(您可以使用 connectionstrings.com 来帮助您生成连接字符串):

<configuration>
    <connectionStrings>
        <add name="OdbcSessionServices" connectionString="DSN=SessionState;" />
    </connectionStrings>

    <system.web>
        <sessionState 
                cookieless="true"
                regenerateExpiredSessionId="true"
                mode="Custom"
                customProvider="OdbcSessionProvider">
            <providers>
                <add name="OdbcSessionProvider"
                        type="Samples.AspNet.Session.OdbcSessionStateStore"
                        connectionStringName="OdbcSessionServices"
                        writeExceptionsToEventLog="false" />
            </providers>
        </sessionState>
    </system.web>
</configuration>

第三: 添加一个函数,该函数将延长 更多 指定的 Timeout

复制 ResetItemTimeout 函数,并将其命名为 ResetItemTimeout2:

var ExtendedTotalMinutes = 2 * 60; // hours * minutes

public override void ResetItemTimeout2(HttpContext context, string id)
{
    OdbcConnection conn = new OdbcConnection(connectionString);
    OdbcCommand cmd = 
        new OdbcCommand("UPDATE Sessions SET Expires = ? " +
            "WHERE SessionId = ? AND ApplicationName = ?", conn);
    cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value 
        = DateTime.Now.AddMinutes(ExtendedTotalMinutes); // IMPORTANT!! Set your total expiration time.
    cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
    cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;

    try
    {
        conn.Open();

        cmd.ExecuteNonQuery();
    }
    catch (OdbcException e)
    {
        if (WriteExceptionsToEventLog)
        {
            WriteToEventLog(e, "ResetItemTimeout");
            throw new ProviderException(exceptionMessage);
        }
        else
            throw e;
    }
    finally
    {
        conn.Close();
    }
}

第四:支持单个ASP.NET Session的扩展!

每当您需要延长 session 时,调用ResetItemTimeout函数,如下所示:

using Samples.AspNet.Session;

// from inside a User Control or Page
OdbcSessionStateStore.ResetItemTimeout2(this.Context, this.Session.SessionID);

// --or--

// from anywhere else
OdbcSessionStateStore.ResetItemTimeout2(System.Web.HttpContext.Current, System.Web.HttpContext.Current.Session.SessionID);

脚注

  1. 阅读comments在带有示例 Session-State Store Provider 的页面上;

    • 关于 使用 GetItem 时 GetSessionStoreItem 中的错误,有一个潜在的好条目。

    • 另一个好处是时间戳应该是 UTC

  2. 可以进行明显的性能/可维护性改进(尤其是在 ResetItemTimeoutResetItemTimeout2 中有重复代码)。

  3. 没有测试过这段代码!


编辑

  • 我意识到我错过了您想延长 更多 的部分,而不是 Timeout - 答案已完全更新。
  • 添加了脚注部分。

关于c# - 根据自定义条件防止个别 session 过期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15742420/

相关文章:

c# - 抽象工厂和控制反转在运行时解析

c# - Azure c# 函数是否有可能默默地失败?

asp.net - 不了解 IIS 经典模式和集成模式?

c# - 如何在 telerik C# 的 OnItemCreated 事件中获取列的值

javascript - 在远程数据源调用之前将过滤器注入(inject)数据源

javascript - 使用 Javascript 删除 CSS 悬停功能

javascript - 使用 javascript 参数命名 sessionStorage 变量

php - 将 session 保存路径理解为无值(value)和安全性

php - 在本地变量之前设置 $_SESSION 的奇怪 PHP 变量行为

c# - 在 .NET 中以编程方式编写 CSS