Rat*_*tna 10 c# asp.net session-variables session-state global-asax
我正在研究的网站非常以数据为中心.有些报告需要一个多小时才能完成.每当用户提交报告请求时,都会创建一个生成报告的新线程.然后,用户将被重定向到一个页面,该页面显示正在进行的报告,并请刷新以下载报告.如果用户再次刷新页面并且报告仍在进行中,则会显示相同的消息; 否则提供下载链接.
所有报告/用户关系都保存在应用程序变量中.这工作正常,除非用户处于非活动状态超过20分钟(正在处理报告时),然后用户退出; 如果用户再次登录,仍可以下载报告.
我不想增加会话到期时间,但如果用户在后台进行了某些操作,我需要停止过期,例如正在处理的报表.
在Session_End中,我能够检索userid并匹配它Application["work"]以查看用户是否有待处理的工作.
但是,在上述情况下,如何推迟会话结束,我一无所知?
编辑:每个人都建议从"维护联系人"到"使用查询字符串"作为解决方法."保持联系"对我来说看起来最有希望,但在以下情况下失败了:a.当浏览器关闭/计算在午餐期间进入待机模式等时.当用户访问另一个nonasp.net部分(它是遗留站点)时.
是不是可以取消Session_End活动本身?
有目前(据我所知)没有简单的方法来延长寿命单一 ASP.NET会话.有一种可能的解决方案:使用自定义会话状态存储提供程序!
首先要做的事情:从已经建成的东西开始!使用Microsoft提供的示例会话状态存储提供程序(及其教程).此示例会话状态存储提供程序使用Microsoft Access作为其后端 ; 但是,因为它使用ODBC连接,所以几乎可以通过已安装的ODBC驱动程序支持任何数据库后端.
此示例会话状态存储提供程序只是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)
)
Run Code Online (Sandbox Code Playgroud)
注意:如果要使用SQL Server,只需将文本(...)替换为varchar(...),将YesNo替换为bit,将Memo替换为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>
Run Code Online (Sandbox Code Playgroud)
第三:增加将用于扩展功能更比指定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();
}
}
Run Code Online (Sandbox Code Playgroud)
第四:支持单个ASP.NET 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);
Run Code Online (Sandbox Code Playgroud)
脚注
使用示例会话状态存储提供程序读取页面上的注释 ;
使用GetItem时,GetSessionStoreItem中有一个关于错误的潜在好的条目.
另一个好处是时间戳应该是UTC.
有可以做(尤其是具有重复的代码明显的性能/可维护性改进ResetItemTimeout和ResetItemTimeout2).
我还没有测试过这段代码!
编辑
Timeout-答案已全面更新.虽然拼命寻找推迟 session_end 事件,但我认为这似乎不可能?
我能想到的最简单的解决方法是“使用 Cookie”并修改我的身份验证逻辑。
我实现了一种方法,当用户请求过期 9 小时(办公室开放工作的最长时间)的报告时,将 guid 密钥写入名为 admin 的 cookie。我将此 GUID 与用户 ID 保存在单独的表中。
在我检查会话用户 ID 的母版页中,我实现了另一种方法来检查任何名为 admin 的 cookie。如果找到,我将会话设置为表中保存的用户 ID,否则我将它们重定向到登录页面,就像发生之前一样。
它似乎像魔术一样起作用。但我需要知道这是正确的事情吗?
| 归档时间: |
|
| 查看次数: |
2050 次 |
| 最近记录: |