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:
ProgressReport has two properties which work in conjunction:
-
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.
-
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:
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;
using System.Web.Script.Serialization;
Implement your handler as follows:
public class progressHandler : IHttpHandler
{
private static int _Counter;
public void ProcessRequest (HttpContext context)
{
context.Response.AppendHeader("Cache-Control",
"no-cache, no-store, must-revalidate");
context.Response.AppendHeader("Expires", "-1");
context.Response.AppendHeader("Pragma", "no-cache");
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);
ProgressData4JS objProgressData4JS = new ProgressData4JS();
if (_Counter < 100)
{
objProgressData4JS.IsComplete = false;
objProgressData4JS.FillRatio = String.Format("{0}%", _Counter);
objProgressData4JS.TextValues = new object[] {
"PENDING",
_Counter };
objProgressData4JS.ErrorMessage = null;
_Counter+=10;
}
else
{
objProgressData4JS.IsComplete = true;
objProgressData4JS.FillRatio = "100%";
objProgressData4JS.TextValues = new object[] {
"COMPLETE",
_Counter };
objProgressData4JS.ErrorMessage = null;
_Counter = 0;
}
JavaScriptSerializer objJavaScriptSerializer =
new JavaScriptSerializer();
string sResponse =
objJavaScriptSerializer.Serialize(objProgressData4JS);
context.Response.ContentType = "text/json";
context.Response.Write(sResponse);
context.ApplicationInstance.CompleteRequest();
}
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">
<!--
function go()
{
var _c = $find("<%= ProgressReport.ClientID %>");
_c.add_complete(onComplete);
_c.start();
}
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