ASP 101 - Active Server Pages 101 - Web04
The Place ASP Developers Go!

Please visit our partners


Windows Technology Windows Technology
15 Seconds
4GuysFromRolla.com
ASP 101
ASP Wire
VB Forums
VB Wire
WinDrivers.com
internet.commerce internet.commerce
Partners & Affiliates














ASP 101 is an
internet.com site
ASP 101 is an internet.com site
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

ASP 101 News Flash ASP 101 News Flash



 Top ASP 101 Stories Top ASP 101 Stories
Migrating to ASP.NET
Getting Scripts to Run on a Schedule
The Top 10 ASP Links @ Microsoft.com

QUICK TIP:
Cache commonly used values in application variables
Show All Tips >>
ASP 101 RSS Feed ASP 101 Updates


Using HTTP Handlers to Create a Progress Bar Control

by Matt Rutledge

The HTTP Pipeline

ASP.NET uses a pipeline model to process the requests to the scripting engine. Here is generally how the pipeline model works.

  1. An HTTP request is passed to an instance of the HttpRuntime() class.
  2. The HttpRuntime() object examines the request to find out which application to send the request to.
  3. Then .NET uses a HttpApplicationFactory to either create or find an application.
  4. Once the proper application is found the request is sent to through any HttpModules that are running on that application.
  5. After the modules have operated on the application the application uses a HttpHandlerFactory to either find or create any handler objects.
  6. The final step is to deliver the application.

Take a look at the following figure for a visual representation of the HTTP Processing Pipeline.

HTTP Processing Pipeline

What is a HTTP Handler?

So What exactly is a Http Handler? Well, HTTP handlers are the .NET components that implement the System.Web.IHttpHandler interface. Any class that implements the IHttpHandler interface can handle incoming HTTP requests.

With Http Handlers you can create your own file extensions, do certain tasks every time a page with a specific extension is loaded, create progress bars to show status, etc., the list goes on and on.

When you implement any interface you have a certain number of functions that you will need to implement. The IHttpHandler interface has two functions that you will need to write. They are the ProcessRequest() function and the IsReuseable() function. The former is the heart of the Http Handler. The latter strictly tells the ASP.NET worker process whether it can reuse this Http Handler or not.

How do you create a HTTP Handler?

As I mentioned above you need to implement the ProcessRequest() and IsReuseable() functions in your own class. So let's create our own class. If you use Visual Studio .NET you can create a new Web solution by doing the following:

  1. Go to File->New->Project
  2. Go to the Visual C# Projects Folder and choose a ASP.NET Web Application
  3. Give the project a name and click "OK"

Now that you have a new C# Web project created you need to add a class to your project. I called mine CHttpProgressHandler. Once you have the class up you will need to inherit from the IHttpHandler interface. Then create a public function called ProcessRequest() that takes the HttpContext as a parameter and then create a public property called IsReusable that implements the get property. The code should look something like the following:

using System;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyProgressBar
{
  /// <summary>
  /// Summary description for CHttpUploadHandler.
  /// </summary>
  public class CHttpProgressHandler : IHttpHandler
  {
    public CHttpProgressHandler()
    {
      //
      // TODO: Add constructor logic here
      //
    }
    #region IHttpHandler Members
    public void ProcessRequest(HttpContext context)
    {
    // TODO:  Add CHttpProgressHandler.ProcessRequest implementation
    }
    public bool IsReusable
    {
      get
      {
        return true;
      }
    }
    #endregion
  }
}

This is the base of all HttpHandlers. Any time that you start creating an Http Handler the class should look like the above code. Right now this Handler does absolutely nothing. So let's make it do something. One request that is seen a lot is creating a progress bar to show the user how long a particular process is going to take. Let's implement our Handler to do exactly that; to show the user how long a certain process will take.

