Sessione non disponibile in IHttpModule

Nel mio programma sto provando a usare la variabile di sessione in IHttpModule. Ecco il mio codice. Funziona perfettamente con il server di sviluppo VS 2010. Ma quando provo a eseguire il debug in IIS7, viene mostrata un’eccezione System.Web.HttpException: Session state is not available in this context Perché la sessione non è disponibile in IIS 7 ma nel server di sviluppo.

 using System; using System.Web; public class Globalizer : IHttpModule { public void Init(HttpApplication context) { context.AcquireRequestState += new EventHandler(setLanguage); } public void Dispose(){} public void setLanguage(Object sender, EventArgs i_eventArgs) { HttpApplication http_application = sender as HttpApplication; http_application.Session["language"] = "test"; } } 

Tutto ciò che serve è implementare IRequiresSessionState .

Quindi il tuo codice dovrebbe apparire come:

 public class Globalizer : IHttpModule, IRequiresSessionState 

se tutto ciò che usi è leggere Sessioni (e non aggiornarle mai), allora dovresti usare IReadOnlySessionState perché questo non blocchi lo stato della sessione, e quindi non avrai richieste simultanee).

Se ansible, sposta il gestore su un gestore PostAcquireRequestState :

Si verifica quando lo stato della richiesta (ad esempio, lo stato della sessione) associato alla richiesta corrente è stato ottenuto.

(O anche un evento successivo)

Lo stesso SessionStateModule carica lo stato della sessione in risposta all’evento AcquireRequestState . Quindi, al momento, dipende dal tipo di gestione del modulo o dei gestori dello stato della sessione.

Trovato su questo nei forum 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; } } } } 

Trovato il motivo.

Se è perché si AcquireRequestState trigger AcquireRequestState per tutti i file come CSS, JS, immagini. quei file non stanno avendo sessione.

soluzione: sembra che ci sia un modo per evitare di chiamare IHttpModule per tutte le richieste. ckeck questa risposta JS, immagini e CSS intercettati da HTTPModule .

Ma non ha funzionato per me. Quindi io uso HttpContext.Current.Session invece di HttpApplication.Session e ogni volta che controlla se Session è nullo prima di salvare in sessione.

Se qualcuno sa, Come evitare di chiamare IHttpModule per file diversi da .aspx Si prega di aiuto qui.

Ecco il codice finale

 using System; using System.Web; public class Globalizer : IHttpModule { public void Init(HttpApplication context) { context.AcquireRequestState += new EventHandler(setLanguage); } public void Dispose(){} public void setLanguage(Object sender, EventArgs i_eventArgs) { if(HttpContext.Current.Session != null){ HttpContext.Current.Session["language"] = "test"; } } } 

Modifica: un altro modo è utilizzare la sessione solo se la richiesta arriva in un file .aspx

 HttpApplication http_application = sender as HttpApplication; HttpContext context = http_application.Context; if(Path.GetExtension(context.Request.PhysicalPath) == ".aspx") { HttpContext.Current.Session["language"] = "test"; http_application.Session["language2"] = "test2"; }