Use ASP.NET Core SignalR with Blazor

This tutorial teaches the basics of building a real-time app using SignalR with Blazor.

Learn how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

At the end of this tutorial, you'll have a working chat app.

Prerequisites

Sample app

Downloading the tutorial's sample chat app isn't required for this tutorial. The sample app is the final, working app produced by following the steps of this tutorial.

View or download sample code

Create a hosted Blazor WebAssembly app

Follow the guidance for your choice of tooling:

Note

Visual Studio 2022 or later and .NET Core SDK 6.0.0 or later are required.

  1. Create a new project.

  2. Choose the Blazor WebAssembly App template. Select Next.

  3. Type BlazorWebAssemblySignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. In the Additional information dialog, select the ASP.NET Core Hosted checkbox.

  5. Select Create.

  6. Confirm that a hosted Blazor WebAssembly app was created: In Solution Explorer, confirm the presence of a Client project and a Server project. If the two projects aren't present, start over and confirm selection of the ASP.NET Core Hosted checkbox before selecting Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorWebAssemblySignalRApp.Client project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

In the BlazorWebAssemblySignalRApp.Server project, create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs;

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

Add services and an endpoint for the SignalR hub

  1. In the BlazorWebAssemblySignalRApp.Server project, open the Program.cs file.

  2. Add the namespace for the ChatHub class to the top of the file:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. Add SignalR and Response Compression Middleware services to Program.cs:

    builder.Services.AddSignalR();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Program.cs:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for controllers and the client-side fallback, add an endpoint for the hub.
    app.UseResponseCompression();
    
    if (app.Environment.IsDevelopment())
    {
        app.UseWebAssemblyDebugging();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    
    app.UseBlazorFrameworkFiles();
    app.UseStaticFiles();
    app.UseRouting();
    
    app.MapRazorPages();
    app.MapControllers();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToFile("index.html");
    
    app.Run();
    

Add Razor component code for chat

  1. In the BlazorWebAssemblySignalRApp.Client project, open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager Navigation
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Note

Disable Response Compression Middleware in the Development environment when using Hot Reload. For more information, see ASP.NET Core Blazor SignalR guidance.

Run the app

Follow the guidance for your tooling:

  1. In Solution Explorer, select the BlazorWebAssemblySignalRApp.Server project. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

    Important

    When executing a hosted Blazor WebAssembly app, run the app from the solution's Server project.

    Google Chrome or Microsoft Edge must be the selected browser for a debugging session.

    If the app fails to start in the browser:

    • In the .NET console, confirm that the solution is running from the "Server" project.
    • Refresh the browser using the browser's reload button.
  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Create a Blazor Server app

Follow the guidance for your choice of tooling:

Note

Visual Studio 2022 or later and .NET Core SDK 6.0.0 or later are required.

  1. Create a new project.

  2. Select the Blazor Server App template. Select Next.

  3. Type BlazorServerSignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorServerSignalRApp project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

Create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs;

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

Add services and an endpoint for the SignalR hub

  1. Open the Program.cs file.

  2. Add the namespaces for Microsoft.AspNetCore.ResponseCompression and the ChatHub class to the top of the file:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. Add Response Compression Middleware services to Program.cs:

    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
    builder.Services.AddSingleton<WeatherForecastService>();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Program.cs:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for mapping the Blazor hub and the client-side fallback, add an endpoint for the hub.
    app.UseResponseCompression();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.MapBlazorHub();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToPage("/_Host");
    
    app.Run();
    

Add Razor component code for chat

  1. Open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager Navigation
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Note

Disable Response Compression Middleware in the Development environment when using Hot Reload. For more information, see ASP.NET Core Blazor SignalR guidance.

Run the app

Follow the guidance for your tooling:

  1. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Next steps

In this tutorial, you learned how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

To learn more about building Blazor apps, see the Blazor documentation:

Additional resources

Learn how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

At the end of this tutorial, you'll have a working chat app.

Prerequisites

Sample app

Downloading the tutorial's sample chat app isn't required for this tutorial. The sample app is the final, working app produced by following the steps of this tutorial.

View or download sample code

Create a hosted Blazor WebAssembly app

Follow the guidance for your choice of tooling:

Note

Visual Studio 2022 or later and .NET Core SDK 6.0.0 or later are required.

  1. Create a new project.

  2. Choose the Blazor WebAssembly App template. Select Next.

  3. Type BlazorWebAssemblySignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. In the Additional information dialog, select the ASP.NET Core Hosted checkbox.

  5. Select Create.

  6. Confirm that a hosted Blazor WebAssembly app was created: In Solution Explorer, confirm the presence of a Client project and a Server project. If the two projects aren't present, start over and confirm selection of the ASP.NET Core Hosted checkbox before selecting Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorWebAssemblySignalRApp.Client project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

In the BlazorWebAssemblySignalRApp.Server project, create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs;

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

Add services and an endpoint for the SignalR hub

  1. In the BlazorWebAssemblySignalRApp.Server project, open the Program.cs file.

  2. Add the namespace for the ChatHub class to the top of the file:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. Add SignalR and Response Compression Middleware services to Program.cs:

    builder.Services.AddSignalR();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Program.cs:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for controllers and the client-side fallback, add an endpoint for the hub.
    app.UseResponseCompression();
    
    if (app.Environment.IsDevelopment())
    {
        app.UseWebAssemblyDebugging();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseBlazorFrameworkFiles();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.MapRazorPages();
    app.MapControllers();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToFile("index.html");
    
    app.Run();
    

Add Razor component code for chat

  1. In the BlazorWebAssemblySignalRApp.Client project, open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager Navigation
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Note

Disable Response Compression Middleware in the Development environment when using Hot Reload. For more information, see ASP.NET Core Blazor SignalR guidance.

Run the app

Follow the guidance for your tooling:

  1. In Solution Explorer, select the BlazorWebAssemblySignalRApp.Server project. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

    Important

    When executing a hosted Blazor WebAssembly app, run the app from the solution's Server project.

    Google Chrome or Microsoft Edge must be the selected browser for a debugging session.

    If the app fails to start in the browser:

    • In the .NET console, confirm that the solution is running from the "Server" project.
    • Refresh the browser using the browser's reload button.
  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Create a Blazor Server app

Follow the guidance for your choice of tooling:

Note

Visual Studio 2022 or later and .NET Core SDK 6.0.0 or later are required.

  1. Create a new project.

  2. Select the Blazor Server App template. Select Next.

  3. Type BlazorServerSignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorServerSignalRApp project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

Create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs;

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

Add services and an endpoint for the SignalR hub

  1. Open the Program.cs file.

  2. Add the namespaces for Microsoft.AspNetCore.ResponseCompression and the ChatHub class to the top of the file:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. Add Response Compression Middleware services to Program.cs:

    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
    builder.Services.AddSingleton<WeatherForecastService>();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Program.cs:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for mapping the Blazor hub and the client-side fallback, add an endpoint for the hub.
    app.UseResponseCompression();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.MapBlazorHub();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToPage("/_Host");
    
    app.Run();
    

Add Razor component code for chat

  1. Open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager Navigation
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Note

Disable Response Compression Middleware in the Development environment when using Hot Reload. For more information, see ASP.NET Core Blazor SignalR guidance.

Run the app

Follow the guidance for your tooling:

  1. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Next steps

In this tutorial, you learned how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

To learn more about building Blazor apps, see the Blazor documentation:

Additional resources

Learn how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

At the end of this tutorial, you'll have a working chat app.

Prerequisites

Sample app

Downloading the tutorial's sample chat app isn't required for this tutorial. The sample app is the final, working app produced by following the steps of this tutorial.

View or download sample code

Create a hosted Blazor WebAssembly app

Follow the guidance for your choice of tooling:

Note

Visual Studio 16.10 or later and .NET Core SDK 5.0.0 or later are required.

  1. Create a new project.

  2. Choose the Blazor WebAssembly App template. Select Next.

  3. Type BlazorWebAssemblySignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. In the Additional information dialog, select the ASP.NET Core Hosted checkbox.

  5. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorWebAssemblySignalRApp.Client project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

In the BlazorWebAssemblySignalRApp.Server project, create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Add services and an endpoint for the SignalR hub

  1. In the BlazorWebAssemblySignalRApp.Server project, open the Startup.cs file.

  2. Add the namespace for the ChatHub class to the top of the file:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. Add SignalR and Response Compression Middleware services to Startup.ConfigureServices:

    services.AddSignalR();
    services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Startup.Configure:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for controllers and the client-side fallback, add an endpoint for the hub.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebAssemblyDebugging();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseBlazorFrameworkFiles();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllers();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToFile("index.html");
        });
    }
    

