Могу ли я получить доступ к состоянию сеанса из HTTPModule? - PullRequest
85 голосов
/ 09 ноября 2008

Я действительно мог бы обновлять переменные сеанса пользователя из моего модуля HTTPModule, но, насколько я вижу, это невозможно.

ОБНОВЛЕНИЕ: Мой код в настоящее время выполняется внутри обработчика событий OnBeginRequest ().

ОБНОВЛЕНИЕ: Следуя полученному совету, я попытался добавить это к подпрограмме Init () в моем HTTPModule:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Но в моей подпрограмме OnPreRequestHandlerExecute состояние сеанса все еще недоступно!

Спасибо и извинения, если я что-то упустил!

Ответы [ 5 ]

80 голосов
/ 09 ноября 2008

Обнаружено на форумах ASP.NET :

using System;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Diagnostics;

// This code demonstrates how to make session state available in HttpModule,
// regradless of requested resource.
// author: Tomasz Jastrzebski

public class MyHttpModule : IHttpModule
{
   public void Init(HttpApplication application)
   {
      application.PostAcquireRequestState += new EventHandler(Application_PostAcquireRequestState);
      application.PostMapRequestHandler += new EventHandler(Application_PostMapRequestHandler);
   }

   void Application_PostMapRequestHandler(object source, EventArgs e)
   {
      HttpApplication app = (HttpApplication)source;

      if (app.Context.Handler is IReadOnlySessionState || app.Context.Handler is IRequiresSessionState) {
         // no need to replace the current handler
         return;
      }

      // swap the current handler
      app.Context.Handler = new MyHttpHandler(app.Context.Handler);
   }

   void Application_PostAcquireRequestState(object source, EventArgs e)
   {
      HttpApplication app = (HttpApplication)source;

      MyHttpHandler resourceHttpHandler = HttpContext.Current.Handler as MyHttpHandler;

      if (resourceHttpHandler != null) {
         // set the original handler back
         HttpContext.Current.Handler = resourceHttpHandler.OriginalHandler;
      }

      // -> at this point session state should be available

      Debug.Assert(app.Session != null, "it did not work :(");
   }

   public void Dispose()
   {

   }

   // a temp handler used to force the SessionStateModule to load session state
   public class MyHttpHandler : IHttpHandler, IRequiresSessionState
   {
      internal readonly IHttpHandler OriginalHandler;

      public MyHttpHandler(IHttpHandler originalHandler)
      {
         OriginalHandler = originalHandler;
      }

      public void ProcessRequest(HttpContext context)
      {
         // do not worry, ProcessRequest() will not be called, but let's be safe
         throw new InvalidOperationException("MyHttpHandler cannot process requests.");
      }

      public bool IsReusable
      {
         // IsReusable must be set to false since class has a member!
         get { return false; }
      }
   }
}
39 голосов
/ 09 ноября 2008

HttpContext.Current.Session должен просто работать, предполагая, что ваш HTTP-модуль не обрабатывает никаких событий конвейера , которые происходят до инициализации состояния сеанса ...

РЕДАКТИРОВАТЬ, после уточнения в комментариях: при обработке события BeginRequest объект Session действительно все равно будет иметь значение null / Nothing, поскольку он еще не был инициализирован средой выполнения ASP.NET. Чтобы обойти это, переместите ваш код обработки в событие, которое происходит после PostAcquireRequestState - мне нравится PreRequestHandlerExecute для меня самого, так как вся работа низкого уровня в значительной степени выполняется на этом этапе , но вы все еще упреждаете любую нормальную обработку.

15 голосов
/ 13 сентября 2011

Доступ к HttpContext.Current.Session в IHttpModule можно выполнить с помощью обработчика PreRequestHandlerExecute.

PreRequestHandlerExecute : «Происходит непосредственно перед тем, как ASP.NET начнет выполнять обработчик событий (например, страницу или веб-службу XML)». Это означает, что перед обслуживанием страницы aspx это событие выполняется. «Состояние сеанса» доступно, поэтому вы можете выбить себя из колеи.

Пример:

public class SessionModule : IHttpModule 
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += BeginTransaction;
            context.EndRequest += CommitAndCloseSession;
            context.PreRequestHandlerExecute += PreRequestHandlerExecute;
        }



        public void Dispose() { }

        public void PreRequestHandlerExecute(object sender, EventArgs e)
        {
            var context = ((HttpApplication)sender).Context;
            context.Session["some_sesion"] = new SomeObject();
        }
...
}
12 голосов
/ 03 июня 2009

Если вы пишете обычный, базовый HttpModule в управляемом приложении, которое вы хотите применить к запросам asp.net через страницы или обработчики, вам просто нужно убедиться, что вы используете событие в жизненном цикле после создания сеанса , PreRequestHandlerExecute вместо Begin_Request, как правило, куда я иду. МДБ имеет право в своем редактировании.

Более длинный фрагмент кода, изначально указанный как ответ на вопрос, работает, но он сложнее и шире, чем первоначальный вопрос. Он будет обрабатывать случай, когда контент поступает от чего-то, у кого нет доступного обработчика ASP.net, где вы можете реализовать интерфейс IRequiresSessionState, тем самым вызывая механизм сеанса, чтобы сделать его доступным. (Как статический GIF-файл на диске). Это в основном установка фиктивного обработчика, который затем просто реализует этот интерфейс, чтобы сделать сеанс доступным.

Если вы просто хотите сеанс для своего кода, просто выберите правильное событие для обработки в вашем модуле.

0 голосов
/ 18 мая 2015

Попробуйте: в классе MyHttpModule объявите:

private HttpApplication contextapp;

Тогда:

public void Init(HttpApplication application)
{
     //Must be after AcquireRequestState - the session exist after RequestState
     application.PostAcquireRequestState += new EventHandler(MyNewEvent);
     this.contextapp=application;
}  

И так, в другом методе (событии) того же класса:

public void MyNewEvent(object sender, EventArgs e)
{
    //A example...
    if(contextoapp.Context.Session != null)
    {
       this.contextapp.Context.Session.Timeout=30;
       System.Diagnostics.Debug.WriteLine("Timeout changed");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...