Partilhar via


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.

No Visual Studio:

  • Selecione Criar um projeto na Janela Inicial ou selecione Arquivo>Novo>Projeto na barra de menus.
  • Na caixa de diálogo Criar um projeto, selecione Blazor Aplicativo Web na lista de modelos de projeto. Selecione o botão Avançar.
  • Na caixa de diálogo Configurar seu novo projeto, nomeie o projeto BlazorSignalRApp no campo Nome do projeto, inclusive com a capitalização correspondente. É importante usar esse nome exato de projeto para garantir que os namespaces correspondam ao código que você copiar do tutorial para o aplicativo que estiver criando.
  • Confirme se o Local do aplicativo é adequado. Deixe marcada a caixa de seleção Colocar solução e projeto no mesmo diretório. Selecione o botão Avançar.
  • Na caixa de diálogo Informações adicionais, use as seguintes configurações:
    • Framework: Confirme se a estrutura mais recente está selecionada. Se a lista suspensa Framework do Visual Studio não incluir o .NET Framework mais recente disponível, atualize o Visual Studio e reinicie o tutorial.
    • Tipo de autenticação: Nenhum
    • Configure para HTTPS: Selecionado
    • Modo de renderização interativo: WebAssembly
    • Local de interatividade: Por página/componente
    • Incluir páginas de exemplo: Selecionado
    • Não usar declarações de nível superior: Não selecionado
    • Selecione Criar.

Adicionar a biblioteca de clientes SignalR

No Gerenciador de Soluções, clique com o botão direito do mouse no projeto BlazorSignalRApp.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 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

No projeto BlazorSignalRApp do servidor, crie uma pasta Hubs (plural) e adicione a seguinte classe ChatHub (Hubs/ChatHub.cs):

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 do projeto BlazorSignalRApp do servidor.

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

using Microsoft.AspNetCore.ResponseCompression;
using BlazorSignalRApp.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(
       ["application/octet-stream"]);
});

Use o Middleware de Compactação de Resposta na parte superior da configuração do pipeline de processamento. Coloque a seguinte linha de código imediatamente após a linha que cria o aplicativo (var app = builder.Build();):

app.UseResponseCompression();

Adicione um ponto de extremidade para o hub imediatamente antes da linha que executa o aplicativo (app.Run();):

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

Adicionar o código de componente Razor ao chat

Adicione o seguinte arquivo Pages/Chat.razor ao projeto BlazorSignalRApp.Client:

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

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

Adicione uma entrada ao componente NavMenu para acessar a página de chat. Em Components/Layout/NavMenu.razor, imediatamente após o bloco <div> para o componente Weather, adicione o seguinte bloco <div>:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="chat">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Chat
    </NavLink>
</div>

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:

Com o projeto do servidor BlazorSignalRApp selecionado no Gerenciador de Soluções, 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