AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=520&pId=-1
Detecting ASP.NET Session Timeouts
page
by Robert Boedigheimer
Feedback
Average Rating: 
Views (Total / Last 10 Days): 187734/ 96

Background and How Sessions Are Implemented

ASP.NET provides a framework for storing data that is specific to an individual user with the Session object. A page can add information to the Session object, and any other page can then retrieve the information for the same user. In order to preserve server memory, ASP.NET implements a rolling timeout mechanism which discards the session information for a user if no request is seen within the timeout period (default 20 minutes which is reset with each request).

It is often useful in an ASP.NET site to know for a particular request if the user’s session information is still intact (that a timeout has not occurred). One common need is to be able to inform the user why they lost their session information, by redirecting to a page that describes the timeout amount and how to avoid the problem in the future.  Without this technique it is difficult to know if a session variable is not present whether it was never set properly or the user waited too long between requests.  Many ASP.NET developers just reference session variables without first ensuring they are actually present.  This causes the infamous "Object reference not set" exception, which can be very difficult to trace back to the specific cause.  Code that checks for null session values is useful, but does not help the developer understand if it was never set properly or if the user just lost her session.  This technique can help to clearly identify that the user waited to long between requests and the session storage information was removed.

This is not the same as using the Session_OnEnd event which can be used for cleanup, logging, or other purposes.  It is also not for enforcing security on a web site. 

How Sessions Are Implemented

Since the HTTP protocol used by web browsers to request files from web servers is stateless, ASP.NET needs to determine which requests were from the same user. The primary mechanism utilizes a non-persistent cookie that is issued by the web server that contains a session id value. The id provided by this cookie is the key used to index into the session infrastructure to access the user's specific data. The session framework is implemented by the HTTP module System.Web.SessionState.SessionStateModule, which executes before the .aspx page events. The module uses the EnableSessionState attribute from the @Page directive to determine if it must retrieve the user’s session information (and whether it needs to write out changes when the request is complete). If the EnableSessionState attribute is true (which it is by default), the module retrieves all of the user’s session information and sets the Session property of the Page class to an instance of the HttpSessionState class. This article focuses on the cookie mechanism, although a cookie-less method of sessions is implemented in ASP.NET (the session id is embedded in the URL string). The Session information can be stored in-process (default, stores in web server memory), with a state service, or a SQL Server database. This article will focus on the in-process storage, but the technique applies to all three locations.

Example User Session

A user opens a browser instance and requests an ASP.NET page from a site. If the EnableSessionState attribute is true, the session module adds the ASP.NET_SessionId cookie to the response. On subsequent requests to the same web site, the browser supplies the ASP.NET_SessionId cookie which the server side module uses to access the proper user’s information.

Detecting Timeouts

The ASP.NET HttpSessionState class provides a useful IsNewSession( ) method that returns true if a new session was created for this request.  The key to detecting a session timeout is to also look for the ASP.NET_SessionId cookie in the request.  If this is a new session but the cookie is present, this indicates a timeout situation.  In order to implement this effectively for an entire web site, it is useful to utilize the “Base Page” concept described in a previous article.

basePageSessionExpire.cs

 public class basePageSessionExpire : System.Web.UI.Page
 {
    public basePageSessionExpire()
    {
    }


  override protected void OnInit(EventArgs e)
  {
       base.OnInit(e);


   //It appears from testing that the Request and Response both share the 
   // same cookie collection.  If I set a cookie myself in the Reponse, it is 
   // also immediately visible to the Request collection.  This just means that 
   // since the ASP.Net_SessionID is set in the Session HTTPModule (which 
   // has already run), thatwe can't use our own code to see if the cookie was 
   // actually sent by the agent with the request using the collection. Check if 
   // the given page supports session or not (this tested as reliable indicator 
   // if EnableSessionState is true), should not care about a page that does 
   // not need session
   if (Context.Session != null)
   {
    //Tested and the IsNewSession is more advanced then simply checking if 
   // a cookie is present, it does take into account a session timeout, because 
   // I tested a timeout and it did show as a new session
    if (Session.IsNewSession)
    {
     // If it says it is a new session, but an existing cookie exists, then it must 
   // have timed out (can't use the cookie collection because even on first 
   // request it already contains the cookie (request and response
     // seem to share the collection)
     string szCookieHeader = Request.Headers["Cookie"];
     if ((null != szCookieHeader) && (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
     {
      Response.Redirect("sessionTimeout.htm");
     }  
    } 
   }
  }
}

sessionTimeout.htm

This can be any page on the site, example just redirects to this page so just show a simple "A timeout has occurred" message for this article.

Each other page on the site just needs to derive from this new base page instead of the default System.Web.UI.Page, so just change the line in the code behind class from ": System.Web.UI.Page" to ": basePageSessionExpire".  Each page should also set the EnableSessionState variable as appropriate:

  • false - page request does not access any session information (the base page uses this to know that it does not need to check for timeout on this request since it does not require session information) 
  • ReadOnly - page request uses session information but does not modify it
  • true - page request reads and updates session information

Conclusion

It is often useful to know for a given request whether the user’s session information is still present.  The technique demonstrated is a straightforward implementation that can be easily applied to an entire web site that uses cookie based ASP.NET Session objects. 

Send comments or questions to robertb@aspalliance.com.



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-19 4:43:15 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search