Developer

Track your users with session objects

How do you track users accessing your Web site, since each request is an independent event, and IP addresses are not necessarily unique? With session objects it's possible. Find out how in this installment of the Active Server Page.


Session state is something often taken for granted with client/server applications. For instance, a Visual Basic program on a network is aware of whether the current user is logged in to the system and is capable of storing other information related to that user. In Web applications, all clients are disconnected from the server, and each communication with the server is a separate request and response. Not even the IP address is guaranteed to be unique to each client, since many users may access your Web site from a corporate network where they share a single IP address for many clients.

This lack of session state can create interesting problems for a Web application. Without some linkage between the client and the server, even maintaining a logged-in status can be difficult. To assist you with the maintenance of session state in Active Server Pages, Microsoft created the session object. You can use the session object within an ASP application to store information related to an individual user. The session object tracks the user by using a cookie that stores a Globally Unique Identifier (GUID). The ASP engine reads the cookie automatically in order to create the association between the current request and any existing sessions.

Saving information
Storing information in the session is easy. The session object uses a collection to store data that operates just like a dictionary object. If you’re not familiar with dictionary objects, don’t be concerned; the concept is easy. Each piece of data you want to store in the session is associated with a unique key value you assign as a string. To demonstrate how data can be stored, we’ll create two Web pages. The first page, named global.asa, performs a special purpose within an ASP application. The global.asa file contains event handlers that are fired whenever the application is started or stopped and whenever a session starts or ends. These events are declared by writing a subroutine named for the event: Application_OnStart(), Application_OnEnd(), Session_OnStart(), or Session_OnEnd(). The names are fairly self-explanatory. For our sample global.asa, we’ll write an event handler for the start of a session. This is the listing:
<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
       sub Session_OnStart()
             Session("sessionStarted") = now()
       end sub
</SCRIPT>

This routine contains a single line of code that stores the current date and time in the session object whenever a new session starts. The key value we have selected for this information is “sessionStarted”. To get this information back out of the session, we simply need to refer to the session object with the appropriate key value. In this case, the second page we have created will reference the session value and output it to the screen. This is test_session.asp:
<%@ LANGUAGE="VBScript" %>
<%  Option Explicit %>
<html>
<head>
<title>Sample Session</title>
</head>
<body>
<%
       Response.Write("<h2>Output From Session</h2><hr>")
       Response.Write("Session Id: ")
       Response.Write(cstr(Session.SessionId))
       Response.Write("<br>")
       Response.Write("Started at: ")
       Response.Write(Session("sessionStarted"))
%>
</body>
</html>

Put it to the test
The test_session.asp page will output the unique session ID and the date and time that the current session started. To see how sessions work, open two browsers and request the test_session.asp page. Each browser should have a different ID and time value. (The time value should differ by a few seconds unless you are very fast!) Now, open a new browser from one of the browsers by using Internet Explorer’s File | New | Window command ([Ctrl]N). When you open a new browser this way, the window shares data with the parent window. This window will display the same session ID and start time as the parent window. To see how the application knows which session each window represents, you can use the test_servervariables.asp page from our previous article (”Communicating with Request and Response objects”). Requesting this page from one of the browser windows will show the ASP session ID in the HTTP_COOKIE server variable.

The session object supports a number of properties and methods. The timeout property (Session.Timeout = x) allows you to set the amount of time in minutes (x) that the session will last. The default timeout for the session is 20 minutes. A session is considered active as long as the user is requesting pages. Once the user stops requesting pages, the timer starts. After the number of minutes defined by timeout has passed, the session is no longer valid, and the next request will create a new session. All the values in the old session will be lost. You can also manually force a session to expire by using the abandon method (Session.Abandon).

Not perfect
Sessions seem like a really great way to track information related to individual users. However, a few problems with sessions exist that you should keep in mind before you use the session object. The first issue is that the session object relies on cookies to track the session ID. If your users think cookies are evil, they may have them turned off, so your application won’t perform properly. I have often overcome this limitation by inserting an ISAPI filter on the Web server that rewrites the contents of the session cookie into the URL. This process of URL rewriting is not uncommon, but it does introduce more work on the server in order to process and rewrite all the links.

The second issue with the session object is that if your application is going to be placed on a Web farm, your load-balancing software must send all requests after the first one to the same server. That’s because the users’ data isn’t present on every server of the Web farm. This reduces the scalability of your application by not allowing each request to be dealt with by the fastest server. To avoid this, you can program your Web pages to be stateless (see ”Keep stateless Web pages in mind when planning your Web site”). In a future article, we’ll explain how to create your own session object that allows stateless Web pages but gives you the same benefits as the built-in session object.

What about .NET?
In ASP.NET, the session-handling capabilities have been greatly improved. The ASP.NET sessions have a property called cookieless that automatically deals with the URL rewrite issue. In addition, the ASP.NET sessions have three modes (inproc, stateserver, and sqlserver). The inproc option works similarly to the current ASP sessions. The stateserver and sqlserver options allow a Web farm to share session data using either a database or a special server running the process ASPState, which allows the sharing of session state data. These values can be set in the config.web XML file within ASP.NET. The file might look something like this:
<configuration>
  <sessionstate
      mode="inproc"
      cookieless="false"
      timeout="20"
      sqlconnectionstring="data source=127.0.0.1;user id=sa;password="
      server="127.0.0.1"
      port="42424"
  />
</configuration>

The sqlconnectionstring property is used when the mode is set to sqlserver. The server and port properties are used when the mode is set to stateserver and indicate the server and port of the machine running the ASPState process.

Summary
Sessions are a great tool within Active Server Pages. By referencing the session object, you can store just about any user-related information to use repeatedly on your ASP pages. There are some issues to consider with sessions and high-traffic Web sites. However, in the new ASP.NET, you can implement solutions to these issues by simply making configuration file changes. The more you understand about how sessions work, the better equipped you will be to make the right configuration choices for your environment. In our next article, we’ll explore the application object, which allows you to store information that’s shared by all sessions.

Do you use objects?
Have you successfully implemented session objects? What obstacles have you run into? Send us an e-mail with your suggestions and experiences.

Editor's Picks

Free Newsletters, In your Inbox