Introduction
There are many project types that may have long running processes, e.g., complex calculation, multiple databases operations and Windows Workflows execution through MVC web app that are required to send current status to user.
Let's Start
I am using Visual Studio 2013 for this sample. Create a new MVC application with no authentication. Right click on References folder and select Manage NuGet Packages... option. Search for SignalR and Install Microsoft SignalR ASP.NET SignalR. This will install SignalR, its dependencies and SingalR JavaScript files:
Don't forget to install Microsoft jQuery Unobstrusive Ajax, you can get it from NuGet Packages too:
The next step is to create SignalR server side Startup
and Hub
classes to pass status from server to MVC Razor view. Create Startup.cs on root folder and paste the following code:
Startup.cs
using Owin;
using Microsoft.Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
This is good practice to create a new folder for Hub. Create the following ProgressHub.cs class in Hub folder:
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 static void SendMessage(string msg)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.All.sendMessage(string.Format(msg));
}
}
}
Edit HomeController
from Controllers folder and add the following function:
public ActionResult ProcessApplication()
{
ProgressHub.SendMessage("Long Running Process Started<br>");
ProgressHub.SendMessage("Process 1 is started...");
System.Threading.Thread.Sleep(6000);
ProgressHub.SendMessage("Process 1 is Finished");
System.Threading.Thread.Sleep(2000);
ProgressHub.SendMessage("Process 2 is started...");
System.Threading.Thread.Sleep(6000);
ProgressHub.SendMessage("Process 2 is Finished");
ProgressHub.SendMessage("<br>Long Running Process Finished");
System.Threading.Thread.Sleep(3000);
return PartialView("_Result");
}
This function has few System.Threading.Thread.Sleep
statements to behave like long running processes. Before and after each Sleep
statement, there is ProgressHub.SendMessage
method call that will send string
message to client where it is being displayed to the end user. I tried to keep this example simple, you can also implement Eventhandler
and call ProgressHub.SendMessage
in event method against any trigger, e.g., against variable value update.
The next step is to move to client side, edit Index.cshtml from Views/Home folder and replace the existing code with the following:
@{
ViewBag.Title = "Home Page";
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
@using (Ajax.BeginForm("ProcessApplication", "Home", "Post",
new AjaxOptions { UpdateTargetId = "divResult", OnComplete = "ReturnData" }))
{
<script src="~/signalr/hubs"></script>
<button type="submit" id="btnSubmit"
class="btn btn-default">Call Method</button>
<div id="divResult"> </div>
<div id="divStatus"></div>
<script type="text/javascript">
var final = "";
$(function () {
var progressNotifier = $.connection.progressHub;
progressNotifier.client.sendMessage = function (message) {
UpdateProgress(message);
};
$.connection.hub.start().done(function () {
});
});
function UpdateProgress(message) {
if (message != 'undefined') {
final += message + "<br>";
$("#divStatus").html(final);
}
}
function ReturnData() {
$('#divStatus').hide();
$('#divResult').show();
}
</script>
}
The connection to hub is created as soon the page is finished loading. When server will call ProgressHub.SendMessage
function, the client will receive this message and call UpdateProgress
function where it is appended in DIV
control for display, very simple!
History