Вызовите событие Session_OnStart из пользовательского класса ASP.NET SessionStateProvider.

Я работаю над проектом asp.net, который использует собственный разработанный класс SessionStateProvider.

Очевидно, событие Session_OnStart не запускается. У меня есть код в Global.asax для обработки события. Я могу только выполнить этот код, изменив файл Web.config для использования SessionStateProvider по умолчанию.

Что я должен сделать, чтобы мой код Session_OnStart выполнялся, когда я использую пользовательский класс SessionStateProvider? У меня есть доступ к исходному коду.

Обновление: на 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 >

Обновление еще раз: сегодня утром я нашел что-то интересное. Прочитав ответ Криса, я попытался использовать только клиента SessionStateProvider и удалил код для кастома SessionIDManager, Как только я это сделал, я сразу же смог увидеть Session_OnStart метод выполнить. Проблема в том, мой обычай SessionStateProvider требуется обычай SessionIDManager, Где именно Session_OnStart событие произошло из? Похоже, это связано с SessionIDManager, не SessionStateProvider,

3 ответа

Решение

Второй ответ, касающийся пользовательских SessionStateStores. Посмотрев на код, я не увидел причин, по которым он не будет вызывать начало сеанса, поэтому я попытался создать своего собственного совместимого, но не функционального поставщика состояния сеанса, чтобы увидеть, что происходит. С моим провайдером состояния сеанса он вызывал Session_start в global.asax нормально. Я включил свой код в качестве демонстрационного доказательства концепции:

Провайдер состояния сеанса:

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 действительно верна? (т.е. без параметров или (объект,eventargs)).

В настоящее время мы находимся в дурацкой позиции, потому что вся информация, которую мы имеем до сих пор, неверна Теперь у нас осталось либо то, что ваш sessionstateprovider заставляет session_start не срабатывать, либо что-то в остальной части вашего кода. Использование моего манекена должно помочь нам ответить на этот вопрос (я надеюсь).

Для чего стоит событие session_start должно быть запущено сразу после CreateNewStoreData Метод запущен в классе вашего провайдера, так что вы можете попробовать установить точку останова и посмотреть, куда он направляется после этого метода.

Изменить: Похоже, я немного упустил вопрос по вопросу. Я собираюсь оставить этот ответ здесь, хотя бы потому, что он может быть интересен для некоторых. Не стесняйтесь комментировать, если вы думаете, что он должен быть удален, хотя.

Извините, это ответ, так как я не на 100% уверен в том, что говорю, но это слишком долго, чтобы быть комментарием...

Я не был уверен, что вы создали пользовательский модуль сеанса или только провайдер хранилища состояний сеансов. Я предполагаю, что модуль, но я не был уверен, просто "SessionStateProvider"...

Из того, что я могу сказать, любой httpmodule, добавленный в web.config, будет проходить через процесс подключения к событиям в 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, который дал мне подсказку о том, как некоторые из этих функций могут работать.

Я предполагаю, что оперативная цель состоит в том, чтобы сделать что-то вроде, скажем, инициализации сеанса, а не в том, чтобы специально что-то делать в методе Session_OnStart. Предполагая, что это так, я думаю, вы можете сделать следующее:

1) Обработайте событие Appication.PostAcquireRequestState.
2) В обработчике проверьте, инициализирован ли сеанс - способ бедняка состоит в том, чтобы установить переменную в сеансе - затем действуйте соответствующим образом.

Другие вопросы по тегам