【问题标题】:Raise Session_OnStart event from custom ASP.NET SessionStateProvider class从自定义 ASP.NET SessionStateProvider 类引发 Session_OnStart 事件
【发布时间】:2011-03-25 12:49:57
【问题描述】:

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

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

当我使用自定义 SessionStateProvider 类时,我必须怎么做才能执行我的 Session_OnStart 代码?我可以访问源代码。

更新:它在 MSDN 上清楚地表明,通常,Session_OnStart 仅在 Session 模式为 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 需要自定义 SessionIDManagerSession_OnStart 事件究竟是从哪里触发的?看起来它与SessionIDManager有关,而不是SessionStateProvider

【问题讨论】:

  • Session_OnStart 根本没有触发吗? IE。您杀死了 VS Web 服务器,将 web.config 设置为您的提供程序,开始 VS 调试,不是吗?当你不设置 web.config - 它是?
  • 正确。 Session_OnStart 根本没有触发
  • on msdn.microsoft.com/en-us/library/ms178586.aspx 我可以看到对 OnEnd 的引用仅在 InProc 上工作,但对 OnStart 没有任何影响...我看不出有任何原因导致这不起作用,遗憾的是... :( 也许如果今晚我感到无聊,我会写一个简单的提供程序来尝试重现您的问题。

标签: asp.net events session global-asax session-state-provider


【解决方案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;}
    }
}

全球.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 的签名实际上是正确的? (即没有参数或 (object,eventargs) )。

目前我们处于不利地位,因为到目前为止我们所掌握的所有信息都是错误的。我们现在留下了有关您的 sessionstateprovider 导致 session_start 不触发或您的其余代码的某些内容。使用我的假人应该可以帮助我们回答这个问题(我希望如此)。

对于它的价值,应该在 CreateNewStoreData 方法在您的提供程序类中运行之后立即触发 session_start 事件,因此您可以尝试在那里放置一个断点,然后查看它在该方法之后的位置。

【讨论】:

  • 克里斯的回答很好。看完你的回答后,我发现问题似乎与SessionIDManager有关,而不是SessionStateProvider
  • @米粉饼干:酷。为你找到答案很有趣。您是否真的发现了 SessionIDManager 的问题,或者还有其他问题出现?并且自私地不要忘记接受我的回答,这样我才能得到赏金。 ;-)
  • 好吧,我希望了解如何使用自定义 SessionIDManager 来引发事件。
  • @Rice Flour Cookies:我实际上看不出 SessionIDManager 与引发此事件有什么关系...您能解释一下您是如何将其缩小到错误的吗?并且您是否有自定义 SessionStateModule 或者您是否使用标准的在支持类中添加了各种附加功能?该事件作为标准在 CompleteAquireState 方法中的 SessionStateModule 中引发。如果您使用的是这个标准,那么我真的看不出它是如何被调用的......
  • @Chris,我通过从我的 web.config 文件中删除 sessionIDManagerType="SessionIDManager.ProgramSessionIDManager" 将其缩小到 SessionIDManager
【解决方案2】:

我猜操作目标是做一些事情,比如初始化会话,而不是需要在 Session_OnStart 方法中专门做一些事情。假设是这种情况,我认为您可以执行以下操作:

1) 处理 Appication.PostAcquireRequestState 事件。
2) 在处理程序中,检查会话是否已初始化——穷人的方法是在会话中设置一个变量——然后采取适当的行动。

【讨论】:

    【解决方案3】:

    编辑: 看起来我确实有点错过了这个问题的重点。我将把这个答案留在这里,只是因为它可能会引起某些人的兴趣。如果您认为应该删除它,请随时发表评论。

    对不起,这是一个答案,因为我不是 100% 确定我在说什么,但它太长了,无法发表评论......

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

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

    所以本质上如果你的新模块是这样包含的:

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

    那么你会想要在你的 global.asax MySession_Start

    我希望这会有所帮助。对不起,如果它没有,它的所有东西你已经尝试过。我建议给出一些代码和一些关于你已经尝试过的想法,但是失败了。可能有趣的代码是您将自定义代码添加到站点的位置(即 web.config 的适当部分),如果可以轻松地将其缩减为微不足道的形式(例如,会话提供程序只是返回一个常量可能很短并显示您的错误)。还有一些迹象表明它是否保持会话状态(即它是否在不调用 onstart 的情况下工作)会很好。 :)

    编辑添加:我想我会链接我遇到的一个有用的网页。 http://aspnetresources.com/articles/event_handlers_in_global_asax 谈到了标准错误处理程序是如何在 global.asax 中连接起来的,并向我指出了有趣的方法 HookupEventHandlersForAppplicationAndModules,它给了我一些关于其中一些可能如何工作的线索。

    【讨论】:

    • 我尝试添加一个名为 MySession_OnStart 的子程序,但似乎没有被调用。
    猜你喜欢
    • 1970-01-01
    • 2015-10-05
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多