我在通过Global.asax.Session_End()
终止ASP.Net会话后,尝试通过Session.Abandon()
执行清理任务。
我已确保以下
Session["foo"] = "bar"
)现在我遇到以下行为:
当我将会话全局写入(web.config中为enableSessionState = true
)时,我Global.asax.Session_End()
会在Session.Abandon()
之后不久按预期触发。
但是,当我在web.config中设置enableSessionState = ReadOnly
并且只允许某些页面通过EnableSessionState="true
向会话添加数据时,例如
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="WebPages_Login" EnableSessionState="true"%>
Global.asax.Session_End()
之后不会触发 Session.Abandon()
,但仅在会话超时后触发。
如何在全局设置Global.asax.Session_End()
的{{1}}上触发Session.Abandon()
?
答案 0 :(得分:1)
我不得不深入研究这个问题。
当从具有EnableSessionState = ReadOnly的页面触发Session.Abandon()时,InProcSessionState未标记为已锁定(_locked = false)。
仅当触发Session.Abandon()的请求的EnableSessionState = true时才会发生这种情况
来自System.Web.SessionState.InProcSessionStateStore.DoGet(...):
if (exclusive) {
lockedByOther = true;
// If unlocked, use a spinlock to test and lock the state.
if (!state._locked) {
state._spinLock.AcquireWriterLock();
try {
if (!state._locked) {
lockedByOther = false;
state._locked = true;
state._utcLockDate = DateTime.UtcNow;
state._lockCookie++;
}
lockId = state._lockCookie;
}
finally {
state._spinLock.ReleaseWriterLock();
}
}
如果会话被放弃,System.Web.SessionState.SessionStateModule.OnReleaseState()将为会话触发_store.RemoveItem()。但是,如果当前的InProcSessionState被锁定,则仅执行此RemoveItem()。请参见InProcSessionStateStore.RemoveItem():
try {
/* Only remove the item if we are the owner */
if (!state._locked || state._lockCookie != lockCookie)
return;
/* prevent overwriting when we drop the lock */
state._lockCookie = 0;
}
因此,在这种情况下(EnableSessionState = ReadOnly),Session.Abandon()根本不会放弃会话。看起来像是一个ASP.Net错误。
因此,我必须做的是两次触发清理代码:
答案 1 :(得分:1)
我对OP有类似的设置。我的应用程序中的一些处理程序使用只读会话状态。但是,我发现.NET中的事件名称显然发生了变化(https://msdn.microsoft.com/en-us/library/ms178583.aspx)。在实现Session_OnStart和Session_OnEnd之后,我的会话被正确终止并且调用Session_OnEnd。我不会在会话状态中存储任何项目。所以我认为没有必要。