This is the twelfth of a new series of posts on ASP .NET Core. In this post, we’ll learn about the use of SignalR to build real-time functionality in your ASP NET Core web apps. SignalR can also be used to add real-time functionality to desktop applications, mobile apps and Azure Functions.

In this Article:

What is SignalR?

SignalR has been around for 5+ years now, allowing ASP .NET developers to easily include real-time features in their web applications. Fast forward to 2018, SignalR Core is now available with ASP .NET Core (as of 2.1) as a cross-platform solution to add real-time features to web apps and more!

In this article, we’ll go over SignalR concepts, using a new sample I developed to allow web users to vote in a real-time online poll. Before you begin, take a look at the sample code project on GitHub:

SignalR Core Samples on GitHub: https://github.com/shahedc/SignalRCoreSamples

I ran a couple of polls on Facebook and Twitter to see what the dev community wanted to see. On Twitter, the #1 choice was “Polling/Voting app” followed by “Planning Poker App” and “Real-time game”. On Facebook, the #1 choice was “Real-time game” followed by “Polling/voting app”. As a result, I’ve decide to complement this article with a polling sample app, and I plan to work on other ideas in 2019.

Twitter poll results: https://twitter.com/shahedC/status/1074862352787492864

More importantly, Brady Gaster suggested that the sample app should definitely be “Not. Chat.” 🙂

Not. Chat. — Brady Gaster (@bradygaster) December 18, 2018

In the sample project, take a look at the SignalRPoll project to see how the polling feature has been implemented. In order to create a project from scratch, you’ll be using both server-side and client-side dependencies.

If you need a starter tutorial, check out the official docs:

Get started with ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr

Dependencies

The Server-Side dependencies for SignalR Core are available via the Microsoft.AspNetCore.App package so this is a freebie when you create a new web app project. In your server-side code, you can use the following namespace:

using Microsoft.AspNetCore.SignalR;

This will give you access to SignalR classes such as Hub and Hub<T> for your SignalR hub to derive from. In the sample project, the PollHub class inherits from the Hub class. Hub<T> can be used for strongly-typed SignalR hubs.

The Client Side dependencies for SignalR Core have to be added manually. Simply right-click on your web app project and select Add | Client-Side Library. In the popup that appears, select a provider (such as “unpkg”) and enter a partial search term for Library, so that you can ideally pick the latest stable version.

Steps to add client library via LibMan (aka Library Manager):

Right-click project in Solution Explorer

Select Add | Client-Side Library

In the popup that appears, select/enter the following:

Provider : choose from cdnjs, filesystem, unpkg

: choose from cdnjs, filesystem, unpkg Library search term: @aspnet/signalr@1… pick latest stable if desired

search term: @aspnet/signalr@1… pick latest stable if desired Files: At a minimum, choose specific files signalr.js and/or its minified equivalent

Server-Side Hub

In the sample app, the PollHub class has a simple SendMessage() method with a few parameters. Derived from the sample Chat application, it starts with the user’s desired “user” value and a custom “message” that can be passed to the SignalR Hub. For the the Captain Marvel/America poll, the method also passes an Id and Value for the selected radio button.

public class PollHub : Hub { public async Task SendMessage(string user, string message, string myCaptainId, string myCaptainVal) { await Clients.All.SendAsync("ReceiveMessage", user, message, myCaptainId, myCaptainVal); } }

To ensure that the SendMessage method from the server has a trigger on the client-side, the client-side code must invoke the method via the SignalR connection created with HubConnectionBuilder() on the client side. Once called, the above code will send a call to ReceiveMessage on all the clients connected to the Hub.

Client-Side

On the client-side, the JavaScript file poll.js handles the call from the browser to the server, and receives a response back from the server as well. The following code snippets highlight some important areas:

var connection = new signalR.HubConnectionBuilder().withUrl("/pollHub").build(); ... connection.on("ReceiveMessage", function (user, message, myCaptainId, myCaptainVal) { ... document.getElementById(myCaptainId + 'Block').innerHTML += chartBlock; }); ... document.getElementById("sendButton").addEventListener("click", function (event) { ... connection.invoke("SendMessage", user, message, myCaptainId, myCaptainVal) ... });

The above snippets takes care of the following:

Creates a new connection objection using HubConnectionBuilder with a designated route Uses connection.on to ensure that calls to ReceiveMessage come back from the server Sets the innerHTML of a <span> block to simulate a growing bar chart built with small blocks Listens for a click event from the sendButton element on the browser When the sendButton is clicked, uses connection.invoke() to call SendMessage on the server

Configuration

The configuration for the SignalR application is set up in the Startup.cs methods ConfigureServices() and Configure(), as you may expect.