Add Razor component code for chat

  1. In the BlazorWebAssemblySignalRApp.Client project, open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Run the app

Follow the guidance for your tooling:

  1. In Solution Explorer, select the BlazorWebAssemblySignalRApp.Server project. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

    Important

    When executing a hosted Blazor WebAssembly app, run the app from the solution's Server project.

    Google Chrome or Microsoft Edge must be the selected browser for a debugging session.

    If the app fails to start in the browser:

    • In the .NET console, confirm that the solution is running from the "Server" project.
    • Refresh the browser using the browser's reload button.
  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Create a Blazor Server app

Follow the guidance for your choice of tooling:

Note

Visual Studio 16.10 or later and .NET Core SDK 5.0.0 or later are required.

  1. Create a new project.

  2. Select the Blazor Server App template. Select Next.

  3. Type BlazorServerSignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorServerSignalRApp project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

Create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Add services and an endpoint for the SignalR hub

  1. Open the Startup.cs file.

  2. Add the namespaces for Microsoft.AspNetCore.ResponseCompression and the ChatHub class to the top of the file:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. Add Response Compression Middleware services to Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });
    }
    
  4. In Startup.Configure:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for mapping the Blazor hub and the client-side fallback, add an endpoint for the hub.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToPage("/_Host");
        });
    }
    

