从自定义ASP.NET SessionStateProvider类引发会话启动事件

从自定义ASP.NET SessionStateProvider类引发会话启动事件,asp.net,events,session,global-asax,session-state-provider,Asp.net,Events,Session,Global Asax,Session State Provider,我正在处理一个asp.net项目,该项目使用内部开发的自定义SessionStateProvider类 显然,会话启动事件没有触发。我在Global.asax中有代码来处理该事件。我只能通过将Web.config更改为使用默认SessionStateProvider来执行此代码 当我使用自定义SessionStateProvider类时,我必须如何执行会话启动代码?我可以访问源代码 更新:MSDN上明确指出,通常,Session\u OnStart仅在会话模式为InProc时启动,因此我必须做一

我正在处理一个asp.net项目,该项目使用内部开发的自定义SessionStateProvider类

显然,会话启动事件没有触发。我在Global.asax中有代码来处理该事件。我只能通过将Web.config更改为使用默认SessionStateProvider来执行此代码

当我使用自定义SessionStateProvider类时,我必须如何执行会话启动代码?我可以访问源代码

更新:MSDN上明确指出,通常,
Session\u 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的回答后,我尝试只使用customer
SessionStateProvider
,并删除了自定义
SessiondManager
的代码。一旦我这样做了,我就可以立即看到
Session\u OnStart
方法执行。问题是,我的自定义
SessionStateProvider
需要一个自定义
SessionIDManager
Session\u OnStart
事件从何处触发?它似乎与
会话管理器有关,而不是与
会话状态提供程序有关。编辑:看起来我确实有点遗漏了问题的要点。我将把这个答案留在这里,只是因为它可能会引起一些人的兴趣。如果你认为应该删除它,请随时发表评论

很抱歉,这是一个答案,因为我不是100%确定我说什么,但它太长了,不能作为一个评论

我不确定您是否创建了自定义会话模块或jsut会话状态存储提供程序。我假设是模块,但我不确定是否只是“SessionStateProvider”

据我所知,web.config中添加的任何httpmodule都将经历一个尝试连接global.asax中事件的过程。它这样做的方式似乎是通过寻找形式为“{name}{event}”或“{event}”的方法,并将它们连接起来,我认为{name}是您在web.config中给模块的名称,{event}当然是类中事件的名称(即start)

因此,本质上,如果您的新模块包含如下内容:

<add name="MySession" type="MySessionStateModule" />

讨论了global.asax中的标准错误处理程序是如何连接起来的,并向我指出了一个有趣的方法hookupeventhandlersforapapplication和modules,它为我提供了一些关于其中一些可能如何工作的线索。

我猜操作目标是做一些事情,比如,初始化会话,而不需要在会话启动方法中专门执行某些操作。假设是这样,我认为你可以做以下几点:

1) 处理Appification.PostAcquireRequestState事件。

2) 在handler中,检查会话是否已初始化——穷人的方法是在会话中设置一个变量——然后采取适当的行动。

第二个答案涉及自定义会话状态存储。在查看代码时,我看不出它为什么不调用sessionstart,所以我尝试创建自己的兼容但不起作用的sessionstateprovider来查看发生了什么。使用我的会话状态提供程序,它在global.asax fine中调用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>

这篇文章的要点主要是说,如果您使用提供的会话管理模块,即使使用自定义提供程序,它也应该触发会话启动事件。也许您可以尝试使用我的虚拟状态提供程序,看看它是否会触发您的事件。我还假设会话启动的签名实际上是正确的?(即无参数或(对象、事件参数))

目前,我们处于一个无用的位置,因为我们目前掌握的所有信息都是错误的。我们现在只剩下关于您的sessionstateprovider导致会话启动未启动的信息,或者关于您的其余代码的信息。使用我的假人可以帮助我们回答这个问题(我希望如此)


不管它值多少钱,会话启动事件应该在提供者类中运行
CreateNewStoreData
方法之后立即触发,这样您就可以尝试在那里放置断点,看看它在该方法之后会指向何处。

会话启动是否根本没有触发?也就是说,您杀死了VS web服务器,向您的提供商设置了web.config,启动了VS调试,但事实并非如此?当你没有设置web.config时,它是正确的。Session_OnStart根本没有启动。在上,我可以看到对ONED的引用仅在InProc上工作,而对OnStart没有任何引用。。。很遗憾,我看不出有什么理由这不起作用……:(如果今晚我觉得无聊,我可能会编写一个简单的提供者来尝试重新处理您的问题。我尝试添加了一个名为MySession_OnStart的sub,但似乎没有被调用。回答得很好Chris。在阅读您的答案后,我发现问题似乎与
SessiondManager
有关,而不是
SessionStateProvider
@Rice Fare Cookies:酷。为你找到答案很有趣。你真的发现你的会话管理有问题吗