public void ConfigureServices(IServiceCollection services) { ... services.AddSignalR(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { ... app.UseSignalR(routes => { ... routes.MapHub<PollHub>("/pollHub"); }); ... }

The above code takes care of the following:

the ConfigureServices() method adds SignalR to the ASP.NET Core dependency injection system with a call to AddSignalR() the Configure() method adds SignalR to the middleware pipeline, while setting up the necessary route(s), using a call to UseSignalR().

At the time of this writing, I have more than one route set up for multiple hubs. For the polling app, we only need the call to MapHub<PollHub>() that sets up the route “/pollHub“. You may recall this route from the client-side JavaScript code where the initial connection is set up.

For streaming fragments of data over time, you should also take a look at Streaming in SignalR Core:

Use streaming in ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/signalr/streaming

Running the App

To run the app, simply run the SignalRPoll app Visual Studio or from the command line. Then, click the Poll item in the top menu to go to the Poll page. This page is a simple Razor page that contains all the HTML elements necessary to display the poll. It also includes <script> references to jQuery, SignalR and poll.js client-side references.

NOTE: Even though I am using jQuery for this sample, please note that jQuery is not required to use SignalR Core. On a related note, you can also configure Webpack and TypeScript for a TypeScript client if you want.

This GIF animation below illustrates the poll in action. To record this GIF of 1 browser window, I also launched additional browser windows (not shown) pointing to the same URL, so that I could vote several times.

In a real world scenario, there are various ways to prevent a user from voting multiple times. Some suggestions include:

Disable the voting button as soon as the user has submitted a vote.

Use a cookie to prevent the user from voting after reloading the page.

Use authentication to prevent a user from voting after clearing cookies or using a different browser.

For more information on authenticating and authorizing users, check out the official docs:

Authentication and authorization in ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz

Azure SignalR Service

Azure SignalR Service is a fully-managed service available in Microsoft’s cloud-hosted Azure services, that allows you to add real-time functionality and easily scale your apps as needed. Using Azure SignalR Service is as easy as 1-2-3:

Add a reference to the Azure SignalR Service SDK Configure a connection string Call services.AddSignalR().AddAzureSignalR() and app.UseAzureSignalR in Startup.cs

For more information on Azure SignalR Service, check out the official docs and tutorials:

What is Azure SignalR: https://docs.microsoft.com/en-us/azure/azure-signalr/signalr-overview

Packaging Changes in 3.0

You may have heard that ASP .NET Core 3.0 will come with some changes in the way packages are made available to developers. So how does this affect SignalR going forward? Things to note:

Microsoft “will stop producing many of the NuGet packages that we have been shipping since ASP.NET Core 1.0. The API those packages provide are still available to apps by using a <FrameworkReference> to Microsoft.AspNetCore.App. This includes commonly referenced API, such as Kestrel, Mvc, Razor, and others.”

“This will not apply to all binaries that are pulled in via Microsoft.AspNetCore.App in 2.x.”

“Notable exceptions include: The SignalR .NET client will continue to support .NET Standard and ship as NuGet package because it is intended for use on many .NET runtimes, like Xamarin and UWP.”

Source: https://github.com/aspnet/Announcements/issues/325

References:

Docs/Tutorials:

Intro to ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction

Get started with ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr

Create backend services for native mobile apps with ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/mobile/native-mobile-backend

Use ASP.NET Core SignalR with TypeScript and Webpack: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr-typescript-webpack

Official Code Samples:

Announcements:

Announcing ASP.NET SignalR 2.4.0 Preview 1: https://blogs.msdn.microsoft.com/webdev/2018/10/04/announcing-asp-net-signalr-2-4-0-preview-1/

ASP.NET SignalR 2.4.0: https://blogs.msdn.microsoft.com/webdev/2018/11/14/asp-net-signalr-2-4-0/

Announcing ASP.NET Core 2.2: https://blogs.msdn.microsoft.com/webdev/2018/12/04/asp-net-core-2-2-available-today/

The future of ASP.NET SignalR: https://blogs.msdn.microsoft.com/webdev/2018/09/17/the-future-of-asp-net-signalr/

Ignite 2018 Sessions on SignalR:

Build real-time web communication apps with ASP.NET Core SignalR: https://myignite.techcommunity.microsoft.com/sessions/65893?source=sessions

Develop real-time features with Azure SignalR Service: https://myignite.techcommunity.microsoft.com/sessions/66604?source=sessions

Build real-time serverless apps with Azure Functions and SignalR Service: https://myignite.techcommunity.microsoft.com/sessions/66631?source=sessions

Blog posts on SignalR:

Useful ASP.NET Core 2.2 Features: https://www.hanselman.com/blog/UsefulASPNETCore22Features.aspx

Differences between SignalR and ASP.NET Core SignalR: https://docs.microsoft.com/en-us/aspnet/core/signalr/version-differences?view=aspnetcore-2.2

Real Time Communication for Mobile with SignalR (Core): https://montemagno.com/real-time-communication-for-mobile-with-signalr/

Azure Functions Bindings with SignalR:

Azure Functions SignalR Service bindings: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-signalr-service

Broadcast Real-time Updates from Cosmos DB with SignalR Service and Azure Functions: https://medium.com/microsoftazure/broadcast-real-time-updates-from-cosmos-db-with-signalr-service-and-azure-functions-349abe76dc5e

Add real-time web functionality to Angular application using ASP.NET Core SignalR, Azure SignalR service and Azure SignalR Service bindings for Azure Functions 2.0: https://blogs.msdn.microsoft.com/atverma/2018/11/02/add-real-time-web-functionality-to-angular-application-using-asp-net-core-signalr-azure-signalr-service-and-azure-signalr-service-bindings-for-azure-functions-2-0/

Additional Resources: