Ian Reddy's

Display Progress with Dynamic Status in ASP.NET (C#)

Posted in .NET Framework by ianreddy on February 19, 2014

In some web applications, we would like to display detailed information on the status of a long running task to the user. One way to achieve this in asp.net is using a timer with an update panel and a polling mechanism to return the current status of the task.

ProgressCapture

The timer can be added to the markup using the syntax below. The Interval specifies the number of milliseconds to wait before initiating a post back. The method mainTimer_Tick will be invoked each time a post back is initiated by the timer. Note that in this example the timer is disabled to begin with and will be enabled by a user event.

<asp:Timer ID="mainTimer" runat="server"
Interval="500" OnTick="mainTimer_Tick" Enabled="false">
</asp:Timer>

Add an update panel, set the UpdateMode to Conditional , include a AsyncPostBackTrigger and specify the control Id to be the timer control added from the step above (in this case its “mainTimer”). This will allow the timer control to explicitly trigger a refresh of the update panel control. In this example I have included an image to show progress along with a label below it to update the details of the task.

<asp:UpdatePanel ID="subPanel" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="mainTimer" />
</Triggers>
<ContentTemplate>
<asp:Image ID="imgProgress" runat="server" ImageUrl="~/Images/progress.gif"
AlternateText="" Visible="false" />
<br />
<asp:Label ID="lblDescription" runat="server" Visible="false"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>

Below is the full mark up and the code behind. The code behind is self explanatory. Hope this helps!!

Markup


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Sample1.aspx.cs" Inherits="Sample1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Timer ID="mainTimer" runat="server" Interval="500" OnTick="mainTimer_Tick" Enabled="false">
</asp:Timer>
<table cellspacing="20" cellpadding="20" width="100%">
<tr>
<td align="center" valign="middle">
<div>
<asp:UpdatePanel ID="subPanel" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="mainTimer" />
</Triggers>
<ContentTemplate>
<asp:Image ID="imgProgress" runat="server" ImageUrl="~/Images/progress.gif" AlternateText=""
Visible="false" />
<br />
<asp:Label ID="lblDescription" runat="server" Visible="false"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<asp:Button ID="btnLoop" runat="server" Text="Start Checking Status" OnClick="btnLoop_Click" />
</td>
</tr>
</table>
</form>
</body>
</html>

Code Behind


public partial class Sample1 : System.Web.UI.Page
{

protected void Page_Load(object sender, EventArgs e)
{

if (!Page.IsPostBack)
//It is prefereable that you kick off the task on the previous page and then redirect to this page
//in order to prevent duplicate submission of tasks
StartLongRunningTask();

}

/// <summary>
/// Just setting server vairables here, this is where you would kick off the long running task.
/// </summary>
private void StartLongRunningTask()
{
this.Application["MaxIndex"] = "20";
this.Application["Counter"] = "1";
}

/// <summary>
/// This triggers the polling to start and constantly check for the task status
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnLoop_Click(object sender, EventArgs e)
{
this.lblDescription.Visible = this.imgProgress.Visible = true;
this.mainTimer.Enabled = true;
}

/// <summary>
/// This methods gets executed at intervals specified within the timer control,
/// in this example its set to 500ms
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void mainTimer_Tick(object sender, EventArgs e)
{
//This example uses the Application object to persist the status of the task
int maxIndex = Convert.ToInt32(this.Application["MaxIndex"]);
int counter = Convert.ToInt32(this.Application["Counter"]);

if (counter >= maxIndex)
{
this.imgProgress.Visible = false;
this.mainTimer.Enabled = false;
lblDescription.Text = "Completed processing all records.";
}
else
{
this.lblDescription.Text = "Processing " + counter + " of " + maxIndex + " records";
this.Application["Counter"] = ++counter;
}

}

}

Leave a comment