Add Razor component code for chat

  1. Open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

Run the app

Follow the guidance for your tooling:

  1. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Next steps

In this tutorial, you learned how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

To learn more about building Blazor apps, see the Blazor documentation:

Additional resources

Learn how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

At the end of this tutorial, you'll have a working chat app.

Prerequisites

Sample app

Downloading the tutorial's sample chat app isn't required for this tutorial. The sample app is the final, working app produced by following the steps of this tutorial.

View or download sample code

Create a hosted Blazor WebAssembly app

Follow the guidance for your choice of tooling:

Note

Visual Studio 16.6 or later and .NET Core SDK 3.1.300 or later are required.

  1. Create a new project.

  2. Choose the Blazor WebAssembly App template. Select Next.

  3. Type BlazorWebAssemblySignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. In the Additional information dialog, select the ASP.NET Core Hosted checkbox.

  5. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorWebAssemblySignalRApp.Client project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

In the BlazorWebAssemblySignalRApp.Server project, create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Add services and an endpoint for the SignalR hub

  1. In the BlazorWebAssemblySignalRApp.Server project, open the Startup.cs file.

  2. Add the namespace for the ChatHub class to the top of the file:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. Add SignalR and Response Compression Middleware services to Startup.ConfigureServices:

    services.AddSignalR();
    services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. In Startup.Configure:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for controllers and the client-side fallback, add an endpoint for the hub.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebAssemblyDebugging();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseBlazorFrameworkFiles();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToFile("index.html");
        });
    }
    

Add Razor component code for chat

  1. In the BlazorWebAssemblySignalRApp.Client project, open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public void Dispose()
        {
            _ = hubConnection?.DisposeAsync();
        }
    }
    

