[英]Can I access session state from an HTTPModule?
我真的可以從我的 HTTPModule 中更新用戶的會話變量,但從我所見,這是不可能的。
更新:我的代碼當前正在OnBeginRequest ()
事件處理程序中運行。
更新:根據到目前為止收到的建議,我嘗試將其添加到 HTTPModule 中的Init ()
例程中:
AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute
但是在我的OnPreRequestHandlerExecute
例程中,會話狀態仍然不可用!
謝謝,如果我遺漏了什么,我深表歉意!
在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; }
}
}
}
HttpContext.Current.Session應該可以正常工作,假設您的 HTTP 模塊沒有處理在會話狀態被初始化之前發生的任何管道事件......
編輯,在注釋中澄清后:處理BeginRequest 事件時,Session 對象確實仍然為 null/Nothing,因為它還沒有被 ASP.NET 運行時初始化。 要解決此問題,請將您的處理代碼移至PostAcquireRequestState之后發生的事件——我自己喜歡PreRequestHandlerExecute ,因為在此階段幾乎完成了所有低級工作,但您仍然搶占了任何正常處理。
可以在PreRequestHandlerExecute
處理程序中訪問IHttpModule
的HttpContext.Current.Session
。
PreRequestHandlerExecute :“在 ASP.NET 開始執行事件處理程序(例如,頁面或 XML Web 服務)之前發生。” 這意味着在提供“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();
}
...
}
如果您要在托管應用程序中編寫一個普通的基本 HttpModule,並希望通過頁面或處理程序應用於 asp.net 請求,則只需確保在會話創建后的生命周期中使用事件。 PreRequestHandlerExecute 而不是 Begin_Request 通常是我去的地方。 mdb 在他的編輯中是正確的。
最初列為回答問題的較長代碼片段有效,但比最初的問題復雜和廣泛。 當內容來自沒有可用的 ASP.net 處理程序的內容時,它將處理這種情況,您可以在其中實現 IRequiresSessionState 接口,從而觸發會話機制使其可用。 (就像磁盤上的靜態 gif 文件)。 它基本上是設置一個虛擬處理程序,然后只實現該接口以使會話可用。
如果您只需要代碼的會話,只需選擇要在模塊中處理的正確事件。
試試看:在 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");
}
}
從 .NET 4.0 開始,不需要使用 IHttpHandler 進行此 hack 加載會話狀態(就像最受好評的答案中的那樣)。 有一個方法HttpContext.SetSessionStateBehavior來定義所需的會話行為。 如果所有請求都需要 Session,請在 web.config HttpModule 聲明中將runAllManagedModulesForAllRequests
設置為 true,但請注意,為所有請求運行所有模塊會產生顯着的性能成本,因此請確保使用preCondition="managedHandler"
如果您不這樣做所有請求都需要會話。 對於未來的讀者,這里是一個完整的例子:
web.config 聲明 - 為所有請求調用 HttpModule:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess"/>
</modules>
</system.webServer>
web.config 聲明 - 僅為托管請求調用 HttpModule:
<system.webServer>
<modules>
<add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess" preCondition="managedHandler"/>
</modules>
</system.webServer>
IHttpModule 實現:
namespace HttpModuleWithSessionAccess
{
public class ModuleWithSessionAccess : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
}
private void Context_BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
app.Context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
private void Context_PreRequestHandlerExecute(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if (app.Context.Session != null)
{
app.Context.Session["Random"] = $"Random value: {new Random().Next()}";
}
}
public void Dispose()
{
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.