2015-10-12 6 views
11

Ho un'applicazione WebForms ASP.NET 4.0. Devo accedere a HttpContext.Current.Session e impostare un valore nell'evento AcquireRequestState in Global.asax (o un evento successivo) e ho riscontrato un comportamento particolare.La sessione è nullo in AcquireRequestState quando si carica il nome della directory virtuale nel browser, ma non è null durante il caricamento di Default.aspx

Supponiamo di avere una directory virtuale in IIS (versione 7 nel mio caso) denominata . In questo ho Default.aspx come pagina iniziale. Un esempio di file Global.asax è qui sotto:

<%@ Application Language="C#" %> 

<script runat="server"> 
    void Application_AcquireRequestState(object sender, EventArgs e) 
    { 
     HttpContext.Current.Session["key"] = "value"; 
    } 
</script> 

Quando visito http://localhost/Foo/Default.aspx nel mio browser, funziona bene. Quando visito lo http://localhost/Foo/ ottengo un NullReferenceException dove imposto il valore sulla sessione. L'unica modifica è l'URL nel browser. Finiscono per colpire la stessa pagina, ma il framework si comporta diversamente in base al fatto che l'URL contenga o meno un nome di cartella o se contenga un file aspx.

Il controllo if (HttpContext.Current.Session != null) non è un'opzione per me, perché è necessario impostare un valore sulla sessione con ogni richiesta, che non è negoziabile.

Esiste un'impostazione di configurazione in IIS che mi manca oppure è una funzionalità di bug/dimenticata?

Una risposta per another question ha accennato al fatto che IIS non carica la sessione per ogni tipo di richiesta, ad esempio i fogli di stile non hanno bisogno di una sessione. Forse questo comportamento sta accadendo perché IIS non può dire in anticipo se quel nome di cartella risulterà nell'esecuzione di un file aspx o se fornirà un file HTML statico?

Aggiornamento: Ho persino provato a riordinare i documenti predefiniti che IIS cerca in modo che "default.aspx" fosse in cima alla lista, ad es.

  1. default.aspx
  2. default.ASP
  3. Default.htm
  4. ...

E sto ancora ricevendo lo stesso problema.

Aggiornamento:

Il gestore eventi viene solo essere stato licenziato una volta perché si traduce in un NullReferenceException. Ho effettuato alcune letture aggiuntive e so che ASP.NET attiva questi eventi per ogni richiesta, anche per i file CSS o JavaScript. Inoltre, l'oggetto della sessione non viene caricato per i file statici perché non esiste il codice che accede alla sessione, quindi non è necessario caricare l'oggetto. Anche così, la prima richiesta è la richiesta per la pagina web, che richiederà la sessione, e la sessione è nullo.

@DmytroShevchenko chiesto:

Prima aggiungere un controllo di guardia if (HttpContext.Current.Session != null) in modo che non ci sia NullReferenceException gettato. Quindi prova a vedere, forse l'evento verrà licenziato una seconda volta, con una sessione disponibile.

Codice modificato:

void Application_AcquireRequestState(object sender, EventArgs e) 
{ 
    if (HttpContext.Current.Session != null) 
    { 
     HttpContext.Current.Session["key"] = "value"; 
    } 
} 

ho impostato un punto di interruzione la dichiarazione if. Ho visto questo evento fuoco 4 volte:

  1. sessione è nullo sessione
  2. è nullo
  3. sessione non nullo
  4. sessione è nullo

Quando continuando ad eseguire il codice ogni volta, solo quando ha iniziato l'esecuzione di Default.aspx e il suo code-behind ho avuto una sessione disponibile. In realtà avevo la pagina web aperta in Firefox e stavo monitorando le richieste di rete. La prima richiesta era per http://localhost/Foo/.

Poi ho impostato un punto di interruzione in Application_BeginRequest come bene e ha ottenuto i seguenti eventi:

  1. BeginRequest
  2. AcquireRequestState
  3. BeginRequest
  4. AcquireRequestState
  5. BeginRequest
  6. AcquireRequestState (sessione non è null)
  7. Eseguire Default.aspx (/ Foo restituisce una risposta al browser)
  8. BeginRequest
  9. AcquireRequestState (sessione è ancora nulla)

