我正在开发一个使用内部开发的自定义SessionStateProvider类的asp.net项目。
显然,Session_OnStart事件未触发。我在Global.asax中有代码来处理事件。我只能通过更改Web.config来使用默认的SessionStateProvider来执行此代码。
当我使用自定义SessionStateProvider类时,我该怎么做才能使Session_OnStart代码执行?我可以访问源代码。
更新:它在MSDN上明确指出,Session_OnStart
通常仅在会话模式为InProc时触发,因此我将不得不采取一些特殊措施来解决此问题我想要的方式。
我在web.config中的会话状态配置如下所示:
< sessionState cookieless="false" regenerateExpiredSessionId="true" mode="Custom"
customProvider="ProgramSessionStateProvider"
sessionIDManagerType="SessionIDManager.ProgramSessionIDManager"
sqlConnectionString="SqlSessionServices" cookieName="smartSessionID" >
< providers >
< add name="ProgramSessionStateProvider"
type="SessionStateProvider.ProgramSessionStateProvider"
connectionStringName="SqlSessionServices" writeExceptionsToEventLog="false" / >
< /providers >
< /sessionState >
再次更新:今天早上我发现了一些有趣的事情。阅读Chris的回答后,我尝试仅使用客户SessionStateProvider
并删除了自定义SessionIDManager
的代码。一旦我这样做,我立即能够看到Session_OnStart
方法执行。问题是,我的自定义SessionStateProvider
需要自定义SessionIDManager
。从Session_OnStart
事件发生的确切位置是什么?它看起来与SessionIDManager
有关,而不是SessionStateProvider
。
答案 0 :(得分:1)
编辑:看起来我确实错过了这个问题的重点。我将在这里留下这个答案,只是因为它可能对某些人感兴趣。如果你认为它应该被删除,请随意发表评论。
对不起,这是一个答案,因为我不是100%肯定我在说什么,但它太长了,无法发表评论......
我不确定您是否已创建自定义会话模块或jsut会话状态存储提供程序。我假设模块,但我不确定只是“SessionStateProvider”......
据我所知,web.config中添加的任何httpmodule都会经历一个尝试连接global.asax中的事件的过程。这样做的方式似乎是通过查找“{name} _ {event}”或“{name} _on {event}”形式的方法,然后将它们连接起来,我认为 { name}是你在web.config中给模块的名称,{event}当然是类中事件的名称(即start)。
所以从本质上讲,如果您的新模块包括在内:
<add name="MySession" type="MySessionStateModule" />
然后你想要你的global.asax MySession_Start
我希望这会有所帮助。对不起,如果没有,以及你之前尝试过的所有东西。我建议给出一些代码以及你已经尝试过的一些想法,但是它会失败。可能有趣的代码是将自定义代码添加到站点中(即web.config的相应部分),也可能是会话类中的一些代码,如果它可以轻松地缩小到一个简单的形式(例如会话提供程序,只返回一个常量可以很短并证明你的错误)。还有一些关于它是否保持会话状态的指示(即它是否工作分开而不是调用onstart)将是好的。 :)
编辑添加:我以为我会链接其中一个有用的网页。 http://aspnetresources.com/articles/event_handlers_in_global_asax讨论了如何在global.asax中连接标准错误处理程序,并指出了有趣的方法HookupEventHandlersForAppplicationAndModules,它为我提供了一些关于其中一些可能如何工作的线索。
答案 1 :(得分:1)
处理自定义SessionStateStores的第二个答案。在查看代码时,我看不出它为什么不会调用会话启动,所以我尝试创建自己的兼容但非功能的会话状态提供程序,以查看发生了什么。使用我的会话状态提供程序,它在global.asax中调用了Session_start。我将我的代码作为概念的演示证明:
会话状态提供者:
namespace WebApplication1
{
public class SessionStateProvider : System.Web.SessionState.SessionStateStoreProviderBase
{
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
ISessionStateItemCollection foo = new SessionStateItemCollection();
HttpStaticObjectsCollection bar = new HttpStaticObjectsCollection();
return new SessionStateStoreData(foo, bar, 300);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout){}
public override void Dispose() { }
public override void EndRequest(HttpContext context) { }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
locked = false;
lockAge = TimeSpan.FromSeconds(10);
lockId = new object();
actions = SessionStateActions.None;
ISessionStateItemCollection foo = new SessionStateItemCollection();
HttpStaticObjectsCollection bar = new HttpStaticObjectsCollection();
return new SessionStateStoreData(foo, bar, 300);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
locked = false;
lockAge = TimeSpan.FromSeconds(10);
lockId = new object();
actions = SessionStateActions.None;
ISessionStateItemCollection foo = new SessionStateItemCollection();
HttpStaticObjectsCollection bar = new HttpStaticObjectsCollection();
return new SessionStateStoreData(foo, bar, 300);
}
internal virtual void Initialize(string name, NameValueCollection config, IPartitionResolver partitionResolver) { }
public override void InitializeRequest(HttpContext context) { }
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { }
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { }
public override void ResetItemTimeout(HttpContext context, string id) { }
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { }
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback){return true;}
}
}
的Global.asax:
protected void Session_Start(object sender, EventArgs e)
{
throw new Exception("It worked!");
}
的web.config:
<sessionState mode="Custom" customProvider="MySessionProvider">
<providers>
<add name="MySessionProvider" type="WebApplication1.SessionStateProvider"/>
</providers>
</sessionState>
这篇文章的重点主要是说如果你使用提供的会话管理模块,即使使用自定义提供程序,它仍然应该触发session_start事件。也许您可以尝试使用我的虚拟状态提供程序,看看是否会触发您的事件。另外我假设你的session_onstart的签名实际上是正确的吗? (即没有参数或(对象,事件))。
目前我们处于一个公开的位置,因为到目前为止我们所掌握的所有信息都是错误的。我们现在留下了关于你的sessionstateprovider的任何东西导致session_start不会触发或者其他代码的内容。使用我的假人应该帮助我们回答这个问题(我希望)。
在您的提供程序类中运行CreateNewStoreData
方法之后,应该触发session_start事件的值得,因此您可以尝试在那里放入一个断点,并在该方法之后查看其前进的位置。 / p>
答案 2 :(得分:0)
我猜测操作目标是做一些事情,比如初始化会话,而不需要在Session_OnStart方法中专门做一些事情。假设是这种情况,我认为你可以做到以下几点:
1)处理Appication.PostAcquireRequestState事件。
2)在处理程序中,检查会话是否已初始化 - 穷人的方式是在会话中设置变量 - 然后采取适当的行动。