[ACCEPTED]-HttpContext.Current.Session" vs Global.asax "this.Session-global-asax

Accepted answer
Score: 18

To answer the original question better:

Background

Every 43 single page request spins up a new Session object 42 and then inflates it from your session store. To 41 do this, it uses the cookie provided by 40 the client or a special path construct (for 39 cookieless sessions). With this session 38 identifier, it consults the session store 37 and deserializes (this is why all providers 36 but InProc need to be Serializable) the 35 new session object.

In the case of the InProc 34 provider, merely hands you the reference 33 it stored in the HttpCache keyed by the session identifier. This is why the InProc provider drops session state when the AppDomain is recycled (and also why multiple web servers cannot share InProc session state.

This 32 newly created and inflated object is stuck 31 in the Context.Items collection so that it's available 30 for the duration of the request.

Any changes 29 you make to the Session object are then persisted 28 at the end of the request to the session 27 store by serializing (or the case of InProc, the 26 HttpCache entry is updated).

Since Session_End fires without 25 a current request in-fly, the Session object is 24 spun up ex-nilo, with no information available. If 23 using InProc session state, the expiration 22 of the HttpCache triggers a callback event into your 21 Session_End event, so the session entry is available, but 20 is still a copy of what was last stored 19 in the HttpContext.Cache. This value is stored against the 18 HttpApplication.Session property by an internal method (called 17 ProcessSpecialRequest) where it is then available. Under all 16 other cases, it internally comes from the 15 HttpContext.Current.Session value.

Your answer

Since the Session_End always fires 14 against a null Context, you should ALWAYS 13 use this.Session in that event and pass 12 the HttpSessionState object down to your 11 tracing code. In all other contexts, it's 10 perfectly fine to fetch from HttpContext.Current.Session and then pass 9 into the tracing code. Do NOT, however, let the 8 tracing code reach up for the session context.

My answer

Don't 7 use Session_End unless you know that the session store 6 you are using supports Session_End, which it does if it 5 returns true from SetItemExpireCallback. The only in-the-box store 4 which does is the InProcSessionState store. It is possible 3 to write a session store that does but the 2 question of who will process the Session_End is kind 1 of ambiguous if there are multiple servers.

Score: 11

Global.asax implements HttpApplication - which 23 is what you are talking to when you call 22 this from within it.

The MSDN documentation for 21 HttpApplication has details on how you can get hold of 20 it in an HttpHandler for example, and then 19 get access to the various properties on 18 it.

HOWEVER

Your application can create multiple 17 instances of HttpApplication to handle parallel 16 requests, and these instances can be re-used, so 15 just picking it up somehow isn't going to 14 guarentee that you have the right one.

I 13 too would also add a note of caution - if 12 your application crashes, there's no guarentee 11 that session_end is going to be called, and 10 you'll have lost all the data across all 9 sessions, clearly not a good thing.

I agree 8 that logging on every page is probably not 7 a great idea, but perhaps a halfway house 6 with some asynchronous logging happening 5 - you fire details off to a logging class, that 4 every now and then logs the details you 3 are after - still not 100% solid if the 2 app crashes, but you're less likely to lose 1 everything.

Score: 4

I think you already answered your own question: usually 18 the Session property in Global.asax and 17 HttpContext.Current.Session are the same 16 (if there is a current request). But in 15 the case of a session timeout, there is 14 no active request and therefore you can't 13 use HttpContext.Current.

If you want to access 12 the session from the method called by Session_End, then 11 pass it as a parameter. Create an overloaded 10 version the Log() method, which takes a 9 HttpSessionState as a parameter, then call 8 Tracker.Log(this.Session) from the Session_End 7 event handler.

BTW: you are aware that you 6 can not rely on the session end event in 5 any case? It will only work as long as you 4 have the session state in-process. When 3 using SQL server or StateServer to mange 2 the session state, the session end event 1 will not fire.

Score: 3

The Session_End event is raised only when the sessionstate mode is set 3 to InProc in the Web.config file. If session mode is set 2 to StateServer or SQLServer, the event is not raised.

use 1 Session["SessionItemKey"] to get the session value.

Score: 0

Okay, I am in the same problem to track 13 the session activity. Instead of using session_end 12 event, I have implemented the IDisposable 11 interface and destructor to my sessiontracker 10 class. I have modified the Dispose() method 9 to save the session activity to DB. I invoked 8 the method obj.Dispose() when a user clicks 7 the logout button. If user closed the browser 6 by mistake, then GC will call the destructor 5 while cleaning the objects (not immediately 4 but for sure it will call this method after 3 sometime). The destructor method internally 2 execute the same Dispose() method to save 1 the session activities into DB.

-Shan

Score: 0

Session is available in your Global.asax 2 file, during the Session_Start event. Maybe 1 wait until this point to do stuff?

More Related questions