Thursday, May 25, 2017

Creating SignalR web application step by step

   
   Microsoft introduced SignalR in 2013, It is an open source project. Developers can add real-time web functionality to their applications with SignalR. I am sure you saw/heard about all SignalR chat applications in those days. I wish SignalR developers in Microsoft, spent more time on creating different demos to show possibilities of real-time web functionality.

   SignalR takes the advantages of WebSocket technology which became available with HTML5.  On SignalR page, It says "incredibly simple real-time web". I agree with that if you have one server in your production environment. If you have webfarm then things will get really tricky really fast. Think about it, one user can open multiple tabs, you need to keep these connection information somewhere in the server side. If you have multiple servers then not all of the connections might be created on the same server. When you need to send a realtime message to a user, you need to send message to all open connections of that user in different servers.

    I have created a simple SignalR application to share, It is not a chat application so yay! I want to create an ecommerce admin page which is going to display what is getting sold in real time. Let's create a new web application and add SignalR references from NuGet first.


     Next step is creating a startup class in our project. If you have one already, you need to add the following code into it. This code enables the SignalR in your application.


So far so good, now we need to add our hub class to our project. Let's create a new folder named Hubs and right click on it to add a new SignalR Hub class by using Add New Item option.


I am going to name the new file ProductHub since it's going to send/receive messages about the products.


When you create it, you might end up with Hello function in it. Hello function is not going to cut it so I am going to change that. I want to update my page when a product is sold. So I am going to replace Hello function with ProductIsSold()


Now we need to move to the client side, and set this function in client side. When we call ProductIsSold() in server side, SignalR is going to send a message to all clients and run productissold jscript function in client side. First we need to add the jscript references to our client side.


       We need to add Jquery reference and SignalR reference to the client side. SignalR automatically creates javascript scripts to connect server side code to client side. That's why we need a reference to SignalR/Hubs path in our client side. I am not sure if this folder supposed to be created when you install the SignalR from Nuget or not. I always had to create this folder myself.  Be sure that this folder exists in your project, SignalR will not work without it. 
      Now I am going to test if the client side can connect to server side with the following code.


  Nothing fancy here, all we are trying to do is to connect the server side and display that connection was successful. If you are having problem in this step, check if the SignalR/Hubs folder exists in your project.

  Users might lost the connection for some reason and we need a solution to handle that situation. Following code tries to reconnect every 5 minutes if the client side disconnects for some reason. Be careful when you are picking the waiting time to connect again, making that number small might cause more problems.


    Now, we need to add a function which is gonna get called when SignalR receives a message from the server side. Function name has to be match to the server side's function name. I created a function named ProductIsSold() in server side earlier, I am going to create a function with the same name in client side. 

So far here is the all code I have added to the client side.


    Client side looks okay for now, I need to go back to the server side and create a function which will send a message to this page when a customer makes a purchase. For that I am going to create a new Controller and add the following code to it. ProductIsSold() is a dynamic function, and you want to be sure that the name of the function is matching to client side's function name. Also I am sending a message to all connected users here to demo the page. Depending on your requirements, you might want to send message to a user or group of users. SignalR has solution for all of these situations.


     So far, here is what our application looks like. The Products are listed in the admin page, SignalR is working and connected. Also when a customer buys a product we are receiving a message in real time. We want to know what product is sold rather than a general message like this. That's what I am going to work on next. I want to tag all the products on the page with their productid and pass the sold product's productid to the page so we can highlight the product box. Let's count the sold products too, I will add a counter under each product.


      Here is my ProductIsSold function. SignalR fires this function automatically when it receives a message with the productid. I find the product box by using the product id. CSS animates the background of the box and updates the counter. 


 Here is the page for customers.

      Admin page shows which product is sold in real time. 
You can find the source of the application in my github repository.



     SignalR is scalable and it has some options including SQL Server, Redis  I use Redis for scaling  SignalR. You need to be sure that all of your servers shares the same machine key so they can decrpyt a connectionid which might be created by a different server in your webfarm. I am going to write about the SignalR scaling options later.

2 comments:

  1. It would have been a great help if reconnect and reliability of messages would have been demonstrated

    ReplyDelete
  2. Thanks. Good article. Would you demonstrate Authentication and Authorisation please?

    ReplyDelete