Recap: Creating a demo of real-time communication app using AspNetCore.SignalR

Published: Jan 9, 2018

I believe the best way to learn a new technology is to create a proof of concept demo application. In this post, I would like to give you a brief recap of what I’ve learned about Microsoft.AspNetCore.SignalR while creating a real-time Planning Poker app.

A user's hand of Planning Poker cards

It’s a tiny web application which I built over the weekend and which you can try out here. Note, for the first time it may take up to 20 seconds for applications startup. To test it you have to join the same group from two different browser tabs or browsers. The source code can be found on Github.

The Recap

Planning poker is a tool frequently used by development teams to estimate how much effort it takes to develop a certain feature. In our team, we were using physical cards. But as a Web developer, I was wondering if I could create an application which allows to do it online and real-time.

The requirements for this app are:

  • It should allow us to create or join a planning group,
  • List group members who are online,
  • Play card (give estimate) and notify rest of the members about cards currently played,
  • Reveal the cards and show the estimates to all group members simultaneously,
  • And start a new game plus clear previously played cards to all group members.

To fullfill requirements above, I am going to use AspNetCore.SignalR library. Which will allow to communicate between browsers a.k.a clients.

By the way, for the frontend, I am using the vue.js client-side framework. And vuetify, the material components library built on top of vue.js.

What's SignalR?

In his article “ Introduction to SignalRPatrick Fletcher explains

ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of adding 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.

As we can read the main functionality SingalR provides is pushing data to the Client. Which means that a browser doesn’t need to make a request to pull data from the backend. Instead, the server side code can directly invoke a JavaScript on the browser by sending a message that client-side code is listening to.

The following example of server-side method accepts group name and a message as a parameter and immediately sends the message to all connected Clients of a certain group.

// C# server side method
public async Task Send(string groupName, string message)
{
await Clients.Group(groupName).InvokeAsync("EVENT_SENT", message);
}

Meanwhile, the client side script is waiting for an event invoked from server and process the received message.

/* JavaScript example of SignalR client's side */
/* Connect to the backend's Hub */
let pokerHub = new HubConnection(HUBS.POKER);
/* Attach event listener to Send event */
pokerHub.on("Send", message => {
// Process the message
});
/* Start the real time communication with the hub */
pokerHub.start();
/* Message to other clients by executing backend's Send() method */
let sendMessage = message => pokerHub.invoke("Send", message);

To start developing you have to add the reference to SignalR package to the AspNetCore project.

<ItemGroup>
<PackageReference Include=”Microsoft.AspNetCore.SignalR” Version=”1.0.0-alpha2-final” />
</ItemGroup>

And must configure the routing for SingalR Hubs in Startup.cs

app.UseSignalR(routes => {
routes.MapHub<Poker>('Poker');
});

SignalR Hub

The main participation in real time communication with SignalR is the Hub. It acts as a glue and allows to invoke server side code from client side and execute client-side code from the backend.

To create a hub one must create a class derived from Microsoft.AspNetCore.SignalR.Hub. This class allows us to get the connected Clients and Groups which are linked to the Hub. As well as getting the context of the Client who has invoked server-side code.

Microsoft.AspNetCore.SignalR.Hub is also responsible for calling OnConnected and OnDisconnected methods each time user visits or leaves a web page on which client-side hub connections are made.

In derived class, we can define our public methods that clients can call, for example

// Poker.cs
public class Poker : Hub
public async Task Send(string message)
{
await Clients.Client(Context.ConnectionId).InvokeAsync(“Send”, message);
}
}

The above code will send the Message back to the same client which called Send method. In this case, the receiving Client is determined from the current HubCallerContext and its ConnectionId property.

HubCallerContext

In the previous example of Send() method, you can see that we use Context.ConnectionId to target and send a message to specific Client. Hub class has a property Context of type HubCallerContext which holds an information about the Clients who are connected to the Hub.

From this class, our server-side code can get a ConnectionId which is a GUID for each Client’s connection to the Hub. As well as ClaimsPrincipal of the calling Client and HubConnectionContext with more information about the connection itself.

I will not go into more details about this context, just want to note that in this demo I use HubCallerContext.HubConnectionContext to map the online users with their data into an in-memory dictionary.

private readonly ConcurrentDictionary<HubConnectionContext, UserDetails> _usersOnline;

Client-side connection to the Hub

To start communicating with the server side we have to install @aspnet/signalr-client package from npm in our client-side application and set up HubConnection in the client-side application’s startup JavaScript or any other JavaScript, where we want to use the SignalR.

import { HubConnection } from '@aspnet/signalr-client';
let pokerHub = new HubConnection("/poker");
pokerHub.on("Connected", message => { /*handleConnected */ });
pokerHub.on("Disconnected", message => { /*handleDisconnected */ });
pokerHub.start();

In the example above I have first created a new HubConnection and passed the server side's Hub route as a parameter. This route should match the one, configured in AspNetCore Startup.cs class.

Next, we have to register the methods which we will allow to invoke from the server side. And set the corresponding handler functions which will receive server-sent Message as a parameter. The message can be a primitive type or a JSON object in case we are passing a complex object to Client’s method.

After this small setup, we can start the Hub and handle the Connected and Disconnected methods when invoked from the server side.

Finally the last JavaScript snippet. To execute a server side method we need to perform invoke() method’s call on the Client’s HubConnection. It will then invoke the server side Hub’s Send method and will pass “message” string as a parameter to it.

pokerHub.invoke("Send", "message");

Conclusion

I created this proof of concept web application to learn the basics how AspNetCore.SignalR library works. And I must admit it was not that hard as I thought before. But let's also admit, this demo is just the tip of the iceberg of all the possibilities SignalR provides to developers.

Hopefully, this will encourage you to try it out in your web applications. And will help you to make the user experience of the applications more exciting and more productive.

Once more before I go, you can try out the app on http://signalr-vuejs.azurewebsites.net or see the source code on https://github.com/AndrejsAbrickis/PlanningPoker

JavaScript, Aspnetcore, Signalr, Web Development, Dotnet Core