Caching in Classic ASP
page 1 of 1
Published: 10 Oct 2006
Unedited - Community Contributed
Abstract
In this article, Tony demonstrates a simple technique for caching classic ASP pages. This technique caches pages based on URL (including querystring), thus allowing for true caching of dynamic pages.
by Tony Alicea
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 27949/ 35

Introduction

ASP.NET has inherent caching capabilities. However, what if you are working with a legacy classic ASP application, and need to cache a particularly intensive page? Perhaps the page pulls a very large set of data from a database, or does a good deal of calculations. If the results don't change often, it would be nice to able to cache that pages output and deliver the cached result to the next user that comes along. Here we demonstrate a simple technique for doing so.

The goal of the technique is to meet the following criteria:

1) A cached page of the final HTML after the ASP page runs is generated and stored on the server. This would then be automatically delivered to the user instead of the ASP page.

2) The caching routine should allow for the storage of a different cached page per querystring value. Thus, for example, if we are passing an ID in a querystring to the ASP page, one cached page should be generated for each ID passed, thus ensuring that even dynamic pages will be cached properly.

3) The caching routine should be simple enough that it can be encapsulated into server-side includes and placed onto any classic ASP page.

We will approach this technique as two files. One to be referenced as a server-side include at the top of any classic ASP page, and one to be referenced at the bottom. The first file we will call "ASPCacheTop.asp" and the second "ASPCacheBottom.asp".

ASPCacheTop.asp

Let's take this file piece by piece:

Listing 1

<%
 Server.ScriptTimeOut = 300 
 
 'Declare variables
 Dim strResponse
 Dim objTextStream
 Dim objHTTP
 Dim strDynURL, strDynURL2
 Dim cache_FILEOBJ, cache_FILETXT
 
 'Get URL
 strDynURL = Request.ServerVariables("URL") & _
"?" & Request.ServerVariables("QUERY_STRING")
 strDynURL2 = strDynURL
 
 'Generate file name based on URL
 strDynURL = Replace(strDynURL, "&""_")
 strDynURL = Replace(strDynURL, "=""-")
 strDynURL = Replace(strDynURL, "/""")
 strDynURL = Replace(strDynURL, "?""$")
 strDynURL = Replace(strDynURL, ".""@")

Our first step is to increase the script timeout. You may want to do this if the ASP page takes a long time to execute. This is only important the first time the page runs - after the page caches the cached result will simply be read from the cache file. We then declare all the variables we will use.

The next step is to grab the URL and querystring for the page we are currently running. We do this by grabbing these values from the Request.ServerVariables collection. We combine the two into one string.

After this, we generate a "saveable" name for the text file. The URL and querystring contain characters which cannot be used in the name of a file, so we replace those characters with others. So, for example, if the URL was "www.theabstractionpoint.com/cachingclassicasp.asp?ID=2&Category=1", after replacing we would have a string that looks like "www@theabstactionpoint@comcachingclassicasp@asp$ID-2_Category-1". This string could then be saved as the name of a text file (i.e. "www@theabstactionpoint@comcachingclassicasp@asp$ID-2_Category-1.txt"). This will be the name of our cached file. By basing the file name on the entire querystring, we will cache a different file for each value passed in the querystring.

Moving on, we will actually begin the caching process:

Listing 2

'Create file system object
 set cache_FILEOBJ = Server.CreateObject("Scripting.FileSystemObject")
 
 'check the "expires" file, which tells us if we've tried to start caching
 if not cache_FILEOBJ.FileExists(Server.Mappath(
 _"cachefiles/" & strDynURL & "_started.txt")) then
 
 'create the "expires" file, which simply 
 'tells us that we've tried to start caching
 Set cache_FILETXT = _
 cache_FILEOBJ.CreateTextFile(Server.Mappath( _
"cachefiles/" & strDynURL & "_started.txt"), True)

We first declare a file system object. We then run an important check. The first step to caching a file will be to write an empty text file which tells us that we have begun the caching process. Why? Suppose the first user comes in and requests the ASP page. Now suppose while that page is caching another user comes in requesting the same page. We don't want multiple attempts to the write the cache file at the same time. So, we first write a quick empty text file to let us know that the process has already started. If the process has already started, we won't try to cache again. We name this empty file the same as the cache file itself, but place "_started" on the end of the filename.

The other very important reason is to prevent an infinite loop. We have just requested a file, say it is called "cachingclassicasp.asp". We will very shortly be requesting that page again (through the ASP XMLHTTP object). If we didn't somehow mark that we had started the caching process, we would find ourselves in an infinite loop.

Note, too, that in the Server.Mappath we assume you want to place your cache files in a directory called "cachefiles". You can change this folder name to suit your own needs. Just be certain ASP has permission to write files to the folder.

If this file does not exist (i.e. nothing has started caching yet), then we need to run the actual caching process:

Listing 3

