Getting started with SignalR

12 בDecember 2012

5 comments

Getting started with SignalR

 

Recently I’ve begun testing ASP.NET.SignalR, an open source project that supports real-time web functionality in our application.SignalR logo

SignalR can be added to an existing ASP.NET application and help as easily gain real-time functionality
in no-time. It can run with browsers that supports HTML5 WebSocket or long polling (IE 8).

 

SignalR has both server and client code, its client code is based on jQuery

In this post I’ll demonstrate how to work with SignalR along with a few basic terms related to it.

 

Install SignalR nuget package

First, you should install Microsoft.ASP.NET.SignalR nugget package, you can do so either by running install command on
nuget management console, or do so by searching the package on the nugget packages GUI.  It will install another 4 SignalR
related packages along with jQuery and JSON.Net packages which SignalR packages depends on.

 

Server Side Code

Now, what we need to do is to have some code that  will act as our service, in SignalR terms it is called Hub.
Our hub will be named SoccerResultsHub and will enable to update the home and visitor team, increment score
for each and update the time left.

For some separation of concern (even a demo needs it) here’s a class to manage hold game data

public class SoccerGame

   {

       private Timer _timer;

 

       public event EventHandler UpdateTimeLeft;

       public SoccerGame()

       {

           TimeLeft = 90;

           _timer = new Timer();

           _timer.Elapsed += (sender, args) =>

               {

                   TimeLeft--;

                   if (UpdateTimeLeft != null)

                       UpdateTimeLeft(this, null);

 

               };

           _timer.Interval = 60000;

           _timer.Start();

       }

       public string HomeTeam { get; set; }

 

       public string VisitorsTeam { get; set; }

 

       public int HomeScore { get; set; }

 

       public int VisitorScore { get; set; }

 

       public int TimeLeft { get; set; }

   }

This class will be used in our hub that looks like that:

public class SoccerResultsHub : Hub

  {

      private  static  SoccerGame _game = new SoccerGame();

 

      public SoccerResultsHub()

      {

          _game.UpdateTimeLeft += (sender, args) => UpdateTimeLeft();

      }

 

      public void UpdateHomeTeamName(string teamName)

      {

          _game.HomeTeam = teamName;

          Clients.All.updateTeams(_game.HomeTeam, _game.VisitorsTeam);

      }

 

      public void UpdateVisitorTeamName(string teamName)

      {

          _game.VisitorsTeam = teamName;

          Clients.All.updateTeams(_game.HomeTeam, _game.VisitorsTeam);

      }

 

      public void UpdateTimeLeft()

      {

          Clients.All.updateTimeLeft(_game.TimeLeft);

      }

 

      public void ScoreForHome()

      {

          _game.HomeScore++;

          Clients.All.updateScores(_game.HomeScore, _game.VisitorScore);

      }

 

      public void ScoreForVisitors()

      {

          _game.VisitorScore++;

      }

 

 

  }

}

For each method on our Hub class, SignalR will create corresponding javascript code enables us to invoke from our client side.

Note the Clients.All.<method> , Clients property of Hub class has the connection context, and its type is self explanatory ConnectionContext .

It has several dynamic properties of which we can add method calls to, the SignalR engine will support extending its javascript ,  the All property of Clients

 

Client Side Code

On our HTML document we need to reference jQuery , SignalR base javascript library and the javascript proxy code generated by SignalR for our Hub above.

<script type="text/javascript" src="Scripts/jquery-1.6.4.js"></script>
  

 <script type="text/javascript" src="Scripts/jquery.signalR-1.0.0-alpha2.js">

</script>

 <script type="text/javascript" src="SignalR/Hubs">

</script>

We’d also use knockoutJs and that’s how our entire Html will look like:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title></title>

</head>

<body>

    <label for="txtHomeName">Home Team:</label>

    <input type="text" id="txtHomeName" data-bind="{value : homeTeamName}" />

    <button data-bind="{click: updateHomeTeamName}">Update</button>

    <button data-bind="{click: homeTeamScores}">Scores</button>

    <span data-bind="{text : homeTeamScore}"></span>

    <br />

     <label for="txtvisitorName">visitor Team:</label>

    <input type="text" id="txtvisitorName" data-bind="{value : visitorTeamName}" />

     <button data-bind="{click: updateVisitorTeamName}">Update</button>

    <button data-bind="{click: visitorTeamScores}">Scores</button>

    <span data-bind="{text : visitorTeamScore}"></span>

    <br />

    <span>Time Left:</span>

    <span data-bind="{text : timeLeft}"></span>

    <script type="text/javascript" src="Scripts/knockout-2.2.0.js"></script>
     

      <script type="text/javascript" src="Scripts/jquery-1.6.4.js">

    </script>

   <script type="text/javascript" src="Scripts/jquery.signalR-1.0.0-alpha2.js">

   </script>

       <script type="text/javascript" src="SignalR/Hubs">

    </script>

       <script type="text/javascript" src="GameViewModel.js">

