Determine if ASP.NET's Session Object has timed out

ASP.NET allows you to pass data, specific to a given user, between web pages using the Session object as it did in prior versions of ASP. This works great since you can store anything in it. My advise, though, is don't use it. It won't work on web farms and has problems when multiple web sites are hosted in virtual directories under IIS.

Also, ASP.NET uses a rolling timeout feature which discards a user's session information if no request is seen within the timeout period. The default, set in the web.config, is 20 minutes which is reset with each request.

If the session times out and you try to reference a previously set value in code without checking first, you get the "Object reference not set" exception. Thus, always check as shown:

    'Add a value to the Session object.
    Session.Add("MyValue", "ABC")
    ...
    If Session.Item("MyValue") Is Nothing Then
        strValue = "XYZ" 'default value
    Else
        strValue = Session.Item("MyValue").ToString()
    End If

So, why not just increase the timeout in the <system.web\sessionState> item in the web.config? Because you may not want to increase the timeout period for security reasons and other things can still pull the rug out from the session object. For example, when running IIS 6 and the idle timeout property of the worker process causes the entire process to end. So, you need to know when session timeouts occur.

First, here is how the session is implemented. The HTTP protocol used by web browsers to get files from web servers is stateless but ASP.NET needs to know which requests came from the same user. The main way to do this is though a non-persistent cookie, issued by the web server, that contains a Session ID value. The ID is used to to access the user's specific data.

The session object is implemented by the HTTP module System.Web.SessionState.SessionStateModule, which executes before any of the .aspx page's events. SessionStateModule uses the EnableSessionState attribute from the @Page directive to see if it needs to get the user’s session information. If EnableSessionState is true, the default, the module gets all of the user’s session data and sets the Session property of the Page class to an instance of the HttpSessionState class.

Note that a cookie-less method of sessions can be implemented in ASP.NET where the session ID is embedded in the URL. The Session information can be stored in-process in the web server's memory, the default, with a state service, or a SQL Server database. This page discusses in-process storage, but applies to the other methods as well.

Here's what happens when a user requests an ASP.NET web page. If the page's EnableSessionState value 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.

The ASP.NET HttpSessionState class has an IsNewSession method that returns True if a new session was created for this request. But to detect a session timeout, you also must look for the ASP.NET_SessionId cookie in the request because you want to know if it is a timeout and not a new session as when the application starts. If this is a new session but the cookie is present, the session has timed out.

You need to do this check in every page that uses the session object. An easier way is to have all of your pages inherit from a base page and perform the check there.

Inheriting from a base page instead of System.Web.UI.Page:

    Public Class MyPage
    Inherits MyBasePage
    ...
    End Class

Base page code to check for session timeouts:

    Public Class MyBasePage
    Inherits System.Web.UI.Page
    ...
    Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
        ' Call the base OnInit method.
        MyBase.OnInit(e)

        If Not Context.Session Is Nothing Then
            If Session.IsNewSession Then
                Dim strCookieHeader As String = Request.Headers("Cookie")

                If Not strCookieHeader Is Nothing Then
                    If strCookieHeader.ToUpper().IndexOf("ASP.NET_SESSIONID") >= 0 Then
                        'On timeouts, redirect user to timeout page.
                        Response.Redirect("MyTimedOutPage.aspx")
                    End If
                End If
            End If
        End If
    End Sub

    End Class

When multiple web sites are hosted in virtual directories. The ASP.NET_SessionId cookie has a default path of "/" which means that the browser will send it to ALL virtual directories hosted in the same IIS site. One way to solve this is to adjust the cookie created by ASP.Net to set the path to the virtual directory for the particular application. Then the browser will not send it to other virtual directories. The cookie can be adjusted in the Global.asax file.

Adjusting the path of the ASP.NET_SessionId cookie:

    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' Fires when the session is started
    Dim oCookie As HttpCookie = Response.Cookies("ASP.NET_SessionId")

    If Not oCookie Is Nothing Then
        oCookie.Path = Request.ApplicationPath.ToLower()
    End If

    End Sub



About TheScarms
About TheScarms


Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page


© Copyright 2024 TheScarms
Goto top of page