WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Learning ASP.NET for the ASP Developer - Part 3
Pages: 1, 2

Doing Something in ASP.NET Which is Cumbersome in Classic ASP

I don't want to leave you with the impression that ASP.NET's power lies in its ability to simplify, reduce, and better structure your code only. So, in this section, I am going to outline an application that would be very cumbersome in classic ASP yet would be something you might consider using immediately on your site. The feature I would like to discuss is Page or Output Caching.

Suppose you have a page on your site which is populated from a database. Each time this page is requested, the corresponding records are pulled out before the page is delivered. With Page Caching, though, the output is cached so that when subsequent requests are made, the time-consuming database extraction is avoided, and the page is served from the cache, thus speeding up its delivery. Even if you have inefficiently coded your page, caching the page output will minimize performance degradation.

In ASP.NET, to cache a page's output, you simply specify the OutputCache directive after the Page directive:

<%@ Page Language="C#" %>
<%@ outputcache duration="60" varybyparam="None" %>

The OutputCache directive has two attributes: duration and varybyparam. The duration attribute specifies in seconds how long the page output is cached after it's first request. The first request after this time will cause the page to be re-evaluated, and then it will be re-cached. The duration is specified in seconds. So, in this example, the page will be cached for one hour after it's first requested.

The second attribute, varybyparam, allows the page to be cached based on query string parameters. Very often, you will have a page whose content depends on what is passed on the querystring. In these kinds of pages, it is pointless to simply cache the page without knowing what is on the querystring, since the code will not know how to extract records from the database. The varybyparam attribute allows you to cache the page based on a subset of the parameters passed on the querystring. For instance, suppose you have a page which reads a parameter "City" on the querystring and then displays some output related to that city. Then, if varybyparam= "City" and a request is made to http://YOUR_PAGE?City=Dallas, then the page output for Dallas will be cached so that subsequent requests for Dallas will not have to make the database call. Thus, multiple versions of this page corresponding to different cities is cached.

In classic ASP, on the other hand, to cache a database extraction of records, you use Application variables. Then, each time the page is requested, a check against another application variable has to be made to determine whether the caching duration is over. If the request is made before the duration is over, then the records are taken from the application variables instead of making an expensive database call. At any rate, though, you have to make some modifications in the code's logic flow to introduce the application variables. In ASP.NET, on the other hand, all you have to do is specify the OutputCache directive without affecting the rest of the code, thus making it a snap to cache your page's output.

For pages whose output does not depend on the querystring, the varybyparam attribute must be set to None. This attribute is mandatory; hence, if there is no dependence on the querystring, you have to still set it to None.

The above discussion is just an outline of the Outputcache directive. For more details, please refer back to ASP.NET in a Nutshell.

While page caching is certainly attractive, by itself, it's not particularly useful. The reason is that if the information in the database has changed in the time interval between the first request to the page and the end of the cache duration, then the new information is not reflected until the caching duration has elapsed. You can, of course, force a re-cache by opening your page and re-saving it. However, this solution is not elegant. It would be better to have a way to clear the page from cache on demand. So, in the remainder of this section, I will outline a method which will allow you to clear a page from cache using a browser. This technique has the advantage that the page can be cleared without the need to manually open the file.

The approach I take is to create a web page which contains a list of checkbox options corresponding to the files that are in a specific folder. A Clear Page(s) from Cache button will, when clicked, remove those pages from cache which have been checked. So that I can present the main ideas without a lot of clutter, I assume that all the pages for our site reside in one folder and that every page's output is not dependent on the querystring. Thus, I can simply remove them from cache without worrying about enumerating any querystring parameter values.

We give an outline of the code to clear pages from cache below. The main purpose is to show you the program structure at a high level and to introduce a few more aspects of ASP.NET rather than to go through the code line-by-line. Let's start by defining the presentation .aspx page where we'll define the CheckBoxList control which will display a list of checkbox options, each corresponding to a file in the folder.


<%@ Page Language="C#" Src="SimpleClearCache.aspx.cs" Inherits="MyNamespace.MyClass" %>
<html>
  <head>
  </head>
  <body>
    <form runat="server">
      <asp:Label id="Label1" runat="server">Label</asp:Label>
      <br />
      <asp:CheckBoxList id="FileName" runat="server"></asp:CheckBoxList>
      <br />
      <asp:Button id="Button1" onclick="Submit_Click" runat="server" 
                  Text="Clear Page(s) From Cache"></asp:Button>
     </form>      
  </body>
</html>

This page has a code-behind page associated with it which has all the code to clear pages from cache. The key to clearing a page from cache is to make use of the RemoveOutputCacheItem of the HttpResponse class. Below is an annotated full listing of the code-behind page:


//SimpleClearCache.aspx.cs
using System;     // for the Object on Submit_Click
using System.Web; // for HttpResponse class
using System.Web.UI.WebControls; // Web controls
using System.IO;  // File system access

