Introduction
Today, we can see more and more web applications developed are equipped with AJAX. Although the success of AJAX compelled more developers to adapt and shift towards Ajax-based applications, still we have some areas left behind specially when it comes to real-time progress indication or notification. In this case, we have the only option to display the progress by showing progress bar or spinning wheel to make the Client believe that something is happening behind the scene without showing any Server-Side information to the Client.
In earnest, with this one-way or disconnected approach, there aren't many ways in which one can accomplish the real-time progress indication in AJAX. To cope with this scenario, one can build a real-time progress bar using a new and still-in-progress library: SignalR; a Microsoft .NET Framework signaling library being developed by the ASP.NET team, shifted as a part of Visual Studio 2013.
This tip will describe as illustrated in the following screen shot:
Using the Code
For creating the sample application as follows, I used Visual Studio 2012, jQuery 1.7, SignalR 2.0 and JQuery UI.
First of all, we need to add SignalR to the web application. There are several ways to do this, the simplest being right-clicking in your project, Manage NuGet packages, search Online for signalr and selecting to install Microsoft ASP.NET SignalR.
Next, we add to the project an OWIN Startup class and add Configuration method inside it to map SignalR library.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(RealTimeProgressBar.Startup))]
namespace RealTimeProgressBar
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Following is the hub class that does the server side processing:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace RealTimeProgressBar
{
public class ProgressHub : Hub
{
public string msg = "Initializing and Preparing...";
public int count = 100;
public void CallLongOperation()
{
for (int x = 0; x <= count; x++)
{
Thread.Sleep(100);
if (x == 20)
msg = "Loading Application Settings...";
else if (x == 40)
msg = "Applying Application Settings...";
else if (x == 60)
msg = "Loading User Settings...";
else if (x == 80)
msg = "Applying User Settings...";
else if (x == 100)
msg = "Process Completed!...";
Clients.Caller.sendMessage(string.Format
(msg + " {0}% of {1}%", x, count));
}
}
}
}
By the time, our server is ready. We have a CallLongOperation()
method that is called from the client side. This method simulates a long running operation with 100 iterations and, at every iteration, notifies the client of the current status with appropriate messages. The Thread.Sleep()
method was introduced to slow down the server, otherwise we could hardly see the progress in action.
Next, we have to prepare the client. Create a new HTML page (or use the page where you want to show the notifications).
<span style="white-space: pre-wrap;"><html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Real-time Progress Bar using SignalR and JQuery UI</title>
<link type="text/css" href="Content/ui.all.css" rel="stylesheet" />
<link href="Content/redmond/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" type="text/css" />
<script src="Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="Scripts/ui.core.js"></script>
<script type="text/javascript" src="Scripts/ui.progressbar.js"></script>
<%----%>
<!--
<script src="Scripts/jquery.signalR-2.0.2.min.js"></script>
<!--
<script src="http://www.codeproject.com/signalr/hubs"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#progressbar").progressbar({ value: 0 });
var progressNotifier = $.connection.progressHub;
progressNotifier.client.sendMessage = function (message) {
UpdateProgress(message);
};
$.connection.hub.start().done(function () {
progressNotifier.server.callLongOperation();
});
});
function UpdateProgress(message) {
var result = $("#result");
result.html(message);
var value = $("#progressbar").progressbar("option", "value");
$("#progressbar").progressbar("value", value + 1);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div style="width: 30%; margin: 0 auto;">
<div id="result" style="font-family: Tahoma;
font-size: 0.9em; color: darkgray; margin-top: 230px; padding-bottom: 5px">
Initializing and Preparing...
</div>
<div id="progressbar" style="width: 300px; height: 15px"></div>
<br />
</div>
</form>
</body>
</html></span>
The above code does start automatically when DOM loaded and can do the following:
- Establishes the persistent connection between the client and the server
- Declares a client side function that will be called by the server
- Calls the server's method that performs the time consuming operation
- Updates the JQuery UI ProgressBar
Points of Interest
This is sometimes useful when we want to load user and application settings from database and save into the application as an intermediary process between authentication and redirection to the main page.