Я действительно мог бы обновить переменные сеанса пользователя из моего HTTPModule, но из того, что я вижу, это невозможно.
ОБНОВИТЬ: Мой код в настоящее время выполняется внутри обработчика событий OnBeginRequest ().
ОБНОВИТЬ: Следуя полученному совету, я попытался добавить это в подпрограмму Init () в моем HTTPModule:
AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute
Но в моей программе OnPreRequestHandlerExecute состояние сеанса все еще недоступно!
Спасибо и извиняюсь, если я что-то упускаю!





HttpContext.Current.Session должен просто работать, если ваш HTTP-модуль не обрабатывает конвейерные события, которые возникают до инициализации состояния сеанса ...
ИЗМЕНИТЬ, после пояснения в комментариях: при обработке BeginRequest событие объект Session действительно будет иметь значение null / Nothing, поскольку он еще не был инициализирован средой выполнения ASP.NET. Чтобы обойти это, переместите свой код обработки в событие, которое происходит после PostAcquireRequestState - мне самому нравится PreRequestHandlerExecute, так как вся низкоуровневая работа в значительной степени выполняется на этом этапе, но вы все равно предотвращаете любую нормальную обработку.
Я обрабатываю OnBeginRequest?
Спасибо за обновление. Если я обрабатываю его в событии уровня приложения, почему бы мне просто не выполнять всю свою обработку на уровне приложения вместо использования HTTPModule?
PostAcquireRequeststate не является «событием уровня приложения»: например, если HTTP-запрос обрабатывается обработчиком веб-службы, вы все равно увидите его в своем HTTP-модуле, но не в Global.asax ...
Похоже, это не работает для меня надежно. Следующий код часто вызывает исключение «Состояние сеанса недоступно в этом контексте». Фактически, это довольно эффектно вызывает сбой отладчика VS. context.PreRequestHandlerExecute + = (отправитель, аргументы) => Console.Write (((HttpApplication) отправитель) .Session ["тест"];
Я пробую это, и, похоже, все работает нормально, кроме запросов GET - теперь они не проходят мимо события ResolveRequestCache. Раньше у меня было все в AuthenticateRequest (до ResolveRequestCache), но теперь я переместил свой код в PreRequestHandlerExecute, чтобы я мог использовать состояние сеанса. Сначала оказалось, что мой HTTP-модуль даже не видит запросы GET, но, подписавшись на каждое событие в жизненном цикле HTTP-модуля и регистрируя каждое из них, я вижу, что мои запросы GET проходят, но останавливаются после события ResolveRequestCache. Какие-нибудь мысли?
Я также должен отметить, что Fiddler показывает 404-Not found для моих запросов GET. Есть ли параметр в IIS, который мне нужно изменить, чтобы это решение работало с GET?
Нашел это на Форумы 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,
// regardless 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; }
}
}
}
MS должна это исправить! ... если я помечу модуль как реализующий IRequiresSessionState, мне не придется прыгать через обруч, чтобы получить его ... (действительно сексуальный код)
Хороший код. Я думал, мне это понадобится, но оказалось, что нет. Этот код завершает загрузку сеанса для каждого изображения и других ресурсов, не относящихся к странице, которые проходят через сервер. В моем случае я просто проверяю, является ли сеанс нулевым в событии PostAcquireRequestState, и возвращаю, если это так.
Этот код полезен, если запрошенный ресурс не обрабатывает состояние сеанса. Для стандартных страниц .aspx просто добавьте код доступа к сеансу в обработчике событий PostAcquireRequestState. Состояние сеанса не будет доступно ни для одного обработчика событий BeginRequest, поскольку состояние сеанса еще не получено.
Фантастический. Спасибо, amigo, этот код действительно помог использовать HttpContext.Current.User в HttpModule
Для тех, кто хочет использовать этот «хак», единственный способ получить эту работу - заставить временный обработчик использовать IReadOnlySessionState вместо IRequiresSessionState.
В моем случае это не работает. Я получил сообщение «Состояние сеанса недоступно в этом контексте». когда есть запрос, пытающийся получить доступ к статическому файлу. Любая помощь ?
OriginalHandler.ProcessRequest(context); в ProcessRequest, если ваш код на самом деле вызывает ProcessRequest(<C>)Чтобы это работало со статическими файлами, я, кроме того, повторно зарегистрировал модуль сеанса (в web.config), удалив preCondition = "managedHandler" (<remove name = "Session" /> <add name = " Session "type = " System.Web.SessionState.SessionStateModule "/>)
Это сработало для защиты папки с файлами PDF с использованием моего существующего кода входа / сеанса. Я нашел аналогичную реализацию, которая разбивает ее на 3 раздела, выполняя проверку сеанса в PreRequestHandlerExecute. Я нашел это более ясным для понимания. martinwilley.com/net/code/AuthorizeModule.html. Я выбрал IReadOnlySessionState как nokturnal, чтобы не бездельничать, а также нуждался в изменении web.config с @nlips
Если вы пишете обычный, базовый HttpModule в управляемом приложении, которое хотите применить к запросам asp.net через страницы или обработчики, вам просто нужно убедиться, что вы используете событие в жизненном цикле после создания сеанса. PreRequestHandlerExecute вместо Begin_Request обычно то место, куда я иду. mdb имеет это право в его редактировании.
Более длинный фрагмент кода, изначально указанный как ответ на вопрос, работает, но он сложнее и шире исходного вопроса. Он будет обрабатывать случай, когда контент поступает из чего-то, что не имеет доступного обработчика ASP.net, где вы можете реализовать интерфейс IRequiresSessionState, тем самым запуская механизм сеанса, чтобы сделать его доступным. (Как статический файл в формате gif на диске). По сути, он устанавливает фиктивный обработчик, который затем просто реализует этот интерфейс, чтобы сделать сеанс доступным.
Если вам просто нужен сеанс для вашего кода, просто выберите правильное событие для обработки в вашем модуле.
Доступ к 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();
}
...
}
Я попробовал это, и вы действительно получили сеанс. Но похоже, что RequestHeader там не полностью, особенно HeaderContentType
Попробуйте: в классе 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");
}
}
К сожалению, это недоступно в HTTPModule - «Ссылка на объект не установлена на экземпляр объекта».