'grab the contents of the page
 Set objHTTP = Server.CreateObject("MSXML2.XMLHTTP")
 objHTTP.open "GET""http://www.theabstractionpoint.com" & strDynURL2, false
 objHTTP.send()
 'output results to screen 
 response.write objHTTP.responseText
 
 'create cache text file
 Set cache_FILETXT = _
 cache_FILEOBJ.CreateTextFile(Server.Mappath( _
"cachefiles/" & strDynURL & ".txt"), True)
 
 'save results
 cache_FILETXT.WriteLine objHTTP.responseText
 
 'clean up
 cache_FILETXT.Close()
 set objHTTP = nothing
 response.end

Here we have the meat of the caching routine. We declare an XMLHTTP object which we then use to make an HTTP request to the page we are trying to cache. You will need to replace "http://www.theabstractionpoint.com" with the address of your own site. Recall that the variable "strDynURL2" held a copy of the original URL (i.e. name of the page) and querystring being requested.

We then make the request, and response.Write the response (which will be the HTML of the page). We response.Write so that the user will actually see the page after it is cached.

We then create the text file in our "cachefiles" directory using the adjusted text file name. Then, we write to the file the HTML we got when the page was done executing. Finally, we close the file and "response.end", ending the execution of the page. Thus, the first time someone requests the page (with particular querystring values), the empty "started" file will be written, the ASP page will be requested via the XMLHTTP object and the results outputted and saved to the cache file.

Now, what if the "started" file already existed? The following occurs:

Listing 4

else
 'otherwise, we've already cached, so grab the contents of the cache file and output
 if cache_FILEOBJ.FileExists( _
Server.Mappath("cachefiles/" & strDynURL & ".txt")) then
      set cache_FILETXT = _
 cache_FILEOBJ.OpenTextFile(Server.Mappath( _
"cachefiles/" & strDynURL & ".txt"), 1)
      response.write cache_FILETXT.ReadAll()
      cache_FILETXT.Close()
      response.end
 
 else
 'if we haven't already requested the page for caching, 
 'then actually run the code for the page
 %>

If the cache file has been started, check to see if it is finished (i.e. the cache file exists). If it does exist, grab the contents of the cache file and output to the screen. Otherwise, just run the ASP file like normal. Since this file will go at the very top of your ASP page, the code of your page will be below the final "else".

ASPCacheBottom.asp

The second page, which should be a server-side include at the bottom of your page, couldn't be any simpler. We just need to close out the IF-statements we started in the top file. So this file is nothing more than:

Listing 5

<%
 end if
 end if
 %

Usage

Thus we have a simple and easy to implement caching routine for any classic ASP page. If you want to cache any page, just save these two files, give ASP permission to write to the folder you chose to store your cache files in, and then update your ASP page as follows:

Listing 6

<!--#include file="ASPCacheTop.asp" -->
 <%
 YOUR HTML AND ASP CODE
 %>
 <!--#include file="ASPCacheBottom.asp" -->

The only thing left would be the question: when and how do we clear the cache files? That is up to you. You could have a job running on the server that regularly empties or archives the folder where the cache files live. Or you could update the caching process to write a "expires" file which holds the date the cache file should expire. When you check if the cache file exists, you could then check that file to see if the cache file has expired and should be rewritten or not.

Once you implement everything, you get the rewards of far less load on your server and pages being delivered lightening fast!

NOTE: This is a reprint of an article originally published here

 



User Comments

Title: Sample   
Name: sample
Date: 2008-08-13 6:57:10 AM
Comment:
Title: ASP Cache
Name: Mohit
Date: 5/27/2008 12:00:46 AM
Comment:
Good
Title: GOOD
Name: jansi
Date: 6/8/2007 1:29:57 AM
Comment:
good
Title: RE: Programmer
Name: Tony Alicea
Date: 10/24/2006 11:39:32 AM
Comment:
It's true that caching to the filesystem is a slower option. However, it depends on your requirements. If you are caching an application, which may not have continuous use, session or application state may not be viable as it will time out. A persistent store allows for caching which is always available, with the goal of avoiding recaching as much as possible.

Storing on the file system also allows for a reviewable cache - a sort of historical archive. It might be faster to cache in a database, if you have a database with the required space available. This methodology could easily be updated to do so.
Title: Programmer
Name: Laverrod
Date: 10/24/2006 10:48:44 AM
Comment:
Is it wise to cache it in this way? Opening a textfile and closing it also takes time...
Title: ASP Cache   
Name: Mohit
Date: 2008-05-27 12:00:46 AM
Comment:
Good
Title: RE: Programmer   
Name: Tony Alicea
Date: 2006-10-24 11:39:32 AM
Comment:
It's true that caching to the filesystem is a slower option. However, it depends on your requirements. If you are caching an application, which may not have continuous use, session or application state may not be viable as it will time out. A persistent store allows for caching which is always available, with the goal of avoiding recaching as much as possible.

Storing on the file system also allows for a reviewable cache - a sort of historical archive. It might be faster to cache in a database, if you have a database with the required space available. This methodology could easily be updated to do so.
Title: Programmer   
Name: Laverrod
Date: 2006-10-24 10:48:44 AM
Comment:
Is it wise to cache it in this way? Opening a textfile and closing it also takes time...

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


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