In my previous column, ”Track your users with Session objects,” I explained how to use the Session object to store user-specific information. Active Server Pages also include an Application object, which represents the whole Web application. The Web application can be the entire directory structure of your Web site, or it can be divided with each directory or virtual directory representing a separate application. An application is defined by the presence of the global.asa file.
The Application object is handy for representing data that is the same for all users of the Web site. For the most part, the Application object works just like the Session object. You can retrieve information from the Application object by using the key you set up when storing the data. This takes the form of Application(“keyname”) and returns the data stored in that key.
An example
Let’s return to the global.asa we created when we were discussing the Session object. This time, we’ll add some functionality to use the Application object. Listing A shows our new global.asa.
Listing A
<SCRIPT LANGUAGE=”VBScript” RUNAT=”Server”>
sub Application_OnStart()
‘Initialize our user counter
Application(“userCount”) = cstr(0)
end sub
sub Session_OnStart()
Session(“sessionStarted”) = now()
on error resume next
‘Lock the application to prevent contention
Application.Lock()
‘Increase the user counter
Application(“userCount”) = cstr( _
cint(Application(“userCount”)) + 1)
‘Unlock immediately so it can be read by other requests
Application.UnLock()
on error goto 0
end sub
sub Session_OnEnd()
on error resume next
Application.Lock()
Application(“userCount”) = cstr( _
cint(Application(“userCount”)) – 1)
Application.UnLock()
on error goto 0
end sub
</SCRIPT>
A closer look
This global.asa file now contains code for two additional event handlers, Session_OnEnd() and Application_OnStart(). We have also added code to the Session_OnStart.
Let’s examine the code beginning with the Application_OnStart() routine. This event handler contains only one line of code, which looks identical to our Session object code. We are placing a counter value in the Application object using the key “userCount”. The value will be set to zero to start the application since at that point, there will be no users of the system. The Application_OnStart() event handler is fired every time the Web server is restarted or the global.asa file is modified.
The next set of new code is in the Session_OnStart() event handler. Here, we are going to update the application value for “userCount” by incrementing the counter by 1 each time a new session starts. Notice we use the Application.Lock() statement before we set the value. This is necessary when dealing with the Application object since it’s a shared resource. Multiple sessions can read the Application object at any time, but only a single process can update the value. To prevent issues with multiple updates, you must lock the Application object before any of the values can be updated. During this time, other processes cannot access values in the Application object, so you must not call the Lock method until you are ready to update the value. The next line of code increments the counter, and the line immediately following the update unlocks the Application object.
Two other items in the code require explanation. First is the use of the on error resume next statement. For those not familiar with Visual Basic or VBScript, this is VBScript’s error handling method. It is not very robust, but it does allow the code to continue running in the event of a problem. I always place the on error statement in front of the application Lock methods to make sure that the Application object is unlocked. Otherwise, an errant piece of code could leave the Application object inaccessible.
The on error goto 0 statement turns off the error-handling routine. When writing code like this, comment out the error handler until you have verified that your code works as expected.
The second item of note in the Session_OnStart() event handler is the use of conversion functions. Notice that in the increment statement, I explicitly convert the data to an integer before the addition operation, and then I explicitly convert it back to a string before storing it back in the Application object. VBScript doesn’t require this, since all values are variants, but I consider it to be a good practice. By making a habit of converting values when you are performing operations, you will avoid a lot of irritating problems that can arise from the automatic conversions that VBScript will perform.
The last section of new code is the Session_OnEnd() event handler. This code doesn’t require a lot of explanation since it is a duplicate of the increment code in the Session_OnStart() routine.
Testing
To test the Application object code, I’m going to reuse another file from our article on Session objects, test_session.asp, which appears in Listing B. It has been modified to output the information about the current users of the application by accessing the Application object.
Listing B
<%@ 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”))
Response.Write(“<br>”)
Response.Write(“There are “)
Response.Write(Application(“userCount”))
Response.Write(“ sessions currently open.”)
%>
</body>
</html>
As you can see from this code, accessing the Application object is identical to accessing the Session object. Open multiple copies of your browser, and the number of sessions count should increment for each one. The count will not decrease until the session timeout occurs (20 minutes, by default).
If you want to decrease the count manually, you can create another page and place a single command on that page: Session.Abandon(). The Abandon method will cause Session_OnEnd() to fire and decrease the count. You must use the same browser windows in order to abandon that particular session. If you request any pages with the browser after calling the page with the Abandon method, it will create a new session, and the count will appear to be the same. Instead, call the abandon page with one browser and refresh the screen of another to see the count change.
Two additional methods for the Application object might prove useful to you: Application.Contents.Remove and Application.Contents.RemoveAll. The Remove method takes a key name and removes that value from the Application object. The RemoveAll method removes all values from the Application object.
Where does this object fit in?
This type of counter is okay for demonstrating the Application object, but it lacks the ability to work in a server farm environment where the count you store in the Application object would reflect only the number of users currently on the individual Web server. The Application object is great for storing shared data, and you should definitely keep it in mind when developing in ASP. Generally, I use the Application object to buffer data that is frequently accessed from the database. By buffering information that doesn’t change very often, you can avoid a lot of calls from the Web server to the database. I’ll demonstrate that buffering in a future article.
A word on ASP.NET
I want to make a slight correction to the previous article, which covered some of the functionality available for the Session object in the new ASP.NET. One of the reasons I don’t like dealing with beta software is that it changes too often, and what you learn often changes as well. In the last article, I discussed the settings for the Session object that you place in the config.web file—and of course, that has changed with the beta 2 release of the .NET SDK.
In the newest beta version, the file used for configuring your Web application is now named web.config. Apparently, Microsoft decided this convention was better for the configuration files. As far as I know, at this time, the entries and syntax are the same as those I described in the previous article.