Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>To answer the original question better:</p> <h2>Background</h2> <p>Every single page request spins up a new <code>Session</code> object and then inflates it from your session store. To do this, it uses the cookie provided by the client or a special path construct (for cookieless sessions). With this session identifier, it consults the session store and deserializes (this is why all providers but InProc need to be Serializable) the new session object.</p> <p>In the case of the InProc provider, merely hands you the reference it stored in the <code>HttpCache</code> keyed by the session identifier. <em>This is why the InProc provider drops session state when the <code>AppDomain</code> is recycled (and also why multiple web servers cannot share InProc session state</em>. </p> <p>This newly created and inflated object is stuck in the <code>Context.Items</code> collection so that it's available for the duration of the request.</p> <p>Any changes you make to the <code>Session</code> object are then persisted at the end of the request to the session store by serializing (or the case of InProc, the <code>HttpCache</code> entry is updated).</p> <p>Since <code>Session_End</code> fires without a current request in-fly, the <code>Session</code> object is spun up ex-nilo, with no information available. If using InProc session state, the expiration of the <code>HttpCache</code> triggers a callback event into your <code>Session_End</code> event, so the session entry is available, but is still a copy of what was last stored in the <code>HttpContext.Cache</code>. This value is stored against the <code>HttpApplication.Session</code> property by an internal method (called <code>ProcessSpecialRequest</code>) where it is then available. Under all other cases, it internally comes from the <code>HttpContext.Current.Session</code> value.</p> <h2>Your answer</h2> <p>Since the Session_End always fires against a null Context, you should ALWAYS use this.Session in that event and pass the HttpSessionState object down to your tracing code. In all other contexts, it's perfectly fine to fetch from <code>HttpContext.Current.Session</code> and then pass into the tracing code. <strong>Do NOT</strong>, however, let the tracing code reach up for the session context.</p> <h2>My answer</h2> <p>Don't use <code>Session_End</code> unless you know that the session store you are using supports <code>Session_End</code>, which it <strong>does</strong> if it returns <code>true</code> from <code>SetItemExpireCallback</code>. The only in-the-box store which does is the <code>InProcSessionState</code> store. It is possible to write a session store that does but the question of who will process the <code>Session_End</code> is kind of ambiguous if there are multiple servers.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload