Programming Microsoft ASP.NET 4 - Dino Esposito [358]
For Session_End to fire, the session state has to exist first. That means you have to store some data in the session state and you must have completed at least one request. When the first value is added to the session dictionary, an item is inserted into the ASP.NET cache—the aforementioned Cache object that we’ll cover in detail in the next chapter. The behavior is specific to the in-process state provider; neither the out-of-process state server nor the SQL Server state server work with the Cache object.
However, much more interesting is that the item added to the cache—only one item per active session—is given a special expiration policy. You’ll also learn more about the ASP.NET cache and related expiration policies in the next chapter. For now, it suffices to say that the session-state item added to the cache is given a sliding expiration, with the time interval set to the session timeout. As long as there are requests processed within the session, the sliding period is automatically renewed. The session-state module resets the timeout while processing the EndRequest event. It obtains the desired effect by simply performing a read on the cache! Given the internal structure of the ASP.NET Cache object, this evaluates to renewing the sliding period. As a result, when the cache item expires, the session has timed out.
An expired item is automatically removed from the cache. As part of the expiration policy for this item, the state-session module also indicates a remove callback function. The cache automatically invokes the remove function which, in turn, fires the Session_End event.
Note
The items in Cache that represent the state of a session are not accessible from outside the system.web assembly and can’t even be enumerated, because they are placed in a system-reserved area of the cache. In other words, you can’t programmatically access the data resident in another session or even remove it.
Why Does My Session State Sometimes Get Lost?
Values parked in a Session object are removed from memory either programmatically by the code or by the system when the session times out or it is abandoned. In some cases, though, even when nothing of the kind seemingly happens, the session state gets lost. Is there a reason for this apparently weird behavior?
When the working mode is InProc, the session state is mapped in the memory space of the AppDomain in which the page request is being served. In light of this, the session state is subject to process recycling and AppDomain restarts. The ASP.NET worker process is periodically restarted to maintain an average good performance; when this happens, the session state is lost. Process recycling depends on the percentage of memory consumption and maybe the number of requests served. Although it’s cyclic, no general estimate can be made regarding the interval of the cycle. Be aware of this when designing your session-based, in-process application. As a general rule, bear in mind that the session state might not be there when you try to access it. Use exception handling or recovery techniques as appropriate for your application.
Consider that some antivirus software might be marking the web.config or global.asax file as modified, thus causing a new application to be started and subsequently causing the loss of the session state. This holds true also if you or your code modify the timestamp of those files or alter the contents of one of the special folders, such as Bin or App_Code.
Note
What happens to the session state when a running page hits an error? Will the current dictionary be saved, or is it just lost? The state of the session is not saved if, at the end of the request, the page results in an error—that is, the GetLastError method of the Server object returns an exception. However, if in your exception handler you reset the error state