</script>

</body>

</html>

 

Using knockoutJs  lets us have our client code deals with the data itself and doesn’t involve any DOM manipulation

In our javascript code we declare a view-model and inside it declare a member named gameHub. This member will be declared as the Hub connection

to the server. it will use to start the connection, call server methods and extend the client so the server can call functions on it (it is bi-directional right?)

You can see that gameHub member has client and server  members used for both purposes mentioned above

That’s how our javascript code will look like:

 

var viewModel =

    {

        gameHub : null,

        homeTeamName: ko.observable(),

        homeTeamScore: ko.observable(),

        visitorTeamName: ko.observable(),

        visitorTeamScore: ko.observable(),

        timeLeft: ko.observable(),

        homeTeamScores : function()

        {

            this.gameHub.server.scoreForHome();

        },

        visitorTeamScores: function () {

            this.gameHub.server.scoreForVisitors();

        },

        updateScores: function (home, visitors) {

            this.homeTeamScore(home);

            this.visitorTeamScore(visitors);

        },

            updateHomeTeamName : function()

            {

                this.gameHub.server.updateHomeTeamName(this.homeTeamName());

            },

            updateVisitorTeamName: function () {

                this.gameHub.server.updateVisitorTeamName(this.visitorTeamName());

            }

    };

 

$(document).ready(function () {

    

    ko.applyBindings(viewModel);

 

    viewModel.gameHub = $.connection.soccerResultsHub;

    viewModel.gameHub.connection.start();

 

    $.extend(viewModel.gameHub.client,

        {

            updateTimeLeft: function (timeLeft) {

                viewModel.timeLeft(timeLeft);

            },

            updateTeams: function (home, visitors) {

                viewModel.homeTeamName(home);

                viewModel.visitorTeamName(visitors);

            },

            updateScores: function (home, visitors) {

                viewModel.updateScores(home, visitors);

            }

        });

});

 

Summary

SignalR let’s us have bi-directional communication between the client and server. It runs on browsers that support websockets and long-polling

while signalR knows which of those features to use. It depends on jQuery on client side and Newtonsoft.Json (and ASP.NET) on server side.

It is still in alpha stage but sure worth a try,  knowing how to use it will help you create great Http based applications.

 

The entire sample can be downloaded here.

kick it on DotNetKicks.com

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

5 comments

  1. Irvin20 בJanuary 2013 ב 18:45

    Touche. Solid arguments. Keep up the great effort.

    Reply
  2. Dan29 בJuly 2013 ב 14:36

    I had to make _game static in order to avoid multiple hubs being created with multiple clients.

    Reply
  3. Ran Wahle30 בJuly 2013 ב 3:09

    Dan you’re absolutely , it is recommended not to have these fields instantiated with the hub. The downloaded example doesn’t do so.

    I’ve noticed that the example shown does so and I’ll correct it.

    Thanks.

    Reply
  4. Maor K.4 בJuly 2016 ב 0:25

    Hi Ran,
    Im working on a solution where i have two clients who talk to each other using SignalR websockets.
    As Websockets is just a transport layer, i’ve wanted to understand how SignalR will handle messaging.
    for example: should i develop my server differently if i know that the clients will send to each other large amount of 64bit long messages as opposed to just a persistent stream?

    thanks,
    Maor.

    Reply
    1. Ran Wahle
      Ran Wahle11 בAugust 2016 ב 9:48

      Well Maor, SignalR puts some overhead over messages sent over the wire (It could be WebSocket where supported but it can be Server-Send-Events, ForeverFrames, or LongPolling) .

      The overhead signalR puts is rather small however If the server purpose is only for persisting connection between to other customers, you might want to check out WebRtc for direct connection, while the server is used for discovery purposes. This is how you may remove loads from the server.

      Reply