Usar ASP.NET Core SignalR com Blazor

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Este tutorial fornece uma experiência de trabalho básica para criar um aplicativo em tempo real usando SignalR com Blazor. Este artigo é útil para os desenvolvedores que já estão familiarizados com SignalR e querem entender como usar SignalR em um Blazor aplicativo. Para obter diretrizes detalhadas sobre as SignalR e Blazor estruturas, consulte os seguintes conjuntos de documentação de referência e a documentação da API:

Saiba como:

  • Criar um aplicativo Blazor
  • Adicionar a biblioteca de clientes SignalR
  • Adicionar um hub SignalR
  • Adicionar serviços SignalR e um ponto de extremidade para o hub SignalR
  • Adicionar o Razor código do componente ao chat

No final deste tutorial, você terá um aplicativo de chat funcional.

Pré-requisitos

Visual Studio 2022 ou posterior com a carga de trabalho de desenvolvimento web e noASP.NET ASP.NET

Aplicativo de exemplo

Baixar o aplicativo de chat usado como exemplo não é necessário para este tutorial. O aplicativo de exemplo é o aplicativo final de trabalho produzido seguindo as etapas deste tutorial.

Exibir ou baixar código de exemplo (como baixar)

Criar um aplicativo web do Blazor

Siga as diretrizes para sua escolha de ferramentas:

Observação

São necessários o Visual Studio 2022 ou posterior e o SDK do .NET Core 8.0.0 ou posterior.

Criar um novo projeto.

Selecione o modelo do Aplicativo Web do Blazor. Selecione Avançar.

Digite BlazorSignalRApp no campo Nome do projeto. Confirme se a entrada Local está correta ou forneça um local para o projeto. Selecione Avançar.

Confirme se o Framework é o .NET 8 ou posterior. Selecione Criar.

Adicionar a biblioteca de clientes SignalR

No Gerenciador de Soluções, clique com o botão direito do mouse no projeto BlazorSignalRApp e selecione Gerenciar Pacotes NuGet.

Na caixa de diálogo Gerenciar pacotes NuGet, confirme se a Fonte de dados do pacote está definida como nuget.org.

Com Procurar selecionado, digite Microsoft.AspNetCore.SignalR.Client na caixa de pesquisa.

Nos resultados da pesquisa, selecione a versão mais recente do pacote Microsoft.AspNetCore.SignalR.Client. Selecione Instalar.

Se a caixa de diálogo Visualizar Alterações aparecer, selecione OK.

Se a caixa de diálogo Aceitação da Licença for exibida, selecione Aceito se você concordar com os termos de licença.

Adicionar um hub SignalR

Crie uma pasta Hubs (plural) e adicione a seguinte classe ChatHub (Hubs/ChatHub.cs) à raiz do aplicativo:

using Microsoft.AspNetCore.SignalR;

namespace BlazorSignalRApp.Hubs;

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

Adicionar serviços e um ponto de extremidade para o hub SignalR

Abra o arquivo Program.

Adicione os namespaces para Microsoft.AspNetCore.ResponseCompression e a classe ChatHub à parte superior do arquivo:

using Microsoft.AspNetCore.ResponseCompression;
using BlazorSignalRApp.Hubs;

Adicione serviços de Middleware de Compactação de Resposta:

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

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento:

app.UseResponseCompression();

Adicione um ponto de extremidade para o hub imediatamente após a linha que mapeia os componentes Razor (app.MapRazorComponents<T>()):

app.MapHub<ChatHub>("/chathub");

Adicionar o código de componente Razor ao chat

Abra o arquivo Components/Pages/Home.razor .

Substitua a marcação pelo seguinte código:

@page "/"
@rendermode InteractiveServer
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager Navigation
@implements IAsyncDisposable

<PageTitle>Home</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();
        }
    }
}

Observação

Desabilite o Middleware de Compactação de Resposta no Development ambiente ao usar o Recarga Dinâmica. Para obter mais informações, confira as diretrizes BlazorSignalRdo ASP.NET Core.

