Using SignalR Triggers

Discover how to use SignalR bindings in Azure Functions.

Azure SignalR Service allows us to establish persistent two-way communication between the client and the server over the network. When the client connects to the server, the connection remains active until the client disconnects. While the connection is active, messages can travel either way at any time. The client can send messages to the server, but the server can likewise send a message to the client when some event occurs. This functionality makes SignalR Service especially useful for building fully interactive web-based applications.

A function can act as a client for a SignalR Service instance. It has various types of bindings, which we will cover in this lesson. We will do so with the following interactive playground:

using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace AzureFunctionApp
{
    public static class Functions
    {
        [FunctionName("Negotiate")]
        public static SignalRConnectionInfo Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
            [SignalRConnectionInfo(HubName = "ExampleHub")] SignalRConnectionInfo connectionInfo)
        {
            try
            {
                return connectionInfo;
            }
            catch
            {
                Console.WriteLine($"No SignalR connection is established");
            }

            return new SignalRConnectionInfo();
        }

        [FunctionName("ReceiveMessage")]
        public static async Task ReceiveMessage(
            [SignalRTrigger("ExampleHub", "messages", "SendMessage", 
            parameterNames: new string[] { "message" })] InvocationContext invocationContext, string message, ILogger logger)
        {
            Console.WriteLine($"Receive {message} from {invocationContext.ConnectionId}.");
        }

        [FunctionName("ReceiveMessageWithParams")]
        public static async Task ReceiveMessageWithParams(
            [SignalRTrigger("ExampleHub", "messages", "SendMessageWithParams")] InvocationContext invocationContext, 
            [SignalRParameter] string message, ILogger logger)
        {
            logger.LogInformation($"Receive {message} from {invocationContext.ConnectionId}.");
        }

        [FunctionName("SendMessage")]
        public static async Task SendMessage(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] object message,
            [SignalR(HubName = "ExampleHub")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            try
            {
                await signalRMessages.AddAsync(
                    new SignalRMessage
                    {
                        Target = "BroadcastMessage",
                        Arguments = new[] { message }
                    });
            }
            catch
            {
                Console.WriteLine($"No SignalR connection is established");
            }
        }
    }
}
Function app with SignalR Service bindings

Note: As the SignalR Service bindings require a real instance of a SignalR Service running in Azure, which cannot be emulated, some of the functionality in the above setup will not work.

Adding the necessary dependencies

Before we can ...