Getting Started with Serverless SignalR and Azure Functions

John Kilmister, · 6 min read
This page was published 3 years ago. While the content may still be relevant there is a high chance things may have changed and the content may no longer be accurate.

SignalR provides the ability to push or broadcast information from a back-end server at any time to any front end web application that has subscribed. This allows for real-time updates of data on web sites, multiplayer games, polls, interactive chat bots and various other uses.

Initially tied to ASP.net and jQuery, SignalR has been around for a long time however much has changed in recent years. Now the technology can be used serverless with a whole range of front end frameworks and a range of back ends languages including Javascript, python, java and C#.

Other features also include two way communication, broadcasting notifications to groups and client auto reconnection.

How does it work

SignalR achieves bi-directional communication using a range of client and server technologies. In HTML5 it uses web sockets however where this is not possible it will communicate using long polling.

All communication is done through the SignalR hub. Previously this would have been as part of an ASP.net application or more recently on an ASP.net core application. Now we are able to create a SignalR hub inside Azure as a stand-alone resource meaning it can be used with a serverless application and integrated into Azure functions.

A Sample Application

There are many types of applications you can create using SignalR. To show how SignalR works however I have chosen the simplest possible application with one-way communication from server to all subscribed clients.

In this application when a file is dropped into azure blob storage this will trigger an Azure function. The function will broadcast through the serverless SignalR Hub to any subscribed clients that a new file is now available.

The sample code is using Azure functions in JavaScript and a simple ReactJS front end however the concepts are the same with other languages.

Creating the Hub

Login to the Azure portal and select SignalR to create a new resource.

Screenshot of Azure update website

There are a number of fields to complete:

Pricing tier

The pricing tier option can be set to either standard or free. Free has a few limits such as limiting concurrent connected users to 20, however is great to get started. Full pricing can be found on the pricing guide.

Units

SignalR units refer to what is in affect a node or sub instance. To improve performance on a standard plan you can have only 1,000 concurrent connections per unit. It is intended that you use multiple units to overcome this limit. A more detailed description on units can be found here on Stack Overflow.

Service mode

For working with Azure functions this must be set to Serverless

Under keys you will find the connection string you will need later. Nothing else needs to be configured in the portal.

Negotiate Function

When the website begins a SignalR connection it will need to locate a HTTP triggered function named negotiate.

This is very simple and contains a single line. For this demo we will use Javascript however the code for other languages can be found in the official documentation

module.exports = async function (context, req, connectionInfo) {
    context.res.body = connectionInfo;
};

Now you have a function you will need to configure the bindings to include SignalR as below. The AzureSignalRConnectionString can be set in your function app settings using the value from the portal.

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "signalRConnectionInfo",
      "name": "connectionInfo",
      "hubName": "serverless",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "in"
    }
  ]
}

Blob Triggered Function

For this sample application we use a blob trigger and broadcast to all subscribers when a new file is added.

module.exports = async function (context, myBlob) {

    context.bindings.signalRMessages = [{
        "target": "newFile",
        "arguments": [ context.bindingData.blobTrigger, context.bindingData.uri ]
    }];
   
    context.done();
};

In the code the target refers to the method name in the web application and arguments is an array of the method parameters that are passed in to it.

To complete this function we need to set the function bindings to include SignalR, the Blob trigger and set the connection string in the function settings.

{
  "bindings": [
    {
      "name": "myBlob",
      "type": "blobTrigger",
      "direction": "in",
      "path": "media",
      "connection": "StorageConnectionString"
    },
    {
      "type": "signalR",
      "name": "signalRMessages",
      "hubName": "serverless",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "out"
    }
  ]
}

Client Web Application

The client web application code is all in a single file and can be viewed on GitHub along with the rest of the code. For this section I have selected only the SignalR section of the code to talk over.

You will need to run npm install @microsoft/signalr. Be aware there are other SignalR npm packages for integrations with asp.net and other implementations.

import React from 'react';
import * as signalR from '@microsoft/signalr'

We will set an array of files in the react state so we can update it when a new file notification arrives. When the page has loaded (componentDidMount in react), we connect to SignalR and setup the call backs.

For the rest of the file including the render methods see Git Hub.

  componentDidMount()
  {

    //The apiBaseUrl should be base url of your functions and 
    //it is possible to run this from local host.
    const apiBaseUrl = "http://localhost:7071/api";

    var connection = new signalR.HubConnectionBuilder()
    .withUrl(apiBaseUrl)
    .build();
 
    //This method is called to create the connection
    //to SignalR so the client can receive messages
    connection.start().then(function () {
      console.log("connected");
    }).catch(function (err) {
        return console.error(err.toString());
    });

   //Connection.on is the callback that will be triggered 
   //when a message is sent via SignalR.
    connection.on("newfile", (name,uri) => {   
      let { files } = this.state;
      files.push({name:name, uri: uri });
      this.setState({ files: files });
    });
  }

Once the application is running, both the functions and the UI, adding a new file to blob storage will then display in the web browser without the user having to refresh.

Azure Web PubSub

Azure Web PubSub is a newer Azure offering that is currently still in preview. Azure Web PubSub can achieve the same result however works at a lower level. This means you miss out on some of the features of SignalR such as auto re-connection and communication full backs. I plan to write a full post on this later with a similar sample application.

Summary

SignalR has come a long way and can now be used with a whole range of languages making it very versatile and simpler to consume.

In this post we looked at Azure SignalR and it’s possible uses. We created a simple application that allows clients to subscribe to the SignalR hub and be notified whenever a new file was added to the blob storage. If you wish to see the full sample the code can be found on GitHub.

Title Photo by Markus Winkler on Unsplash.

Recent and Related Articles