Executar o aplicativo

Siga as diretrizes para suas ferramentas:

Pressione F5 para executar o aplicativo com depuração ou Ctrl+F5 (Windows)/+F5 (macOS) para executar o aplicativo sem depuração.

Copie a URL da barra de endereços, abra outra instância ou guia do navegador e cole a URL na barra de endereços.

Escolha qualquer navegador, insira um nome e uma mensagem e selecione o botão para enviar a mensagem. O nome e a mensagem são exibidos em ambas as páginas instantaneamente:

SignalRBlazor aplicativo de exemplo aberto em duas janelas do navegador mostrando mensagens trocadas.

Citações: Star Trek VI: O País Desconhecido ©1991 Paramount

A experiência hospedada Blazor WebAssembly

Criar o aplicativo

Siga as diretrizes de sua escolha de ferramentas para criar um aplicativo hospedado Blazor WebAssembly:

Observação

O Visual Studio 2022 ou posterior e o SDK do .NET Core 6.0.0 ou posterior são necessários.

Crie um novo projeto.

Escolha o modelo doaplicativoBlazor WebAssembly. Selecione Avançar.

Digite BlazorWebAssemblySignalRApp no campo Nome do projeto. Confirme se a entrada Local está correta ou forneça um local para o projeto. Selecione Avançar.

Na caixa de diálogo Informações adicionais, marque a caixa de seleção ASP.NET Core Hospedado.

Selecione Criar.

Confirme se um aplicativo hospedado Blazor WebAssembly foi criado: em Gerenciador de Soluções, confirme a presença de um projeto Client e de um projeto Server. Se os dois projetos não estiverem presentes, comece novamente e confirme a caixa de seleção ASP.NET Core Hospedado antes de selecionar Criar.

Adicionar a biblioteca de clientes SignalR

No Gerenciador de Soluções, clique com o botão direito do mouse no projeto BlazorWebAssemblySignalRApp.Client e selecione Gerenciar Pacotes NuGet.

Na caixa de diálogo Gerenciar pacotes NuGet, confirme se a Fonte de dados do pacote está definida como nuget.org.

Com Procurar selecionado, digite Microsoft.AspNetCore.SignalR.Client na caixa de pesquisa.

Nos resultados da pesquisa, selecione o pacote Microsoft.AspNetCore.SignalR.Client. Defina a versão para corresponder à estrutura compartilhada do aplicativo. Clique em Instalar.

Se a caixa de diálogo Visualizar Alterações aparecer, selecione OK.

Se a caixa de diálogo Aceitação da Licença for exibida, selecione Aceito se você concordar com os termos de licença.

Adicionar um hub SignalR

BlazorWebAssemblySignalRApp.Server No projeto, crie uma pasta (plural) Hubs e adicione a seguinte classe ChatHub (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);
    }
}
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);
    }
}
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);
        }
    }
}
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);
        }
    }
}

Adicionar serviços e um ponto de extremidade para o hub SignalR

No BlazorWebAssemblySignalRApp.Server projeto, abra o Program.cs arquivo.

Adicione o namespace da classe ChatHub à parte superior do arquivo:

using BlazorWebAssemblySignalRApp.Server.Hubs;

Adicione SignalR e Serviços de Middleware de Compactação de resposta:

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

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento imediatamente após a linha que cria o aplicativo:

app.UseResponseCompression();

Entre os pontos de extremidade para controladores e o fallback do lado do cliente, adicione um ponto de extremidade para o hub. Imediatamente após a linha app.MapControllers();, adicione a seguinte linha:

app.MapHub<ChatHub>("/chathub");

No projeto BlazorWebAssemblySignalRApp.Server, abra o arquivo Startup.cs.

Adicione o namespace da classe ChatHub à parte superior do arquivo:

using BlazorWebAssemblySignalRApp.Server.Hubs;

Adicione SignalR e Serviços de Middleware de Compactação de resposta:

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

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento:

app.UseResponseCompression();

