Written by Irmak Tevfik on 15 - Mar - 2015

Simple SignalR tutorial with a sample Project

Today we have a simple article explaining how to implement SignalR to a simple web project. I thought it would be better to have a sample project to select seats across users. Simple idea can be extended to be used on cinemas, online Bus seats selection etc... as seen below:

During this tutorial we will be explaining the basic working principle of Signalr and how does the connection has been setup and maintained, so lets begin.

1- CREATING AN EMPTY ASP.NET WEB APPLICATION AND REGISTER SIGNALR
So lets's begin with creating an empty Web application and call it PlaneSeats.


For this sample project we will only be needing a simple html page so there is no need to select MVC or other engine packages to be included. So lets go ahead and select empty project.



Once our solution is ready, lets add our Signalr NuGet package to our solution. Simply right click to PlaneSeats project, go to Manage NuGet Packages... and search online for the NuGet package "Microsoft.AspNet.SignalR". Adding this package will also be installing dependent packages to the project such as OWIN.



Thanks to Microsoft SignalR team, we will be having a useful readme file generated on visual studio right after we included the NuGet. Basicly we will be following what it says. 



So lets go ahead and add an OWIN Startup class to out project. Once you right click to the project, it should be coming up on the "Add" menu as shown below.



Basically we will be needing this class to tell the hosting environment we will be registering and using SignalR components on application pipeline. Once we add, lets include the following as generated on readme.txt

using Microsoft.Owin;
using Owin;
using MyWebApplication;
 
namespace MyWebApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

2- ADDING HTML, HUB AND USING SIGNALR
Now, I have included the full project with CSS and js files at the end of the article to be downloaded. For this time I will add a HTML page and name it as "Homepage.html". This page will be having the basic html and css layout for this demonstration. Once I have included the "Images" folder and html page. Our solution should look like:


Lets move on to our page as we have some crucial information to go through. Please note that we need to include SignalR scripts on our page along with JQuery. So our page header will be having references to both as shown below. Please make sure their path exists!!.
<script src="/scripts/jquery-2.1.3.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.signalR-2.1.2.js"></script>
<script src="/SignalR/hubs"></script>

Now, you will be wondering, why we do not have any path called "/SignalR/hubs" on our project. Simply, run the project and browse "http://localhost(or whatever you are hosting on)/signalr/hubs" and you will be witnessing the magic. Basically, once we register SignalR to our project and reference it, it will be creating proxies to be connected to our Hubs that we will be creating now.



Now, lets create our Hub to be used. We will be opening connection on our clients to our Hubs to get/send data to the server. Lets go ahead and add a "SignalR Hub Class (v2)" to our project as shown below and name it as PlaneHub.cs


Default class will come up with a method called "Hello". In the begining it might not make any sense but briefly, what it does is if any of the client windows invokes this "Hello" method, it will be pushing hello function to "all" of the "clients". So if any client says hello, "Clients.All.hello" line makes sure that every open client connection gets the greeting :)
Lets move on to our project and change the class content as below. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;
 
namespace PlaneSeats
{
     public class PlaneHub : Hub
    {
        //just added to create dummy user Id :)
        static int userId;
 
        private static List<PlaneSeatsArrangement> allSeats = new List<PlaneSeatsArrangement>();
 
        public void CreateUser()
        {
            userId++;
            Clients.All.createUser(userId);
        }
 
        public void PopulateSeatData()
        {
            var returnData = Newtonsoft.Json.JsonConvert.SerializeObject(allSeats);
            Clients.All.populateSeatData(returnData);
        }
 
        public void SelectSeat(int userId, int seatNumber)
        {
            //create document model
            var planeSeatsArrangement = new PlaneSeatsArrangement() { SeatNumber = seatNumber, UserId = userId };
            allSeats.Add(planeSeatsArrangement);
            var returnData = Newtonsoft.Json.JsonConvert.SerializeObject(planeSeatsArrangement);
            Clients.All.selectSeat(returnData);
        }
    }
 
    public class PlaneSeatsArrangement
    {
        [JsonProperty(PropertyName = "userid")]
        public int UserId { get; set; }
 
        [JsonProperty(PropertyName = "seatnumber")]
        public int SeatNumber { get; set; }
    }
}

Ok, we might not be happy for using a static variable but lets ignore it :) Let me go through the methods and how we are going to use them on the page.
CreateUser: It is useless but it increments the userId every time a browser opens up.
PopulateSeatData: Whenever a client navigates to homepage.html, it will be passing the seats data to the client.
SelectSeat: Whenever a client selects a seat, it will be pushing the seat data to all of the clients.

So lets move on to our html page and examine all parts we used. Please note that, whenever you have included a method to your hub and rebuild your project, it will be reflected on your proxies. 
So you can browse "/signalr/hubs" and examine the changes. Also it is very important to know that whatever the name of your method is, it will be accessible as in "camel Casing" on client side, just becareful.

If we follow the codes step by step:

STEP 1:
We define a variable to hold the connection. we will be using this variable to access our hub methods.
// Defining a connection to the server hub.
var myHub = $.connection.planeHub;

STEP 2 (OPT):
// Setting logging to true so that we can see whats happening in the browser console log. [OPTIONAL]
$.connection.hub.logging = true;

STEP 3:
Once ready, start the connection
$(function () {
    //// Start the hub
    window.hubReady = $.connection.hub.start();
});

STEP 4:
For our project, once the hub connection is set up, we need to get the seats data and create user. So we add this function
$.connection.hub.start().done(function () {
    // Call the server side function AFTER the connection has been started
    myHub.server.createUser();
    //invoke for the user data
    myHub.server.populateSeatData();
});

STEP 5:
Rest is actually simple, whenever we click to the seats, we invoke selectSeat method with the neccessary parameters.
$('.' + settings.seatCss).click(function () {
    if ($(this).hasClass(settings.selectedSeatCss)) {
        alert('This seat is already reserved');
    }
    else {
        myHub.server.selectSeat(userId, $(this)[0].innerText);
    }
});

Feel free to digg the codes on GitHub 
https://github.com/irmaktevfik/PlaneSeats/ 

Enjoy Coding:) comments powered by Disqus