Before you get to caught up in what the logic of the Handler is let's think about all the elements you will need to implement this progress indicator. First you will need a way to display a progress bar on a page. There are a lot of controls out there that you can download if you would like; we are going to create our own. Then you need a process that takes a certain amount of time to complete; for this you can implement a loop on a separate page that is triggered by an event. When that event is triggered you need to pop-up the progress bar. So you will need two pages, one for to implement a long process, and one to show the progress.

Let's implement our very own Progress Bar Control. To do this you will need to add another class to your project and inherit from the WebControl class and the INamingContainer interface. You will have two properties to set, the foreground color and the background color. Then you need to implement the render function to draw the progress bar. Here is the code for the Progress Bar Control:

Note: This is not a tutorial on how to create controls.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace Progress
{
  /// <summary>
  /// Progress bar control is used to display the progress or 
  /// status of a particular process.
  /// </summary>
  [DefaultProperty("Text"), ToolboxData("<{0}:ProgressBar runat=server>
    </{0}:ProgressBar>")]
  public class ProgressBar : WebControl, INamingContainer 
  {
    // Member variables
    private int nProgress      = 0;    // Percentage out of 100
    private int nPercentOfProgress  = 0;    // Percentage in 20ths
    /// <summary>
    /// Default Constructor
    /// </summary>
    public ProgressBar() 
    {
      // Set the default colors of the control
      this.BackColor = System.Drawing.Color.LightGray;
      this.ForeColor = System.Drawing.Color.Blue;
    }
    /// <summary>
    /// Accessor to set the background color of the control
    /// </summary>
    public override System.Drawing.Color BackColor 
    {
      get 
      {
        return base.BackColor;
      }
      set 
      {
        base.BackColor = value;
      }
    }
    /// <summary>
    /// Accessor to set the foreground color of the control
    /// </summary>
    public override System.Drawing.Color ForeColor 
    {
      get 
      {
        return base.ForeColor;
      }
      set 
      {
        base.ForeColor = value;
      }
    }
    /// <summary>
    /// Accessor to update the progress of the control
    /// </summary>
    public int PercentageOfProgress 
    {
      get 
      {
        return nProgress;
      }
      set 
      {
        // Make sure the progress doesn't have invalid values
        if (value > 100)
        {
          nProgress = 100;
        }
        else if (value < 0)
        {
          nProgress = 0;
        }
        else
        {
          nProgress = value;
        }
        // Calculate the percentage done if the progress > 0
        if (nProgress != 0)
        {
          nPercentOfProgress = nProgress / 5;
        }
      }
    }
    /// <summary>
    /// Renders the progress bar
    /// </summary>
    /// <param name="output"></param>
    protected override void Render(HtmlTextWriter output) 
    {
      // Create a table to render
      Table table      = new Table();
      TableRow row    = new TableRow();
      table.CellPadding  = 0;
      table.CellSpacing  = 0;
      table.BorderWidth  = 0;
      table.Width      = 100;
      // Add a row to the table
      table.Rows.Add(row);
      // Since we split the data into 20ths
      // we need a cell for each piece.
      // Another option is to use the GDI to 
      // create a graphic progress bar.
      for(int i = 0; i < 20; i++) 
      {
        TableCell td  = new TableCell();
        td.Width    = 5;
        td.Height    = 16;
        // If the count is less then the percent done 
        // then you need to set it to the fore color.
        // Otherwise the progress has not reached this 
        // cell and you need to set it to the back color.
        if (i < nPercentOfProgress)
        {
          td.BackColor = this.ForeColor;
        }
        else
        {
          td.BackColor = this.BackColor;
        }
        // Add the cell to our row
        row.Cells.Add(td);
      }
      // Add the table to the calling page
      this.Controls.Add(table);
      table.RenderControl(output);
    }
  }
}

Now you can create a new Web form and put your control in it.

How to Enable Access to Information in your HTTP Handlers

To make sure the popup-window can reach your information about the progress, you have to save it in the Application-state. The reason we use the application state to store the information is because Session state information is not available until the whole process is done. So in order to do this you need to create a unique key to make sure that every user doesn't get the same progress bar.

You will need to set this value when you are doing your processing. So in your aspx page that is doing the loading you can put something like this in the code behind page:

private void btnSubmit_Click(object sender, System.EventArgs e)
    {
      if(Page.IsValid)
      {
        // Start the proces
        for(int i = 0; i <= 100; i++) 
        {
          System.Threading.Thread.Sleep(300);
          // Save the progress in the Application-state with
          // a unique key for this session
          Application["progress_" + Session.SessionID] = i;
        }
        lblMsg.Text = "<h1>PROCESS FINISHED!!</h1>";
}

This will store the total percentage process in the application state. So in your Http Handler you can access that Application state variable like this:

    #region IHttpHandler Members
    public void ProcessRequest(HttpContext context)
    {
      HtmlTextWriter writer = new HtmlTextWriter(context.Response.Output);
      // Build the HTML for the popup
      writer.WriteFullBeginTag("html");
      writer.WriteFullBeginTag("body");
      writer.WriteFullBeginTag("head");
      writer.WriteFullBeginTag("title");
      writer.Write("Progress");
      writer.WriteEndTag("title");
      writer.WriteBeginTag("meta");
      writer.WriteAttribute("http-equiv","refresh");
      writer.WriteAttribute("content","1");
      writer.Write(HtmlTextWriter.TagRightChar);
      writer.WriteEndTag("head");
      writer.WriteFullBeginTag("body");
      int progress;
      // When the process is unknown in the Application-state, the process is 0
      if(context.Application["progress_" + context.Request.Params["id"]] == null)
        progress = 0;
      // Else this equals the int in the Application-state
      else
        progress = (int) context.Application["progress_" +
          context.Request.Params["id"]];
      // Create the progressbar
      Progress.ProgressBar pbProgress = new Progress.ProgressBar();
      pbProgress.ID = "ProgressBar";
      // Set the value of the progressbar
      pbProgress.PercentageOfProgress = progress;
      pbProgress.RenderControl(writer);
      writer.Write("<div align=\"center\">" + progress + "%</div>");
      // If the proces is finished,
      if(progress == 100) 
      {
        // Close the popup-window using JavaScript
        writer.WriteBeginTag("script");
        writer.WriteAttribute("language","javascript");
        writer.Write(HtmlTextWriter.TagRightChar);
        writer.Write("window.close();");
        writer.WriteEndTag("script");
        // DON'T FORGET to remove the variable from the Application-state,
        // otherwise it will exist 'forever'   
        context.Application.Remove("progress_" + context.Request.Params["id"]);
      }
      writer.WriteEndTag("body");
      writer.WriteEndTag("html");
    }

Registering Your HTTP Handlers with .NET

Registering HTTP Handlers with your .NET Web Application is extremely simple. All you have to do is add a new section to your <system.web> portion of your Web.Config file. The new section should look something like this:

<httpHandlers>
  <add verb="GET" path="ProgressBar.aspx" type="UploadProgressBar.CHttpUploadHandler, UploadProgressBar" validate="false" />
</httpHandlers>

Putting it all Together

This article includes the source files which you can download from here: ProgressBar.zip (21 KB). The Page that does the processing, in other words the page that you want to display the progress bar for, is called UploadForm.aspx. This page triggers a popup that loads ProgressBar.aspx. The HttpHandler that we specified in the Web.Config file catches any requests to ProgressBar.aspx and pipes them through the CHttpUploadHandler class. The process request in the class file prints a progress bar to the ProgressBar.aspx document.

Conclusion

I hope you enjoyed this article and you will find it usefull. If you have any questions please feel free to e-mail me at ruts@datausa.com. Happy Coding!


Home |  News |  Samples |  Articles |  Lessons |  Resources |  Forum |  Links |  Search |  Feedback

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers