Sony Arouje

a programmer's log

SignalR – Real time pushing of data to connected clients

with 25 comments

Updated post about how to create a chat application using SignalR 2.1

How many times you might have refreshed your browser to see the updated score of a cricket match or refresh to get the updated stock details. Isn’t that cool if the browser can display the updated data without refreshing or doing a page load. Yes it is, then the next question come to mind is how to implement it using .NET technology. There is no straight forward approach, most of them have loads of code.

So how do we achieve it? The answer is SignalR. Scott Hanselman have a nice post about SignalR. In his post he explains a small chat application using 12 lines of code.

I wanted a real time pushing of data to ASP.NET, Javascript client or desktop clients for a project I am working on. The details of that project I will post it later. I am aware of SignalR but never really tried or doesn’t know how to make it work. Yesterday I decided to write a tracer to better understand how SignalR works. This post is all about that tracer I created.

Tracer Functionality

The functionality is very simple. I need two clients a console and a web app. Data entered in any of these clients should reflect in other one. A simple functionality to test SignalR.

Let’s go through the implementation.

I have three projects in my solution 1. SignalR self hosted server 2. A console Client 3. A Web application.

SignalR server

Here I used a self hosting option. That means I can host the server in Console or Windows service. Have a look at the code.

using System;
using System.Threading.Tasks;
using SignalR.Hosting.Self;
using SignalR.Hubs;
namespace Net.SignalR.SelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://localhost:8081/";

            var server = new Server(url);
            server.MapHubs();
            
            server.Start();
            Console.WriteLine("SignalR server started at " + url);

            while (true)
            {
                ConsoleKeyInfo ki = Console.ReadKey(true);
                if (ki.Key == ConsoleKey.X)
                {
                    break;
                }
            }
        }

        public class CollectionHub : Hub
        {
            public void Subscribe(string groupName)
            {
                Groups.Add(Context.ConnectionId, groupName);
                Console.WriteLine("Subscribed to: " + collectionName);
            }

            public Task Unsubscribe(string groupName)
            {
                return Clients[groupName].leave(Context.ConnectionId);
            }

            public void Publish(string message, string groupName)
            {
                Clients[groupName].flush("SignalR Processed: " + message);
            }
        }

    }
}

As you can see from the main I hosted the SignalR server in a specific URL. You can see another Class called CollectionHub inherited from Hub. So what is a hub? Hubs provide a higher level RPC framework, client can call the public functions declared in the hub. In the above Hub I declared Subscriber, Unsubscribe and Publish function. The clients can subscribe to messages by providing a Collection Name, it’s like joining to a chat room. Only the members in that group receives all the messages.

You will notice another function called Publish with a message and a groupName. The clients can call the publish method by passing a message and a group name. SignalR will notify all the clients subscribed to that group with the Message passed. So what’s this ‘flush’ function called in publish, it’s nothing but the function defined in the client. We will see that later.

We are done, run the console application and our SignalR server is ready to receive requests.

SignalR clients

First we will look into a Console client. Let’s see the code first.

using SignalR.Client.Hubs;
namespace Net.SignalR.Console.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            var hubConnection = new HubConnection("http://localhost:8081/");
            var serverHub = hubConnection.CreateProxy("CollectionHub");
            serverHub.On("flush", message => System.Console.WriteLine(message));
            hubConnection.Start().Wait();
            serverHub.Invoke("Subscribe", "Product");
            string line = null;
            while ((line = System.Console.ReadLine()) != null)
            {
                // Send a message to the server
                serverHub.Invoke("Publish", line, "Product").Wait();
            }

            System.Console.Read();
        }
    }
}

Let’s go line by line.

  1. Create a hub connection with the url where SignalR server is listening.
  2. Create a proxy class to call functions in CollectionHub we created in the server.
  3. Register an event and callback, so that Server can call client and notify updates. As you can the Event name is ’Flush’, if you remember the server calls this function in Publish function to update the message to clients.
  4. Start the Hub and wait to finish the connection.
  5. We can call any public method in declared in Hub using the Invoke method by passing the function name and arguments.

Run the console application and type anything and hit enter. You can see some thing like below.

image

The name prefixed ‘SignalR Processed’ is the message back from the SignalR server. So we are done with a console application.

Now how about we have to display the updates in a web application. Let’s see how to do it in web application. In web application I used javascript to connect to the SignalR server.

<html xmlns="http://www.w3.org/1999/xhtml">
    <script src ="Scripts/json2.js" type="text/jscript"></script>
    <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery.signalR-0.5.3.min.js" type="text/javascript"></script>
    <script type="text/javascript">
           $(function () {
               var connection = $.hubConnection('http://localhost:8081/');
               proxy = connection.createProxy('collectionhub')
               connection.start()
                    .done(function () {
                        proxy.invoke('subscribe', 'Product');
                        $('#messages').append('<li>invoked subscribe</li>');
                    })
                    .fail(function () { alert("Could not Connect!"); });


               proxy.on('flush', function (msg) {
                   $('#messages').append('<li>' + msg + '</li>');
               });

               $("#broadcast").click(function () {
                   proxy.invoke('Publish', $("#dataToSend").val(), 'Product');
               });

           });
    </script>
    <body>
        <div>
            <ul id="messages"></ul>
            <input type="text" id="dataToSend" />
            <input id="broadcast" type="button" value="Send"/>
        </div>
    </body>
</html>

 

You can install SignalR Javascript client from Nuget and it will install all the required js files. The code looks very similar to the one in Console application. So not explaining in detail.

 

Now if you run all three application together and any update in one client will reflect in other. As you can see in web client we use Javascript for DOM manipulation, so the page will never refresh but you will see the updated info.

image

I hope this post might help you to get started with SignalR.

Dowload the source code.

Happy coding….

Advertisements

Written by Sony Arouje

October 2, 2012 at 4:48 pm

Posted in .NET

Tagged with , ,

25 Responses

