Вызовите событие Session_OnStart из пользовательского класса ASP.NET SessionStateProvider. - PullRequest
2 голосов
/ 05 августа 2010

Я работаю над проектом 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 ]

1 голос
/ 11 августа 2010

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

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

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

1 голос
/ 10 августа 2010

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

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

0 голосов
/ 10 августа 2010

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

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

...