Entre os pontos de extremidade dos controladores e o fallback do lado do cliente, adicione um ponto de extremidade ao hub imediatamente após a linha endpoints.MapControllers();:

endpoints.MapHub<ChatHub>("/chathub");

Adicionar o código de componente Razor ao chat

No projeto BlazorWebAssemblySignalRApp.Client, abra o arquivo Pages/Index.razor.

Substitua a marcação pelo seguinte código:

@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();
        }
    }
}
@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();
        }
    }
}
@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();
        }
    }
}
@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();
    }
}

Observação

Desabilite o Middleware de Compactação de Resposta no Development ambiente ao usar o Recarga Dinâmica. Para obter mais informações, confira as diretrizes BlazorSignalRdo ASP.NET Core.

Executar o aplicativo

Siga as diretrizes para suas ferramentas:

No Gerenciador de Soluções, selecione o projeto BlazorWebAssemblySignalRApp.Server. Pressione F5 para executar o aplicativo com depuração ou Ctrl+F5 (Windows)/+F5 (macOS) para executar o aplicativo sem depuração.

Importante

Ao executar um aplicativo Blazor WebAssembly hospedado, execute o aplicativo no projeto de da soluçãoServer.

O Google Chrome ou o Microsoft Edge devem ser o navegador selecionado para uma sessão de depuração.

Se o aplicativo não for iniciado no navegador:

  • No console do .NET, confirme se a solução está em execução no projeto "Server".
  • Atualize o navegador usando o botão recarregar.

Copie a URL da barra de endereços, abra outra instância ou guia do navegador e cole a URL na barra de endereços.

Escolha qualquer navegador, insira um nome e uma mensagem e selecione o botão para enviar a mensagem. O nome e a mensagem são exibidos em ambas as páginas instantaneamente:

SignalRBlazor aplicativo de exemplo aberto em duas janelas do navegador mostrando mensagens trocadas.

Citações: Star Trek VI: O País Desconhecido ©1991 Paramount

Blazor Server experiência

Criar o aplicativo

Siga as diretrizes de sua escolha de ferramentas para criar um aplicativo Blazor Server:

Observação

O Visual Studio 2022 ou posterior e o SDK do .NET Core 6.0.0 ou posterior são necessários.

Crie um novo projeto.

Selecione o modelo doBlazor Serveraplicativo. Selecione Avançar.

Digite BlazorServerSignalRApp no campo Nome do projeto. Confirme se a entrada Local está correta ou forneça um local para o projeto. Selecione Avançar.

Selecione Criar.

Adicionar a biblioteca de clientes SignalR

No Gerenciador de Soluções, clique com o botão direito do mouse no projeto BlazorServerSignalRApp e selecione Gerenciar Pacotes NuGet.

Na caixa de diálogo Gerenciar pacotes NuGet, confirme se a Fonte de dados do pacote está definida como nuget.org.

Com Procurar selecionado, digite Microsoft.AspNetCore.SignalR.Client na caixa de pesquisa.

Nos resultados da pesquisa, selecione o pacote Microsoft.AspNetCore.SignalR.Client. Defina a versão para corresponder à estrutura compartilhada do aplicativo. Clique em Instalar.

Se a caixa de diálogo Visualizar Alterações aparecer, selecione OK.

Se a caixa de diálogo Aceitação da Licença for exibida, selecione Aceito se você concordar com os termos de licença.

Adicionar o pacote System.Text.Encodings.Web

Esta seção só se aplica a aplicativos para ASP.NET Core versão 3.x.

