Quickstart: Create a chat room by using SignalR Service

Azure SignalR Service is an Azure service that helps developers easily build web applications with real-time features. This service was originally based on SignalR for ASP.NET Core 2.1, but now supports later versions.

This article shows you how to get started with the Azure SignalR Service. In this quickstart, you'll create a chat application by using an ASP.NET Core MVC web app. This app will make a connection with your Azure SignalR Service resource to enable real-time content updates. You'll host the web application locally and connect with multiple browser clients. Each client will be able to push content updates to all other clients.

You can use any code editor to complete the steps in this quickstart. One option is Visual Studio Code, which is available on the Windows, macOS, and Linux platforms.

The code for this tutorial is available for download in the AzureSignalR-samples GitHub repository. Also, you can create the Azure resources used in this quickstart by following Create a SignalR Service script.

If you don't have an Azure subscription, create a free account before you begin.


Having issues? Try the troubleshooting guide or let us know.

Create an Azure SignalR resource

  1. To create an Azure SignalR Service resource, first sign in to the Azure portal. In the upper-left side of the page, select + Create a resource. In the Search the Marketplace text box, enter SignalR Service.

  2. Select SignalR Service in the results, and select Create.

  3. On the new SignalR settings page, add the following settings for your new SignalR resource:

    Name Recommended value Description
    Resource name testsignalr Enter a unique resource name to use for the SignalR resource. The name must be a string of 1 to 63 characters and contain only numbers, letters, and the hyphen (-) character. The name cannot start or end with the hyphen character, and consecutive hyphen characters are not valid.
    Subscription Choose your subscription Select the Azure subscription that you want to use to test SignalR. If your account has only one subscription, it's automatically selected and the Subscription drop-down isn't displayed.
    Resource group Create a resource group named SignalRTestResources Select or create a resource group for your SignalR resource. This group is useful for organizing multiple resources that you might want to delete at the same time by deleting the resource group. For more information, see Using resource groups to manage your Azure resources.
    Location East US Use Location to specify the geographic location in which your SignalR resource is hosted. For the best performance, we recommend that you create the resource in the same region as other components of your application.
    Pricing tier Free Currently, Free and Standard options are available.
    Pin to dashboard Select this box to have the resource pinned to your dashboard so it's easier to find.
  4. Select Review + create. Wait for the validation to complete.

  5. Select Create. The deployment might take a few minutes to complete.

  6. After the deployment is complete, select Keys under SETTINGS. Copy your connection string for the primary key. You'll use this string later to configure your app to use the Azure SignalR Service resource.

    The connection string will have the following form:


Having issues? Try the troubleshooting guide or let us know.

Create an ASP.NET Core web app

In this section, you use the .NET Core command-line interface (CLI) to create an ASP.NET Core MVC web app project. The advantage of using the .NET Core CLI over Visual Studio is that it's available across the Windows, macOS, and Linux platforms.

  1. Create a folder for your project. This quickstart uses the E:\Testing\chattest folder.

  2. In the new folder, run the following command to create the project:

    dotnet new mvc

Having issues? Try the troubleshooting guide or let us know.

Add Secret Manager to the project

In this section, you'll add the Secret Manager tool to your project. The Secret Manager tool stores sensitive data for development work outside your project tree. This approach helps prevent the accidental sharing of app secrets in source code.

  1. Open your .csproj file. Add a DotNetCliToolReference element to include Microsoft.Extensions.SecretManager.Tools. Also add a UserSecretsId element as shown in the following code for chattest.csproj, and save the file.

    <Project Sdk="Microsoft.NET.Sdk.Web">
        <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
        <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.2" />

Having issues? Try the troubleshooting guide or let us know.

