Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using Ajax to display the progress of an ASP.NET server task

0.00/5 (No votes)
3 Jan 2008 1  
A progress bar implementing ASP.NET Ajax Extensions 1.0

Progress report in run mode

Introduction

Our objective is to display an Ajax progress bar which indicates the progress of a server task. Our environment is ASP.NET 2.0 on Windows and IIS and our progress bar uses ASP.NET Ajax Extensions 1.0 which you can download and install from http://www.asp.net/ajax/.

Background

This article refers to the open-source controls of �Memba Velodoc XP Edition� which you can download from http://www.velodoc.com/en/download.htm (this page links to Codeplex, Google code and Sourceforge.NET) and which are distributed under the GPL license. These controls include a progress bar which we demonstrate in this article. You can experiment these controls live at http://www.velodoc.net/.

Using the code

In Visual Studio 2005, create a new ASP.NET Ajax-Enabled Web Site and add a reference to Memba.WebControls.XP.dll which contains the progress report server control. Memba.WebControls.XP.dll is part of Memba Velodoc XP Edition. Source code is available at the download location cited above.

Open the Default.aspx page and add the ProgressReport server control, either by dragging and dropping the control after adding it to the toolbox or simply by adding the following code between the existing <form> tags:

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server" ></asp:ScriptManager>
<mbui:ProgressReport ID="ProgressReport" runat="server"  
    DefaultText="Waiting..."
    Width="400px"
    Interval="1000"
    BarCssClass="cssProgressBar"
    FillerCssClass="cssProgressFiller" 
    HandlerUrl="~/progressHandler.ashx"
    TextFormat="Value 1: {0}<br/>Value 2: {1}" ></mbui:ProgressReport>
<input type="button" onclick="go();" value="Go" />
</form> 

Also add an html button to start the progress bar using the onlick event.

You may have to register the control at the top of the page, using the following statement:

<%@ Register Assembly="Memba.WebControls.XP" Namespace="Memba.WebControls" TagPrefix="mbui" %> 

The progress bar consists of two nested DIV�s. The outer DIV constitutes the frame of the progress bar and the inner DIV constitutes the filled section which represents the progress. Add the following styles just above the </head> closing tag of your page:

<style  type="text/css">
<!--
div.cssProgressBar
{
 border:solid 1px DarkGreen !important;
 padding:1px;
 background-color:White;
}
div.cssProgressFiller
{
 background-color:DarkGreen !important;
 height:10px;
}
//-->
</style>

Your ProgressReport control should now look like follows:

Progress report in design mode

ProgressReport has two properties which work in conjunction:

  1. HandlerUrl points to an http handler which should return a JSON string in a specific format; you could use an ASP.NET page to return this formatted string, but a handler is leaner in this case because ASP.NET pages have a complex lifecycle.
  2. TextFormat is the formatting string used to display a textual description of the progress using the data returned by the http handler.

Now create a new generic handler called progressHandler.ashx:

Adding a new generic handler in Visual Studio 2005

This handler would generally query the progress of a task executing on the server. One could imagine a loop which would iterate through the pages of a multipage report and regularly update the current page number in memory (application state, session state or context cache). The handler would query the memory and return the progress in percentage of the total number of pages. The progress bar defines the interval at which the handler is called. We have made our example simpler as we simply increment a static counter.

Add the following two statements at the top of your handler:

using Memba.WebControls; //ProgressData4JS
using System.Web.Script.Serialization; //JavaScriptSerializer

Implement your handler as follows:

public class progressHandler : IHttpHandler
{
    private static int _Counter;
    
    public void ProcessRequest (HttpContext context)
    {
        //First, make sure the content is not cached because we need
        //"real-time" progress report
        
        //Using headers or cache attributes to set the cache policy
        //should be equivalent
        context.Response.AppendHeader("Cache-Control",
            "no-cache, no-store, must-revalidate");
        context.Response.AppendHeader("Expires", "-1");
        context.Response.AppendHeader("Pragma", "no-cache");

        //but the following does not work in IIS 7 (Vista 64-bit OS),
        //which requires the code above
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.Cache.SetRevalidation(
            HttpCacheRevalidation.AllCaches);
        context.Response.Cache.SetNoStore();
        context.Response.Cache.SetNoServerCaching();
        context.Response.Cache.SetExpires(DateTime.Now);
        
        //Create a progress data object which will be used for JSON 
        //serialization
        ProgressData4JS objProgressData4JS = new ProgressData4JS();
        
        //Fill the progress data until progress reaches 100%
        if (_Counter < 100)
        {
            objProgressData4JS.IsComplete = false;
            objProgressData4JS.FillRatio = String.Format("{0}%", _Counter);
            objProgressData4JS.TextValues = new object[] {
                "PENDING",
                _Counter };
            objProgressData4JS.ErrorMessage = null;
            _Counter+=10;
        }
        else //Once progress reaches 100% we are done
        {
            objProgressData4JS.IsComplete = true;
            objProgressData4JS.FillRatio = "100%";
            objProgressData4JS.TextValues = new object[] {
                "COMPLETE",
                _Counter };
            objProgressData4JS.ErrorMessage = null;
            _Counter = 0;
        }
        
        //Serialize progress data
        JavaScriptSerializer objJavaScriptSerializer =
            new JavaScriptSerializer();
        string sResponse =
            objJavaScriptSerializer.Serialize(objProgressData4JS);
        context.Response.ContentType = "text/json";
        //Some use "application/json"
        
        //Write the response
        context.Response.Write(sResponse);
        context.ApplicationInstance.CompleteRequest();
        //See: http://support.microsoft.com/kb/312629
        //context.Response.End();
    }
 
    public bool IsReusable {
        get
        {
            return true;
        }
    }
}

Whatever the task you execute on your server and you want to report progress on, always use a ProgressData4JS object which you write to the response stream using JSON serialization. The progress bar of the ProgressReport control uses the FillRatio property of the PorgressData4JS object to display the status of the progression. ProgressData4JS also has a property called TextValues which is an array of objects used to display the text under the progress bar in conjunction with the TextFormat property of the ProgressReport control. In our example, when the progress has reached 100%, TextValues contains �COMPLETE� and �100�. The TextFormat property of our ProgressReport is �Value 1: {0}<br />Value2: {1}�. The result displayed will be:

Value 1: COMPLETE
Value 2: 100

Now, we need to write the Javascript code to start the progress report. Add the following script just before the </body> closing tag of your page.

<script type="text/javascript">
<!--
//Click event handler for the Go button
function go()
{
    //Get a reference to the progress control
    var _c = $find("<%= ProgressReport.ClientID %>");
    //Add an event handler for the complete event
    _c.add_complete(onComplete);
    //Start progress report
    _c.start();
}
//Complete event handler for the progress report
function onComplete(e)
{
    alert("complete");
}
//-->
</script>

The script implements two event handlers:

  • A click event handler for the go button, which starts the progress;
  • A complete event handler for the progress report control, which displays an alert when the server task is complete.

Press F5 to run the project and click the go button to see the progress bar progressing.

Points of Interest

This progress bar is an easy to use server control based on ASP.NET Ajax extensions. It not only displays a progress bar but also a highly flexible textual description. For more advanced developers, the source code of the progress bar is available at Codeplex, Google code and Sourceforge.NET and is commented in great details.

History

  • Version 1.0 dated 18 Dec 2007

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here