Subscribe to comments with RSS.

  1. Excellent, but looks like the js code not anymoe compatible with current SignalR js libs ?

    gabriel

    April 5, 2013 at 1:21 pm

    • Hi Gabriel,
      Thanks for the comment. I didn’t knew that, if time permits I will update the js code.

      Regards,
      Sony Arouje

      Sony Arouje

      April 5, 2013 at 2:09 pm

      • Hi Sony, nice post. I have a doubt.. incase you start your signalR server after all the diffrent SignalR clients are up. How will you get the connection? do we need to restart all the SignalR clients?? can you give some suggestion??

        dev

        April 9, 2013 at 2:00 pm

      • Hi Dev,
        You need to have the SignalR server running prior to the client. If the client started before SignalR server then you need restart the client.

        Regards,
        Sony Arouje

        Sony Arouje

        April 9, 2013 at 2:27 pm

  2. Hi Sony, Thanks for your reply. Thats the challenge i’m facing now. My situation is i have many real time client application running, its very costly to restart the client in my case. Can we host a hub at both client and server sony?

    dev

    April 10, 2013 at 4:11 am

    • Hi Dev,
      I don’t know how hosting a hub in both client and server will resolve your issue. Can you have the server running all the time?

      Regards,
      Sony Arouje

      Sony Arouje

      April 10, 2013 at 12:01 pm

      • Hi Sony, I’m just trying to implement some intelligence to identify the connection state and make the connection either from Server or Client.

        Regards
        Dev

        dev

        April 11, 2013 at 1:49 am

      • Hi Dev,
        That’s great. Let us know how you achieved it. It might help some one.

        Regards,
        Sony

        Sony Arouje

        April 12, 2013 at 12:17 pm

  3. Can you do the reverse of the same. I mean to say Hub in IIS website and Client is WPF or Console App. Coz I am facing problem while implementing the same. The server is getting connected but the server method is not getting

    nileshanchan

    April 22, 2013 at 5:56 pm

    • Hi Nilesh,
      As far as i know we can host hub in IIS and can be accessed from any type of clients.

      Regards,
      Sony

      Sony Arouje

      April 23, 2013 at 11:58 am

      • Thnx for your reply Soni, even I thought of the same thing and i am able to connect the server hosted in IIS but I am not able to post my messages via server methods. My criteria is the user can chat from web as well as WPF app and server hosted in web application

        Anonymous

        April 23, 2013 at 6:08 pm

      • Thnx for your reply Soni, even I thought of the same thing and i am able to connect the server hosted in IIS but I am not able to post my messages via server methods. My criteria is the user can chat from web as well as WPF app and server hosted in web application

        nileshanchan

        April 23, 2013 at 6:09 pm

    • Here is the updated one using SignalR 2.1 hosted in IIS https://sonyarouje.com/2014/09/18/signalr-2-1/

      Sony Arouje

      September 18, 2014 at 12:59 am

  4. Hello Sony,
    I am trying to implement your example…but since I am using the current versions of the signalr packages: SignalR.Hosting.Self -Version 0.5.84-rc -Pre(also tried SignalR.Hosting.Self -Version 0.53) and Microsoft.Aspnet.SignalR.Client instead SignalR.Client(which is deprecated) I am getting this exception when the client console app is started:
    “You are using a version of the client that isn’t compatible with the server. Client version 1.2, server version 1.0.”}

    Do you maybe have idea how I can solve this issue?
    Thanks at advance…I consider your post may be very helpful

    Greetings,
    Sandra

    Sandra Gorgieva

    July 24, 2013 at 9:19 pm

    • Sorry for the late reply Sandra. I havent tried this eg. with the new version, If time permits I will give a try with the latest release and fix the issue.

      Sony Arouje

      August 2, 2013 at 2:33 pm

      • Hello Sandra/Sony,

        Were you able to resolve the error, “You are using a version of the client that isn’t compatible with the server. Client version 1.4, server version 1.3.”, you received?
        I am facing the same issue and still not able to resolve it.

        Thanks,
        Anand Shah

        Anand Shah

        May 19, 2015 at 10:25 am

      • Hi Anand,
        From the error I assume you are using two different versions of SignalR in client and server. Please visit my updated post for more details, here I use the latest SignalR https://sonyarouje.com/2014/09/18/signalr-2-1/

        Regards,
        Sony Arouje

        Sony Arouje

        May 19, 2015 at 10:31 am

  5. Do you know of any examples of using SignalR with a WPF application and a WCF service?

    Shawn

    October 8, 2013 at 7:50 pm

    • Hi Shawn,
      Can you please provide some more details you are looking for? are you looking eg. to see how SignalR is consumed in WPF?

      Regards,
      Sony Arouje

      Sony Arouje

      October 9, 2013 at 3:50 pm

  6. I currently have a Windows Service that uses SignalR to send data to WCF service, Right now the WCF service logs the data in a txt file, this works fine the problem I am having now is sometimes the SIgnalR stops working and Then I get no data without having to log back into the server and manually re-start the Windows Service, Is there any was to automatically re-connect if SignalR stops for a short time period?

    Shawn Rye

    November 22, 2013 at 7:22 pm

    • Hi Shawn,
      Sorry for the late reply. I think you can close and restart SignalR host from your code. But the important part is how do we know the SignalR stop working.

      Regards,
      Sony

      Sony Arouje

      November 28, 2013 at 11:05 am

  7. Hello, do you have any plan to upgrade the sample into SignalR 2.1? Seems the SignalR.Server package is lost after I upgrade it.

    Thanks.
    Bruce

    Anonymous

    September 12, 2014 at 9:16 am

  8. […] two years ago I published a post about SignalR. Recently some readers requested an updated post using SignalR 2.1, here is the updated […]

  9. Hello Sony Arouje ,

    Nice post thanks for Upload this sample .
    I’ve Question .If Console client is behind Router,Proxy,firewall. And If Firewall or Proxy of Client preventing some protocol like ICMP or any other ,as you know mostly in Company office PC these kind of security do by network LOL.

    OR
    these days some new router disable Port forwarding thing ,

    Are you sure In that situation signalR will work .we don’t have to any setting on client side ????

    Thanks Advance.

    Adam Lee

    December 31, 2014 at 3:26 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: