SignalR Tutorial, Part 1: A Simple Chat Application using SignalR and AngularJS
Overview
ASP.NET SignalR provides an easy way to add real-time web functionality to applications. Real-time web functionality is the ability to have server code push content to connected clients instantly as it becomes available, rather than having the server wait for a client to request new data.
SignalR provides a simple API for creating server-to-client remote procedure calls (RPC) that call JavaScript functions in client browsers (and other client platforms) from server-side .NET code. SignalR also includes API for connection management (for instance, connect and disconnect events), and grouping connections.
SignalR is a suitable technology to create chat applications or real-time dashboards which needs duplex communication between clients and the server.
The client can be of any applications such as web or windows applications, mobile application, or etc.
To get more detail explanation on what SignalR is see this: http://www.asp.net/signalr/overview/getting-started/introduction-to-signalr
Development environment
Visual Studio 2015 and .NET 4.6 is used in this tutorial. The same steps are applicable if you are using Visual Studio 2013 and .NET 4.5.
We use AngularJS which is a framework to create dynamic web applications.
You need to have IIS 8 installed as well as WebSocket protocol to be enabled on your machine.
Setting up the project
-
In Visual Studio create a new empty ASP.NET MVC web application with no identification. Name the application SampleChat.
-
Install SignalR via NuGet package manager. You can use the Package Manager Console, or the right click on the project and select Manage NuGet Packages.
Search for SignalR and install the package.
Alternatively you can install the package using the following comand in NuGet Package Manager Console:
Install-Package Microsoft.AspNet.SignalR
Notice that after installation it adds jquery.signalR and jquery javascript libraries to the Script folder. SignalR is using jQuery in order to communicate with the client.
-
Create and configure Owin Startup. Notice that after installing SignalR a readme file is opened which is guiding you configure Owin startup. To do so add an Owin Startup Class to project and name it Startup.cs.
Modify its content as below:
namespace SampleChat { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } }
-
Install AngularJs core via NuGet package manager. You can use the Package Manager Console, or the right click on the project and select Manage NuGet Packages.
Search for AngularJs core and install the package.
Alternatively you can install the package using the following comand in NuGet Package Manager Console:
Install-Package AngularJS.Core
-
Add a JavaScript file in Scripts folder for our chat application and name it sampleChat.js.
Create the SignalR Hub
SignalR hubs are created on the server where they listen to any incoming request and can invoke methods on any number of clients which are connected to them. The server creates long running duplex connection to the clients which connects to it via WebSocket, Server Send Event, Forever Frame, or Long Polling respectively based on the server and client infrastructure.
-
Add a SignalR Hub Class to the project and name it ChatHub.
Note that out ChatHub class derived from the Hub base class which provides methods that communicate with SignalR connections that connected to a Microsoft.AspNet.SignalR.Hub.
It is a good practice to create a folder called Hubs and place all Hubs classes inside that. Since our project is a simple application I created that in our project root.
-
The Hub Class already includes a method called Hello(). Clients can call this method via SignalR jQuery library and pass any data they want. This method on the sever then is getting All the Clients and invoking their JavaScript method called hello(). This method is not of our interest. Modify it as below so it can get two string values as parameter. Name and the message which user sends on the client.
public class ChatHub : Hub { public void SendMessage(string name, string message) { Clients.All.broadcastMessage(name, message); } }
Clients called this method and send a name and message as string. Then the Hub will broadcast that name and message to all client applications which are connected to it. So all clients will be instantly updated with the new message.
Create Client Application
Now that we have setup our Hub server we can create our client application. You can either use an MVC razor view or a simple HTML page. For simplicity we use a simple HTML file.
-
Add an HTML file to the project and name it index.html.
-
Add script reference to jquery, angular, and jquery.signalr JavaScript files as well as our own sampleChat.js file. You can do it by drag and drop the JavaScript files from Solution Explorer to the end of HTML body section. Take note that the order is important.
<!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8" /> </head> <body> <script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery.signalR-2.2.0.js"></script> <script src="signalr/hubs"></script> <script src="Scripts/angular.js"></script> <script src="Scripts/sampleChat.js"></script> </body> </html>
Notice the third script reference <script src=”signalr/hubs“></script> does not exist physically. This is a JavaScript proxy created by the SignalR to enables the clients to connect the server hub. You can paste the URL on the browser and see the content of the file.
Notice that at the bottom the server proxy contains the sendMessage method accepting two parameters which is map to our Hub’s SendMessage method.
You can also create this proxy manually which is useful when you want to connect to this hub from an Android phone for instance.
-
Open sampleChat.js and modify it as below:
(function () { var app = angular.module('chat-app', []); app.controller('ChatController', function ($scope) { // scope variables $scope.name = 'Guest'; // holds the user's name $scope.message = ''; // holds the new message $scope.messages = []; // collection of messages coming from server $scope.chatHub = null; // holds the reference to hub $scope.chatHub = $.connection.chatHub; // initializes hub $.connection.hub.start(); // starts hub // register a client method on hub to be invoked by the server $scope.chatHub.client.broadcastMessage = function (name, message) { var newMessage = name + ' says: ' + message; // push the newly coming message to the collection of messages $scope.messages.push(newMessage); $scope.$apply(); }; $scope.newMessage = function () { // sends a new message to the server $scope.chatHub.server.sendMessage($scope.name, $scope.message); $scope.message = ''; }; }); }());
-
Modify the index.html as below:
The first textbox binds to name scope variable and the second textbox binds to message scope variable.
The button calls our controller newMessage() method which is responsible to send the new message to the hub.
With the ng-repeat we loop though the messages collection and displays on the view.
<body ng-app="chat-app"> <div ng-controller="ChatController" > <div> Name: <input type="text" ng-model="name" /><br /> Message: <input type="text" ng-model="message" /><br /> <input type="button" value="Send" ng-click="newMessage()" /> </div> <div> <ul> <li ng-repeat="chat in messages"> <span ng-bind="chat"></span> </li> </ul> </div> </div> <script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery.signalR-2.2.0.js"></script> <script src="signalr/hubs"></script> <script src="Scripts/angular.js"></script> <script src="Scripts/sampleChat.js"></script> </body>
-
Browse index.html on two different browsers and send messages.
how to do this exact application using in webapplication or webform
Keys here are you need to:
1. install SignalR (best is via Nuget),
2. add your Hub (which is a class derived from Hub),
3. add your client handler, and lastly
4. start your hub which in case of WebForms you should do it in Global.asax.cs.
This might be helful: http://www.codeproject.com/Articles/526876/AddingplusSignalRplustoplusanplusASP-NetplusWebFor
interesting! mvvm right?
nice work bro!
all of this is easy stuff. The real challenge is making a swift client call remotely a signalr. It is too hard; therefore, everyone avoids it and just give simple js client running on the same server
Great tutorial ….Question for the OP:
How do you determine when it is more appropriate to use SignalR and when it is more appropriate to use AngularJS? Or when to combine both ?
These are totally two different technologies. SignalR enables server to client communications, AngularJS is a client side framework makes it easier to develop dynamic webpages. The main subject of this tutorial is the SignalR and how it enables server to client message broadcasting. The AngularJS here is just a client side framework I used to present data on the client. Here AngularJS can be replaced with any other Javascript frameworks, or even pure Javascript or JQuery.
I was not sure if Angular with it’s 2 way databinding could actually replicate this, however I guess there is no way of knowing if the data on the server changes unless a push occurs. So I guess the only equivalent technology that could currently accomplish this is by using Meteor correct?
Great post and good to get into SignalR, but it has some typos:
End of the SampleChat.js file should be:
” };
});
}());”
Here, the first 2 semicolons are missing.
You say “Install-Package Microsft.AspNet.SignalR”
Of course this has to be Microsoft instead of Microsft π
Thanks Erwin noticing the typos π I have fixed accordingly.
I was trying to follow your tutorial and couldn’t display a message after i pressed a send button.
Please download the source code and compare if you missed anything. If couldn’t solve, send me your source so I check for you. If you follow the exact steps it should be working.
Not sure if there is something wrong with the package,
But I actually encounter this problem
And it’s not until I install the exact package on the source code downloaded (AngularJS 1.4.4 and SignalR 2.2.0 instead of the default 1.6.5(?) and 2.2.2) that the project is actually working
Thanks for such a great post. I have a requirement where in i want to access SignalR service from HTML pages that are not part of the project and on other server. I tried replacing jQuery reference with CDN link and providing server url to hub connection but it did not work.
//server where signalR is running
$.connection.hub.url = ‘http://localhost:25466/’;
var chat = $.connection.chatHub;
Great Post
can u guide me to online users and group chat and post image and video
Thanks for you comment and interest. This post is only explaining the basics of SignalR technology. With a little twist you will be able to append users and group management and post whatever media you want. At the moment I don’t have any plan to write any post about it.
Awesome post…
I am getting below error.
SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.
Please help.
$.connection.chathub doesnot get initialized with current versions of jquery and jquery signalR libraries.
I had to change it to older versions.
hubs:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error)
angular.js:12416 Error: SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. .
I am trying this code and it doesn’t run. Also when I navigate to http://localhost:12907/signalr/hubs url, i get error
Could not find a part of the path ‘~\SampleChat\SampleChat\SampleChat\bin\roslyn\csc.exe’.
Can some one help me please?