Add Azure SignalR to the web app

  1. Add a reference to the Microsoft.Azure.SignalR NuGet package by running the following command:

    dotnet add package Microsoft.Azure.SignalR
  2. Run the following command to restore packages for your project:

    dotnet restore
  3. Add a secret named Azure:SignalR:ConnectionString to Secret Manager.

    This secret will contain the connection string to access your SignalR Service resource. Azure:SignalR:ConnectionString is the default configuration key that SignalR looks for to establish a connection. Replace the value in the following command with the connection string for your SignalR Service resource.

    You must run this command in the same directory as the .csproj file.

    dotnet user-secrets set Azure:SignalR:ConnectionString "<Your connection string>"

    Secret Manager will be used only for testing the web app while it's hosted locally. In a later tutorial, you'll deploy the chat web app to Azure. After the web app is deployed to Azure, you'll use an application setting instead of storing the connection string with Secret Manager.

    This secret is accessed with the Configuration API. A colon (:) works in the configuration name with the Configuration API on all supported platforms. See Configuration by environment.

  4. Open Startup.cs and update the ConfigureServices method to use Azure SignalR Service by calling the AddSignalR() and AddAzureSignalR() methods:

    public void ConfigureServices(IServiceCollection services)

    By not passing a parameter to AddAzureSignalR(), this code uses the default configuration key for the SignalR Service resource connection string. The default configuration key is Azure:SignalR:ConnectionString.

  5. In Startup.cs, update the Configure method by replacing it with the following code.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        app.UseEndpoints(endpoints =>

Add a hub class

In SignalR, a hub is a core component that exposes a set of methods that can be called from the client. In this section, you define a hub class with two methods:

  • Broadcast: This method broadcasts a message to all clients.
  • Echo: This method sends a message back to the caller.

Both methods use the Clients interface that the ASP.NET Core SignalR SDK provides. This interface gives you access to all connected clients, so you can push content to your clients.

  1. In your project directory, add a new folder named Hub. Add a new hub code file named ChatHub.cs to the new folder.

  2. Add the following code to ChatHub.cs to define your hub class and save the file.

    Update the namespace for this class if you used a project name that differs from SignalR.Mvc.

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    namespace SignalR.Mvc
        public class ChatHub : Hub
            public Task BroadcastMessage(string name, string message) =>
                Clients.All.SendAsync("broadcastMessage", name, message);
            public Task Echo(string name, string message) =>
                       .SendAsync("echo", name, $"{message} (echo from server)");

Add the client interface for the web app

The client user interface for this chat room app will consist of HTML and JavaScript in a file named index.html in the wwwroot directory.

Copy the css/site.css file from the wwwroot folder of the samples repository. Replace your project's css/site.css with the one you copied.

Here's the main code of index.html:

Create a new file in the wwwroot directory named index.html, copy, and paste the following HTML into the newly created file:

<!DOCTYPE html>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <title>Azure SignalR Group Chat</title>
    <h2 class="text-center" style="margin-top: 0; padding-top: 30px; padding-bottom: 30px;">Azure SignalR Group Chat</h2>
    <div class="container" style="height: calc(100% - 110px);">
        <div id="messages" style="background-color: whitesmoke; "></div>
        <div style="width: 100%; border-left-style: ridge; border-right-style: ridge;">
            <textarea id="message"
                      style="width: 100%; padding: 5px 10px; border-style: hidden;"
                      placeholder="Type message and press Enter to send..."></textarea>
        <div style="overflow: auto; border-style: ridge; border-top-style: hidden;">
            <button class="btn-warning pull-right" id="echo">Echo</button>
            <button class="btn-success pull-right" id="sendmessage">Send</button>
    <div class="modal alert alert-danger fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <div>Connection Error...</div>
                    <div><strong style="font-size: 1.5em;">Hit Refresh/F5</strong> to rejoin. ;)</div>

    <!--Reference the SignalR library. -->
    <script src="https://cdn.jsdelivr.net/npm/@microsoft/signalr@3.1.8/dist/browser/signalr.min.js"></script>

    <!--Add script to update the page and send messages.-->
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function () {

            const generateRandomName = () =>
                Math.random().toString(36).substring(2, 10);

            let username = generateRandomName();
            const promptMessage = 'Enter your name:';
            do {
                username = prompt(promptMessage, username);
                if (!username || username.startsWith('_') || username.indexOf('<') > -1 || username.indexOf('>') > -1) {
                    username = '';
                    promptMessage = 'Invalid input. Enter your name:';
            } while (!username)

            const messageInput = document.getElementById('message');

            function createMessageEntry(encodedName, encodedMsg) {
                var entry = document.createElement('div');
                if (encodedName === "_SYSTEM_") {
                    entry.innerHTML = encodedMsg;
                } else if (encodedName === "_BROADCAST_") {
                    entry.innerHTML = `<div class="text-center broadcast-message">${encodedMsg}</div>`;
                } else if (encodedName === username) {
                    entry.innerHTML = `<div class="message-avatar pull-right">${encodedName}</div>` +
                        `<div class="message-content pull-right">${encodedMsg}<div>`;
                } else {
                    entry.innerHTML = `<div class="message-avatar pull-left">${encodedName}</div>` +
                        `<div class="message-content pull-left">${encodedMsg}<div>`;
                return entry;

            function bindConnectionMessage(connection) {
                var messageCallback = function (name, message) {
                    if (!message) return;
                    var encodedName = name;
                    var encodedMsg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
                    var messageEntry = createMessageEntry(encodedName, encodedMsg);

                    var messageBox = document.getElementById('messages');
                    messageBox.scrollTop = messageBox.scrollHeight;
                connection.on('broadcastMessage', messageCallback);
                connection.on('echo', messageCallback);

            function onConnected(connection) {
                console.log('connection started');
                connection.send('broadcastMessage', '_SYSTEM_', username + ' JOINED');
                document.getElementById('sendmessage').addEventListener('click', function (event) {
                    if (messageInput.value) {
                        connection.send('broadcastMessage', username, messageInput.value);

                    messageInput.value = '';
                document.getElementById('message').addEventListener('keypress', function (event) {
                    if (event.keyCode === 13) {
                        return false;
                document.getElementById('echo').addEventListener('click', function (event) {
                    connection.send('echo', username, messageInput.value);

                    messageInput.value = '';

            function onConnectionError(error) {
                if (error && error.message) {
                var modal = document.getElementById('myModal');
                modal.style = 'display: block;';

            const connection = new signalR.HubConnectionBuilder()
                .then(() => onConnected(connection))
                .catch(error => console.error(error.message));

The code in index.html calls HubConnectionBuilder.build() to make an HTTP connection to the Azure SignalR resource.

If the connection is successful, that connection is passed to bindConnectionMessage, which adds event handlers for incoming content pushes to the client.

HubConnection.start() starts communication with the hub. Then, onConnected() adds the button event handlers. These handlers use the connection to allow this client to push content updates to all connected clients.

Add a development runtime profile

In this section, you'll add a development runtime environment for ASP.NET Core. For more information, see Work with multiple environments in ASP.NET Core.

  1. Create a folder named Properties in your project.

  2. Add a new file named launchSettings.json to the folder, with the following content, and save the file.

        "profiles" : {
            "ChatRoom": {
                "commandName": "Project",
                "launchBrowser": true,
                "environmentVariables": {
                    "ASPNETCORE_ENVIRONMENT": "Development"
                "applicationUrl": "http://localhost:5000/"

Having issues? Try the troubleshooting guide or let us know.

Build and run the app locally

  1. To build the app by using the .NET Core CLI, run the following command in the command shell:

    dotnet build
  2. After the build successfully finishes, run the following command to run the web app locally:

    dotnet run

    The app will be hosted locally on port 5000, as configured in our development runtime profile:

    info: Microsoft.Hosting.Lifetime[0]
          Now listening on: https://localhost:5001
    info: Microsoft.Hosting.Lifetime[0]
          Now listening on: http://localhost:5000
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Development
    info: Microsoft.Hosting.Lifetime[0]
          Content root path: E:\Testing\chattest
  3. Open two browser windows. In each browser, go to http://localhost:5000. You're prompted to enter your name. Enter a client name for both clients and test pushing message content between both clients by using the Send button.

    Example of an Azure SignalR group chat

Having issues? Try the troubleshooting guide or let us know.

Clean up resources

If you'll continue to the next tutorial, you can keep the resources created in this quickstart and reuse them.

If you're finished with the quickstart sample application, you can delete the Azure resources created in this quickstart to avoid charges.


Deleting a resource group is irreversible and includes all the resources in that group. Make sure that you don't accidentally delete the wrong resource group or resources. If you created the resources for hosting this sample in an existing resource group that contains resources you want to keep, you can delete each resource individually from its blade instead of deleting the resource group.

Sign in to the Azure portal and select Resource groups.

In the Filter by name text box, type the name of your resource group. The instructions for this quickstart used a resource group named SignalRTestResources. On your resource group in the result list, select the ellipsis (...) > Delete resource group.

Selections for deleting a resource group

You're asked to confirm the deletion of the resource group. Enter the name of your resource group to confirm, and select Delete.

After a few moments, the resource group and all of its resources are deleted.

Having issues? Try the troubleshooting guide or let us know.

Next steps

In this quickstart, you created a new Azure SignalR Service resource. You then used it with an ASP.NET Core web app to push content updates in real time to multiple connected clients. To learn more about using Azure SignalR Service, continue to the tutorial that demonstrates authentication.