Building A Private Chat Application Using SignalR

Introduction

Here, I will be demonstrating an application to chat privately using SignalR. Before that, we need to know first what SignalR is! SignalR is an open and free library that can integrate real-time functionality into your web applications. There are many areas where SignalR can come in handy to make your application more convenient, integrated, and responsive to the end user. Real-time means having your Server respond as quickly as possible to the client as and when a request is made. 

For instance, we have a requirement to show the user uploading a file and the percentage of that file uploaded on the Server. Or I had encountered a scenario where we had to show the end user who would upload a CSV file with an ‘n’ number of rows and process each row for some validations. 

End user would like to know what is going on in the back-end. So, could we show him how many rows have been processed and how many are left out? Similar to a progress window. Here comes the SignalR magic! Most of us think SignalR would be useful in making chat applications, but NO! It has much more than chat! The makers of SignalR would not have a thought in mind to make a chat application out of it! Much of a story now! Let’s get into a bit of theory!

Theory

We will look into a simple image below, and from that image, we will try and gain some knowledge on the flow: 

Nowadays, every application requires a load of server response in real time to sustain in the market, as user expectations have risen higher. Remote Procedure Calls (RPC) is the concept in the SignalR internally. SignalR provides an API that helps make the RPC between the Server and the client. From the client side, server-side functions are called using JavaScript once the connection to the Server is set. The SignalR API also helps create connections and manage them when required. In simple terms, SignalR provides

  • connection between Server and client,
  • letting the Server call the functions on the client side and from the client side,
  • calling the server side. 

 

That somehow is called “Server-Push”. SignalR starts with HTTP and then to a WebSocket if the connection is available. According to Wiki, “WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.” An advantage of using WebSocket is that both client and server applications can use it. WebSocket is considered the most efficient and consistent communication medium as it can manage server memory properly, is a full duplex communication, and has low latency. These are the considerations made with SignalR that make it more efficient. The SignalR decides the transport based on the browser, i.e., if the browsers support the kind of transport required by the SignalR. We will discuss the kinds of transport next:

HTML 5 Transports

  • WebSockets, as we have already discussed. This transport is considered true-persistent, creating a two-way connection between client and Server if the browser supports it.
  • Server Sent events also called Event Source, which is supported by all browsers except IE.

Comet Transports

Comet, usually,is a web application model in which a long-held HTTP request allows the Server to post data to a client (browser).

  • Forever frame This is supported by Internet Explorer only. Creates a hidden frame making a request to the endpoint on the Server. The server keeps pinging the client or sending the script to the client, thus providing a one-way connection, creating a new connection on every request.
  • Ajax Polling This is long polling, which is never persistent. This polls the request and waits until and unless the response is received from the Server. This introduces latency, and the connection resets.

Practical

Practical

We will create a chat application to explain the flow of SignalR. We install the SignalR and create a hub to which the client will interact, calling the server methods, and in return, the server responds and interacts with the client. You can directly add a new project in VS for the SignalR or create an MVC project and install the SignalR package/libraries from the Nuget.

PM > Install-Package Microsoft.AspNet.SignalR

This is to download all the dependencies required for the SignalR. 

After the successful installation, the above dlls or packages are installed into your project. There will be a class file which needs to be added to the root of your project, which would look like:

 

  1. using Owin;  
  2. Using Microsoft.Owin;  
  3. [assembly: OwinStartup(typeof(SignalRChat.Startup))]  
  4. namespace SignalRChat   
  5. {  
  6.     public class Startup   
  7.     {  
  8.   public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here app.MapSignalR();   
  9.         }   
  10.     }  
  11.  }  

This is an OWIN-based application. Every OWIN application will have a startup.cs class, where the components for the application pipeline are added. The OWIN attribute specifies the property type, the project’s start-up, and the configuration method and sets up the SignalR mapping for the App. Another two script files will be added as we install the packages for SignalR.

These script files are mandatory to be loaded onto the .cshtml page to activate the SignalR. Let’s look into the code immediately: We need to add a new hub class inside a Hub folder. Let’s name that LetsChatHub.cs, which would look like: 

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using Microsoft.AspNet.SignalR;  
  6. namespace LetsChatApplication.Hubs  
  7. {  
  8.     public class LetsChatHub: Hub  
  9.     {  
  10.         public void Send(string name, string message, string connId)  
  11.         {  
  12.             Clients.Client(connId).appendNewMessage(name, message);  
  13.         }  
  14.     }  
  15. }  

The above send method accepts the parameters, name (which you would be giving once you navigate onto the url), the message (which the user would be sending from the UI). The other parameter is connId, which would help us have chat private and not send to every user who navigates to the site. If you would like to have every user receive and send the messages to those who navigate to the URL ,To allow every user the access, the code you change as below:

  1. namespace LetsChatApplication.Hubs  
  2. {  
  3.     public class LetsChatHub: Hub  
  4.     {  
  5.         public void Send(string name, string message)  
  6.         {  
  7.             Clients.All.appendNewMessage(name, message);  
  8.         }  
  9.     }  
  10. }  

The Send method is requested from the client with the parameters after the connection is set on the client side, and once the Server receives the request, it processes and sends back the response to the client using the appendNewMessage. This appendNewMessage method is added on the client side to receive the response and display on the UI to the client. You need to add a controller, lets suppose: “LetsChat” with an action “LetsChat”, add a view to that with the below code. The client-side code would look like below:

  1. @{  
  2.     ViewBag.Title = “LetsChat”;  
  3.   
  4. }  
  5.   
  6.   
  7. <h2>Lets Chat</h2>  
  8. <link href=”~/Content/sweetalert.css” rel=”stylesheet” />  
  9.   
  10. <div class=”form-group col-xl-12″>  
  11.     <label class=”control-label”>Your connection Id</label><br />  
  12.     <input type=”text” class=”col-lg-12 text-primary” id=”frndConnId” placeholder=”Paste your friend’s connection Id” /><br /><br />  
  13.     <label class=”control-label”>Your Message</label><br />  
  14.     <textarea type=”text” class=”col-lg-10 text-primary” id=”message”></textarea>       
  15.     <input type=”button” class=”btn btn-primary” id=”sendmessage” value=”Send” /><br /><br />  
  16.     <img src=”~/Content/smile.jpg” width=”20″ height=”20″ id=”smile” style=”cursor:pointer”/>  
  17.     <img src=”~/Content/uff.jpg” width=”20″ height=”20″ id=”ufff” style=”cursor:pointer” />  
  18.     <div class=” container chatArea”>  
  19.         <input type=”hidden” id=”displayname” />  
  20.         <ul id=”discussion”></ul>  
  21.     </div>  
  22. </div>  
  23. <br />  
  24. <input type=”hidden” id=”connId” />  
  25.   
  26. <!–Reference the autogenerated SignalR hub script. –>  
  27. @section scripts {  
  28.     <script src=”~/Scripts/jquery-1.10.2.min.js”></script>  
  29.     <script src=”~/Content/sweetalert.min.js”></script>  
  30.     <script src=”~/Scripts/jquery.signalR-2.2.0.min.js”></script>  
  31.     <script src=”~/signalr/hubs”></script>  
  32.     <script>  
  33.         //var userName = “”;  
  34.         //var sessionVal = ”;  
  35.         $(function () {  
  36.             // Reference the auto-generated proxy for the hub.  
  37.             var chat = $.connection.letsChatHub;  
  38.               
  39.             debugger;  
  40.   
  41.             // Create a function that the hub can call back to display messages.  
  42.             chat.client.addNewMessageToPage = function (name, message) {  
  43.                 // Add the message to the page.  
  44.                 $(‘#discussion’).append(‘<li><strong>’ + htmlEncode(name)  
  45.                     + ‘</strong>: ‘ + htmlEncode(message) + ‘</li>’);  
  46.             };  
  47.             // Get the user name and store it to prepend to messages.  
  48.             swal({  
  49.                 title: “Lets Chat!”,  
  50.                 text: “<span style=’color:#f8bb86;font-weight:700;’>Enter your name:</span>”,  
  51.                 type: “input”,  
  52.                 html: true,  
  53.                 showCancelButton: true,  
  54.                 closeOnConfirm: true,  
  55.                 animation: “slide-from-top”,  
  56.                 inputPlaceholder: “Your Name”  
  57.             },  
  58.             function (inputValue) {  
  59.                 userName = inputValue;  
  60.                 if (inputValue === false) return false;  
  61.                 if (inputValue === “”) {  
  62.                     swal.showInputError(“You need to type your name!”);  
  63.                     return false;  
  64.                 }  
  65.                 $(‘#displayname’).val(inputValue);  
  66.             });  
  67.             // Set initial focus to message input box.  
  68.             $(‘#message’).focus();  
  69.             $(‘#message’).keypress(function (e) {  
  70.                 if (e.which == 13) {//Enter key pressed  
  71.                     $(‘#sendmessage’).trigger(‘click’);//Trigger search button click event  
  72.                 }  
  73.             });  
  74.             $(“#smile”).click(function () {  
  75.   
  76.             });  
  77.             // Start the connection.  
  78.             $.connection.hub.start().done(function () {  
  79.   
  80.                 $(‘#sendmessage’).click(function () {  
  81.                     // Call the Send method on the hub.  
  82.                     var connId = $(“#connId”).val();  
  83.                     var frndConnId = $(“#frndConnId”).val();  
  84.                     var finalConnId = frndConnId == “” ? $.connection.hub.id : frndConnId;  
  85.                     chat.server.send($(‘#displayname’).val(), $(‘#message’).val(), finalConnId);  
  86.                     $(“#connId”).val($.connection.hub.id);  
  87.                     if (frndConnId == “”) {  
  88.                         swal(“You connection Id”, $.connection.hub.id, “success”);  
  89.                     }  
  90.                     // Clear text box and reset focus for next comment.  
  91.                     $(‘#discussion’).append(‘<li><strong>’ + htmlEncode($(‘#displayname’).val())  
  92.                    + ‘</strong>: ‘ + htmlEncode($(‘#message’).val()) + ‘</li>’);  
  93.                     $(‘#message’).val(”).focus();  
  94.                 });  
  95.             });  
  96.      
  97.         });  
  98.     // This optional function html-encodes messages for display in the page.  
  99.     function htmlEncode(value) {  
  100.         var encodedValue = $(‘<div />’).text(value).html();  
  101.         return encodedValue;  
  102.     }  
  103.     </script>  
  104. }  

We have a normal UI in place to add your message and send button to call the server methods. Let’s understand the code above part by part.

  1. var chat = $.connection.letsChatHub;  

Here, we set the connection to the Hub class. As you can notice, letsChatHub is the same hub class file name we added to set up the Server. The convention as follows, the intial of the methods or the class name starts with lowercase. From here, we use chat to access the Send method.

  1. $.connection.hub.start().done(function()  
  2.             {  
  3.             $(‘#sendmessage’).click(function()  
  4.                          {  
  5.                         // Calls the Send method on the hub. chat.server.send($(‘#displayname’).val(), $(‘#message’).val(), finalConnId);  

chat. Server.send,is self explanatory, it sets the chat connection to call the Server Send method once the connection is set and started.

  1. chat.client.appendNewMessage = function (name, message) {  
  2. //  
  3. }  

This is called when the Server receives the request and calls back the method on the client side.

How Would the Sample Work?

The sample provided for download will be a few instructions to follow:

  • When you navigate to the LetsChat/LetsChat route, an alert will pop up asking you for the name with which you would like to chat. Sweet Alert.
  •  
  • Once you enter the name, you see a textbox that asks you for “Your friend’s connection ID”, but since you are starting the chat, you send a message, and another pop-up comes up with your connection ID, which you need to share with your friends to share your message. Remember, only those who use your ID while chatting can see and send messages to you.
  • When your friend navigates, he ought to generate his connection ID and share it with you to set up your connection completely. Thus, you need to have the connID to whom you will be sending and vice-versa with your friend. Then just chat. 

If you want to send a message to all and make that common, use the Clients.All code snippet to send all. Another exciting thing, which was figured out, is the use of @section scripts{}, that lets the Signal R scripts render and active on your page, and also, using the @section scripts provides your code a good outlook.

 

Share and Send Files Using SignalR !

Ooops!! Nice question, right? Ideally, It is not advised; rather, I would not recommend sending or sharing files using Signal R. There is always a better way to accomplish that. Using API, you can have an upload area and use SignalR to show the progress, and once the upload is complete, update the user regarding the completion and generate a download link on the UI for the users to download and view the file. This is only sometimes the best idea, but it is just another idea. 

Conclusion

This is just a simple Chat application you can use to chat with your friends if you host on Azure or any other domain. But again, SignalR is not just more than much. There are a lot of other practical uses of SignalR. I will be sharing more of SignalR’s utility in future articles.

More Posts

GENeration INVINCIble culture

A journey has just begun to create a culture, not an organization.

INVINCIX for Start-ups

In this era of digitization, we at INVINCIX are on a mission to digitize 500+ Start-Ups during the next 2 financial year FY 2021-22 And 2022-23.

Business eXperience delivery – BXD

Direct dealing with the business definition and objective .

Focus on : Optimized investment

Continuous improvement on efficiency is a learning curve.

High operations efficiency index

Deeper understanding of each other’s working style leading to long-term benefits.

Believe and philosophy

We are committed to build a GenInvinci organization that has the ability to “Engage”, “Innovate”, “Invent” And “Excel”

Corporate responsibility

A sense of satisfaction when you touch the heart with emotion.

INVINCIANS

We will keep our feet grounded, to ensure, your head is in the cloud.

Achievers

Recognizing the outstanding Invincians

Client speak

A moment to look back the accomplishment.

Accolades

It means a lot to us.

Knowledge Corner

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Career

Join our Growing Team And Proud To Ba An INVINCIANS.

Contact us

Let's connect and find the solutions you need. Our team is ready and waiting to assist you with any questions or concerns you may have.

Business transformation and re-engineering

Digital transformation framework enables excellence in “Innovation”, “Agility” And “Responsiveness”

IT process and automation services

The existence of software industry started with automation of manual processes. The automation has evolved over a period of time and termed as “Digitalization Services”.

Software development services

AD4P Experience – Unlock the potential of IT to ensure your application is future enabled .

Product engineering

Original thinkers are rare and original ideas are precious. A product is always originated by a great idea.

Simplified consulting

Our consulting will hold your hand and be part of you, through out transformation journey.

User experience services

Clear emphasis on the experience not on the interface make us a class apart .

Quality assurance

As enterprises look to software as a source of competitive advantage, they demand quality-at speed and scale.

Data management and data science

As enterprises look to software as a source of competitive advantage, they demand quality-at speed and scale.

E-board Online

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Barcode inventory

Quick inventory management using barcodes .

Routing matrix

Cost effectiveness routing with ease of customer satisfaction.

DigiStack

Unleashing efficiency in the service industry through automation .

Vendor management system

Elevate efficiency and facilitate success with vendor management system.

Spare parts management system

Simplifying your stock validation & management process.

Agile office

“Swift and Simple” office automation

Telto

Make your service station digital

Clidok

Your doctor is a click away

Tawny

A watchdog for your digital infrastructure

White patches In black-box

Extracting meaningful data from ocean of data

Vendor management system

connecting hospitality industry smoothly

X Solutions

A mini ERP for all your need

Instablood

Connecting world via blood

Invoicedge

Simplify e-Invoicing with our secured SaaS-based APIs

Workshop calendar

Browse our workshop calendar for upcoming events and opportunities to expand your knowledge and skills.

Courses

Explore our diverse range of courses designed to cater to various interests, offering opportunities for personal and professional growth

Cuttack

Head Office
Sharadha Bhawan, Rajendra Nagar, Cuttack, Odisha 753010

Bhubaneswar

Branch Office
Plot No.353, 1st Floor, Infocity Ave, Sishu Vihar, Patia, Bhubaneswar-751024, Odisha, INDIA

Singapore

Branch Office
60 eu tong sen street #02 03 furama city center Singapore 059804

UK

Branch Office
28 Rye Croft Avenue, Twickenham, London, Tw2 6hr

Vietnam

Branch Office
02nd Floor, Saigon Paragon Building, No.3 , Nguyen Luong Bang Street, Tan Phu Ward, District 07, Ho Chi Minh City, Vietnam