al # 9 della richiesta AJAX nel browser per http://localhost:54859/8fad4e71e57a4caebe1c6ed7af6f583a/arterySignalR/poll?transport=longPolling&connectionToken=...&messageId=...&requestUrl=http%3A%2F%2Flocalhost%2FFoo%2F&browserName=Firefox&userAgent=Mozilla%2F5.0+(Windows+NT+6.1%3B+WOW64%3B+rv%3A41.0)+Gecko%2F20100101+Firefox%2F41.0&tid=4&_=1445346977956 è appeso in attesa di una risposta.

+0

cosa succede se si aggiunge il controllo 'if (HttpContext.Current.Session! = Null)' e mettere un debugger per la linea che mette un nuovo valore nella sessione? Forse questo evento viene eseguito due volte per questa richiesta? Una volta senza una sessione e una volta con una sessione? –

+0

Anche quando inserisco un punto di interruzione, la sessione è nullo. Ho trovato una soluzione alternativa, ma non una causa principale. Se la sessione è nullo, reindirizzo l'utente a /Default.aspx dove è disponibile la sessione. –

+0

Capisco che la sessione è nullo. Quello che sto chiedendo è se questo evento viene licenziato più di una volta per richieste a 'http: // localhost/Foo /'. –

risposta

8

Ho trovato a discussion sulle differenze tra la pubblicazione di una pagina tramite il suo URL esplicito e la pubblicazione di un documento predefinito.

Con MVC e WebAPI, è stato introdotto un nuovo HttpModule: ExtensionlessUrlHandler. Credo che l'evento che si attiva più volte (e solo una volta che la sessione sia disponibile) possa essere causato da questo modulo o da un'altra logica di reindirizzamento di ASP.NET che effettivamente reindirizza ASP.NET per gestire Default.aspx.

Inoltre, come lei stesso ha citato, questi eventi possono essere attivati ​​per richieste di file statici.

La linea di fondo è, non si deve fare affidamento sulla sessione disponibile ogni volta che viene generato l'evento. Ma è lecito ritenere che sia possibile accedere alla sessione almeno una volta quando si serve una pagina ASP.NET. Quindi, questo è come il codice dovrebbe essere simile:

void Application_AcquireRequestState(object sender, EventArgs e) 
{ 
    if (HttpContext.Current.Session != null) 
    { 
     HttpContext.Current.Session["key"] = "value"; 
    } 
} 
1

Quello che sta accadendo è che determinati eventi che si verificano prima di trasferire la richiesta alla pagina, attivano questo evento. Allo stesso modo, questo evento può essere generato da pagine diverse da ASPX. Penso che avete bisogno di fare un paio di cose:

  • set AutoEventWireUp-false nel codice della pagina (in default.aspx). Sembra strano e non correlato, ma a quanto pare questo può resolve your issue.
  • verificare per null. Veramente. Perché da tutti gli eventi, sei interessato solo a quegli eventi originati da una pagina ASPX (o simile) che in realtà hanno uno stato di sessione. Poiché ogni richiesta true da un utente crea sempre una sessione, è possibile semplicemente filtrare per questi senza preoccuparsi di perdere determinati eventi. Come hai visto, ad ogni ciclo, c'è sempre almeno un evento colpito che ha una sessione impostata.
  • utilizzare PostAcquireRequestState, è la cosa più naturale da utilizzare (o utilizzare PreRequestHandlerExecute), perché su tale evento, è garantito che tutti gli stati siano impostati e riempiti.
1

Credo che la vostra richiesta di URL non è contiene "aspx", giusto?

La versione IIS7 + ha la configurazione a tuute le esigenze non utilizzerà il "SessionStateModule" quando si pensa che il gestore della richiesta non è managedHandler

Quindi la soluzione è facile

Trova il tuo web.config, quindi aggiungere la proprietà

<modules runAllManagedModulesForAllRequests="true"> 
    .... 
</modules> 

runAllManagedModulesForAllRequests = "true" raccontare uso asp.net tutti i moduli in ogni caso

speranza utile

0

Quando la risorsa ha errore di compilazione quindi la sessione sarà nullo anche in Application_PostAcquireRequestState

Problemi correlati