In this post I will show how to use SignalR in an Angular project with an asp.net core backend.

SignalR

SignalR is a .Net library for adding realtime updates to web applications. Instead of the typical client side pull based workflow, SignalR enables notifications to be pushed from the server to the client. You can think of it as a .Net counterpart to Socket.io from the Javascript community.

One good use case of this is status updates in the UI from a long running process on the server. Instead of polling for server updates in the client code, SignalR provides the glue to push notifications directly to the client from the server. SignalR works best over websockets since this is the best way to open a two way channel between client and server. In legacy browsers, SignalR will fall back on other protocols though.

There are two parts to setting up SignalR. I will discuss both in the following sections.

Server

The first step is to enable SignalR on the server by bringing in the required .Net middleware. I have included the relevant pieces from Startup.cs below:

using System; using System.Collections.Generic; using System.IO; using Friends.Hubs; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; namespace Friends { public class Startup { public void ConfigureServices (IServiceCollection services) { services.AddSignalR (); } public void Configure (IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting (); app.UseEndpoints (endpoints => { endpoints.MapHub<GreetingHub> ("/greetingHub"); }); } } }

Aside from just including the SignalR library I am also mapping up a hub endpoint. Hubs are key to SignalR since they define the two way communication between client and server. Hubs expose server endpoints that can be called by the client, but also initiate server pushes. We will see an example of this in the following Hub code:

using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; namespace Friends.Hubs { public class GreetingHub : Hub { public async Task SendMessage (string user) { await Clients.All.SendAsync ("ReceiveGreeting", $"Good Morning {user}"); } } }

In my hub I have defined a method called SendMessage. Think of this as the public server side api. Internally my hub method calls Clients.All.SendAsync with the argument “ReceiveGreeting”. This is an example of a server side push that will end up calling a client side method called ReceiveGreeting.

Client

In this particular example my client is an Angular component, but you can use any Javascript framework you like. Just add the npm package @microsoft/signalr to bring in the SignalR dependencies.

I have included my Angular component below:

import { Component } from '@angular/core'; import * as signalR from '@microsoft/signalr'; @Component({ templateUrl: 'greeting.component.html', }) export class GreetingComponent { greeting: string; async ngOnInit() { let connection = new signalR.HubConnectionBuilder() .withUrl("/greetingHub") .build(); connection.on("ReceiveGreeting", data => { this.greeting = data; }); await connection.start() connection.invoke("SendMessage", "Joe"); } }

The first step is to establish a connection to the hub by calling the hub endpoint we wired up on the server. Next we invoke the SendMessage hub method that we discussed in the previous section. Notice how I am also defining an event to capture any push notification of type ReceiveGreeting from the server. Basically this code snippet will make a call to the server side hub and receive an asynchronous server push in return.

Demo

Since my code uses two different types of technologies, Angular and .Net, I have decided to go with a language agnostic build system called Bazel for my demo. The main benefit of this is that I can build Angular Typescript and C# code in the same build step.

You can download my sample code if you are interested in trying it out yourself.