namespace MyNamespace {
  public class MyClass : System.Web.UI.Page {
    // Declare controls from the presentation block
    protected CheckBoxList FileName;
    protected Label Label1;
    protected Button Button1;

    void Page_Load() {
      if (! IsPostBack) {
        // Enumerate files in the directory and 
        // databind to CheckBoxList
        String [] Files = Directory.GetFiles(Server.MapPath("/"));
        Array.Sort(Files); // Sort files alphabetically
        Label1.Text = "<br>Number of files: = " + Files.Length;
        FileName.DataSource = Files;
        DataBind();
      } // end of IsPostBack if-block
    }

    public void Submit_Click(Object sender, EventArgs e) {
      Label1.Text = "<p>The following pages are removed from " + 
                    "the cache:<p>";
      // Determine the selected item
      string TempFileName = "";
      for (int i=0; i < FileName.Items.Count; i++) {
        // Loop through all files and determine which 
        // ones have been selected.
        TempFileName = ""; // Reset the TempFileName string
        if (FileName.Items[i].Selected) {

          // Get the current file name
          TempFileName = FileName.Items[i].Text;

          // Strip the root from path using 
          // Regex.Replace(input_str, 
          //               pattern_str, 
          //               replacement_str)
          TempFileName = TempFileName.Replace(
            Request.ServerVariables["APPL_PHYSICAL_PATH"],
            "/");

          // Next, replace all the slashes 
          // to the proper direction
          TempFileName = TempFileName.Replace("\\", "/");
          Label1.Text += @"<a target=""_blank"" " + 
                          "href='"+TempFileName+"'>" + 
                          TempFileName + "</a>" + ":<br>";
  
          // Remove page from cache
  
          HttpResponse.RemoveOutputCacheItem(TempFileName);
        } 
      }
    } // end of Submit_Click
  } // end of MyClass
} // end of MyNamespace

This solution is not ideal, though. A better way would be to make a request to the page after the page is removed from cache. As a result, it will be the system which will bear the brunt of an initial slow response. But, all your site visitors will get the faster cached page. An even further improvement is to trigger the cache clearing code the moment the database is updated for that page. This way, every time the database content for that page is updated, the page will be automatically cleared from cache so that it can immediately start reflecting the new material.

Finally, there are a few other things which you can implement right away using the concepts discussed in this article. Firstly, you can define custom error handling pages without having to modify settings on the Internet Information Server (IIS), as is the case for classic ASP sites. In ASP.NET, you can define the custom error handling pages within a file, web.config, which is placed in the root folder of your site.

Another control that can save you a lot of time is the calendar control. With this control, you can display a month of events, say, with minimal amount of coding. Lastly, ASP.NET makes it very easy to create images on the fly. So, if you'd like to create a "My Profile" area on your website and have an image tab with the user's name, then based on the user logged in, you can stream a dynamically created image to the browser. So, each user will see his or her name on the image, yet there is no explicit image on your site with that user's name. You can, of course, also cache that image too using the techniques discussed above to speed up the performance. Refer to the ASP.NET Cookbook for more details on creating dynamic images.

Summary

ASP.NET is significantly different from classic ASP. However, we can use our knowledge of classic ASP to learn ASP.NET. As we have seen, if we look at controls as an evolution of classic ASP, we could introduce some of the more advanced concepts, such as DataBinding, in a natural manner. We have also seen that controls offer a powerful way to separate presentation from code as well as write more efficient code.

The objective of this three-part tutorial was to quickly give you a bird's eye-view of ASP.NET. The idea was to let you "see" in a rapid manner what this technology has to offer. As a result, we have only skimmed the surface of ASP.NET. But my hope, however, is to have given you enough justification to further study ASP.NET and to motivate you to start migrating your classic ASP site to ASP.NET.

Finally, and perhaps surprisingly, ASP.NET is not limited to just Microsoft platforms. Using Mono (http://www.mono-project.com), you can implement ASP.NET sites on several other platforms such as Linux, MacOS X, and Unix. Thus, you can finally build cross-platform applications.

Related Links and References

  1. Page Directive: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconPage.asp
  2. Web Matrix: http://www.asp.net/webmatrix/default.aspx?tabIndex=4&tabId=46
  3. Custom User Controls: http://www.asp101.com/lessons/usercontrols.asp
  4. ASP.Net in a Nutshell,  G.Andrew Duthie, Matthew MacDonald, http://www.oreilly.com/catalog/aspdotnetnut/index.html, O'Reilly.com, June 2002
  5. ASP.NET Cookbook, Michael A. Kittel. Geoffrey T. LeBlond, http://www.oreilly.com/catalog/aspnetckbk/index.html, O'Reilly.com, August 2004
  6. The Mono Project, http://www.mono-project.com.

Neel Mehta has a doctorate from the University of Pennsylvania and is an ardent fan of .NET and sees it as one of the few technologies that will be around for some time.


Return to ONDotnet.com.