Devido a um problema de resolução de pacote ao usar o 5.x System.Text.Json em um aplicativo ASP.NET Core 3.x, o projeto exige uma referência de pacote para System.Text.Encodings.Web. O problema subjacente foi resolvido em uma versão de patch e com suporte para o ASP.NET Core 5.0. Para obter mais informações, consulte System.Text.Json define netcoreapp3.0 sem dependências (dotnet/runtime #45560).

Para adicionar System.Text.Encodings.Web ao projeto, siga as diretrizes para sua escolha de ferramentas:

No Gerenciador de Soluções, clique com o botão direito do mouse no projeto BlazorServerSignalRApp e selecione Gerenciar Pacotes NuGet.

Na caixa de diálogo Gerenciar pacotes NuGet, confirme se a Fonte de dados do pacote está definida como nuget.org.

Com Procurar selecionado, digite System.Text.Encodings.Web na caixa de pesquisa.

Nos resultados da pesquisa, selecione o pacote System.Text.Encodings.Web. Selecione a versão do pacote que corresponde à estrutura compartilhada em uso. Clique em Instalar.

Se a caixa de diálogo Visualizar Alterações aparecer, selecione OK.

Se a caixa de diálogo Aceitação da Licença for exibida, selecione Aceito se você concordar com os termos de licença.

Adicionar um hub SignalR

Crie uma pasta (plural)Hubs e adicione a seguinte classe ChatHub (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);
    }
}
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);
    }
}
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);
        }
    }
}
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);
        }
    }
}

Adicionar serviços e um ponto de extremidade para o hub SignalR

Abra o arquivo Program.cs.

Adicione os namespaces para Microsoft.AspNetCore.ResponseCompression e a classe ChatHub à parte superior do arquivo:

using Microsoft.AspNetCore.ResponseCompression;
using BlazorServerSignalRApp.Server.Hubs;

Adicione serviços de Middleware de Compactação de Resposta:

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

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento:

app.UseResponseCompression();

Entre os pontos de extremidade para mapear o hub Blazor e o fallback do lado do cliente, adicione um ponto de extremidade ao hub imediatamente após a linha app.MapBlazorHub();:

app.MapHub<ChatHub>("/chathub");

Abra o arquivo Startup.cs.

Adicione os namespaces para Microsoft.AspNetCore.ResponseCompression e a classe ChatHub à parte superior do arquivo:

using Microsoft.AspNetCore.ResponseCompression;
using BlazorServerSignalRApp.Server.Hubs;

Adicione serviços de Middleware de Compactação de Resposta:

services.AddResponseCompression(opts =>
{
   opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
         new[] { "application/octet-stream" });
});

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento:

app.UseResponseCompression();

Entre os pontos de extremidade para mapear o hub Blazor e o fallback do lado do cliente, adicione um ponto de extremidade ao hub imediatamente após a linha endpoints.MapBlazorHub();:

endpoints.MapHub<ChatHub>("/chathub");

Adicionar o código de componente Razor ao chat

Abra o arquivo Pages/Index.razor .

Substitua a marcação pelo seguinte código:

@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();
        }
    }
}
@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();
        }
    }
}
@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();
        }
    }
}
@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();
    }
}

Observação

Desabilite o Middleware de Compactação de Resposta no Development ambiente ao usar o Recarga Dinâmica. Para obter mais informações, confira as diretrizes BlazorSignalRdo ASP.NET Core.

Executar o aplicativo

Siga as diretrizes para suas ferramentas:

Pressione F5 para executar o aplicativo com depuração ou Ctrl+F5 (Windows)/+F5 (macOS) para executar o aplicativo sem depuração.

Copie a URL da barra de endereços, abra outra instância ou guia do navegador e cole a URL na barra de endereços.

Escolha qualquer navegador, insira um nome e uma mensagem e selecione o botão para enviar a mensagem. O nome e a mensagem são exibidos em ambas as páginas instantaneamente:

SignalRBlazor aplicativo de exemplo aberto em duas janelas do navegador mostrando mensagens trocadas.

Citações: Star Trek VI: O País Desconhecido ©1991 Paramount

Próximas etapas

Neste tutorial, você aprendeu como:

  • Criar um aplicativo Blazor
  • Adicionar a biblioteca de clientes SignalR
  • Adicionar um hub SignalR
  • Adicionar serviços SignalR e um ponto de extremidade para o hub SignalR
  • Adicionar o Razor código do componente ao chat

Para obter diretrizes detalhadas sobre as estruturas de SignalR e Blazor, consulte os seguintes conjuntos de documentação de referência:

Recursos adicionais