Real-time notifications with SignalR

Introduction

Sometimes server side operations take time. It's not really user friendly to have users pressing a button and waiting 30 seconds for some operation to be executed, with the only progress information being a spinning wheel.

If you have server side operations that are time consuming and you would like your users to get insight into what is going on in the server in real-time, this article is for you.

I will show how you can use ASP.NET SignalR 2.0 to send messages from the server to the client while a process is running in the server. The result is a notification bar that is displayed to the user showing the progress happening in the server.

Disclaimer

The fact that you can use such technique doesn't mean you should start using it everywhere. You should always strive to optimize performance. As an example, if you have a database query that is slow you should try to optimize it first and, if it's really an expensive operation that you cannot improve, you can use such a technique to make your users more informed about the operation in progress.

Using the code

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.

We are going to use a notification jQuery plugin that provides nice out-of-the-box notifications. Still in NuGet's package management window, search for "noty". Select and install the package named jQuery Notification Plugin.

Next we add to the project a OWIN Startup class.

1

Add the following line to the Configuration method of the new Startup class:

app.MapSignalR();  

Next, we are going to add a SignalR hub. For this, add a new SignalR Hub Class (v2) item to your project.

2

This is the class that does the server side processing. I defined the class as follows:

public class RealtimeNotifierHub : Hub
{
    public int recordsToBeProcessed = 100000;

    public void DoLongOperation()
    {
        for (int record = 0; record <= recordsToBeProcessed; record++)
        {
            if (ShouldNotifyClient(record))
            {
                Clients.Caller.sendMessage(string.Format("Processing item {0} of {1}", record, recordsToBeProcessed));
                Thread.Sleep(10);
            }
        }
    }

    private static bool ShouldNotifyClient(int record)
    {
        return record % 10 == 0;
    }
}      

At this point our server is ready. We have a method called DoLongOperation that is called from the client side. This method simulates a long running operation with 100.000 iterations and, at every 10 iterations, notifies the client of the current status. The Thread.Sleep call was introduced to slow down the server, otherwise the for loop runs so fast that the notification bar wouldn't be needed.

Next we have to prepare the client. Create a new html page (or use the page where you want to show the notifications).

<!DOCTYPE html>
<html>
<head>
    <title>Real-time notifier</title>
    <script src="Scripts/jquery-1.10.2.min.js"></script>

    <!-- Import the noty scripts -->
    <script src="Scripts/noty/jquery.noty.js"></script>
    <script src="Scripts/noty/layouts/top.js"></script>
    <script src="Scripts/noty/themes/default.js"></script>

    <!-- Import the SignalR scripts -->
    <script src="Scripts/jquery.signalR-2.0.0.js"></script>
    <script src="http://www.codeproject.com/signalr/hubs"></script>
</head>
<body>
    <div style="margin-top: 100px;">
        <!-- This button will trigger the time consuming operation -->
        <input type="button" id="mybutton" value="Call a time consuming server side operation" />
    </div>
    <script type="text/javascript">

        $(function () {
            // Initialize the connection to the server
            var realtimeNotifier = $.connection.realtimeNotifierHub;

            // Preparing a client side function called sendMessage that will be called from the server side
            realtimeNotifier.client.sendMessage = function (message) {
                showOrUpdateSuccessMessage(message, false);
            };

            // Establish the connection to the server. When done, sets the click of the button
            $.connection.hub.start().done(function () {
                $('#mybutton').click(function () {
                    // When the cutton is clicked, call the method DoLongOperation defined in the Hub
                    realtimeNotifier.server.doLongOperation();
                });
            });
        });
    </script>
    <script type="text/javascript">
        // Helper code that updates the noty notification bar
        var n;
        function showOrUpdateSuccessMessage(message, timeout) {
            if (n == null) {
                n = noty({ text: message, type: 'success', timeout: timeout, maxVisible: 1 });
            }
            else {
                n.setText(message);
            }
        }
    </script>
</body>

The example above does several basic things:

  • establishes the connection from the client to 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 noty notification bar.

This is how it looks like when it's running:

3

You can find a working Visual Studio 2013 solution in the CodeProject article I created.
http://www.codeproject.com/Tips/672433/Real-time-notifications-with-SignalR

Alternatively, you can get it from GitHub at https://github.com/gustavorhm/RealtimeNotifier

If you have any questions I'll be happy to answer them.

References

comments powered by Disqus