Run the app

Follow the guidance for your tooling:

  1. In Solution Explorer, select the BlazorWebAssemblySignalRApp.Server project. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

    Important

    When executing a hosted Blazor WebAssembly app, run the app from the solution's Server project.

    Google Chrome or Microsoft Edge must be the selected browser for a debugging session.

    If the app fails to start in the browser:

    • In the .NET console, confirm that the solution is running from the "Server" project.
    • Refresh the browser using the browser's reload button.
  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Create a Blazor Server app

Follow the guidance for your choice of tooling:

Note

Visual Studio 16.6 or later and .NET Core SDK 3.1.300 or later are required.

  1. Create a new project.

  2. Select the Blazor Server App template. Select Next.

  3. Type BlazorServerSignalRApp in the Project name field. Confirm the Location entry is correct or provide a location for the project. Select Next.

  4. Select Create.

Add the SignalR client library

  1. In Solution Explorer, right-click the BlazorServerSignalRApp project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type Microsoft.AspNetCore.SignalR.Client in the search box.

  4. In the search results, select the Microsoft.AspNetCore.SignalR.Client package. Set the version to match the shared framework of the app. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add the System.Text.Encodings.Web package

This section only applies to apps for ASP.NET Core version 3.x.

Due to a package resolution issue when using System.Text.Json 5.x in an ASP.NET Core 3.x app, the project requires a package reference for System.Text.Encodings.Web. The underlying issue was resolved in a patch release and backported to ASP.NET Core 5.0. For more information, see System.Text.Json defines netcoreapp3.0 with no dependencies (dotnet/runtime #45560).

To add System.Text.Encodings.Web to the project, follow the guidance for your choice of tooling:

  1. In Solution Explorer, right-click the BlazorServerSignalRApp project and select Manage NuGet Packages.

  2. In the Manage NuGet Packages dialog, confirm that the Package source is set to nuget.org.

  3. With Browse selected, type System.Text.Encodings.Web in the search box.

  4. In the search results, select the System.Text.Encodings.Web package. Select the version of the package that matches the shared framework in use. Select Install.

  5. If the Preview Changes dialog appears, select OK.

  6. If the License Acceptance dialog appears, select I Accept if you agree with the license terms.

Add a SignalR hub

Create a Hubs (plural) folder and add the following ChatHub class (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Add services and an endpoint for the SignalR hub

  1. Open the Startup.cs file.

  2. Add the namespaces for Microsoft.AspNetCore.ResponseCompression and the ChatHub class to the top of the file:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. Add Response Compression Middleware services to Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });
    }
    
  4. In Startup.Configure:

    • Use Response Compression Middleware at the top of the processing pipeline's configuration.
    • Between the endpoints for mapping the Blazor hub and the client-side fallback, add an endpoint for the hub.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToPage("/_Host");
        });
    }
    

Add Razor component code for chat

  1. Open the Pages/Index.razor file.

  2. Replace the markup with the following code:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            await hubConnection?.DisposeAsync();
        }
    }
    

Run the app

Follow the guidance for your tooling:

  1. Press F5 to run the app with debugging or Ctrl+F5 (Windows)/+F5 (macOS) to run the app without debugging.

  2. Copy the URL from the address bar, open another browser instance or tab, and paste the URL in the address bar.

  3. Choose either browser, enter a name and message, and select the button to send the message. The name and message are displayed on both pages instantly:

    SignalR Blazor sample app open in two browser windows showing exchanged messages.

    Quotes: Star Trek VI: The Undiscovered Country ©1991 Paramount

Next steps

In this tutorial, you learned how to:

  • Create a Blazor project
  • Add the SignalR client library
  • Add a SignalR hub
  • Add SignalR services and an endpoint for the SignalR hub
  • Add Razor component code for chat

To learn more about building Blazor apps, see the Blazor documentation:

Additional resources