ASP.NET Core SignalR cliente .netASP.NET Core SignalR .NET Client

O ASP.NET Core SignalR biblioteca de cliente .net permite que você se comunique com SignalR hubs de aplicativos .net.The ASP.NET Core SignalR .NET client library lets you communicate with SignalR hubs from .NET apps.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

O exemplo de código neste artigo é um aplicativo do WPF que usa o SignalR cliente .net ASP.NET Core.The code sample in this article is a WPF app that uses the ASP.NET Core SignalR .NET client.

Instalar o SignalR pacote do cliente .netInstall the SignalR .NET client package

O Microsoft. AspNetCore. SignalR . O pacote do cliente é necessário para que os clientes .net se conectem aos SignalR hubs.The Microsoft.AspNetCore.SignalR.Client package is required for .NET clients to connect to SignalR hubs.

Para instalar a biblioteca de cliente, execute o seguinte comando na janela do console do Gerenciador de pacotes :To install the client library, run the following command in the Package Manager Console window:

Install-Package Microsoft.AspNetCore.SignalR.Client

Conectar-se a um hubConnect to a hub

Para estabelecer uma conexão, crie uma HubConnectionBuilder chamada e Build .To establish a connection, create a HubConnectionBuilder and call Build. A URL do Hub, o protocolo, o tipo de transporte, o nível de log, os cabeçalhos e outras opções podem ser configurados durante a criação de uma conexão.The hub URL, protocol, transport type, log level, headers, and other options can be configured while building a connection. Configure as opções necessárias inserindo qualquer um dos HubConnectionBuilder métodos no Build .Configure any required options by inserting any of the HubConnectionBuilder methods into Build. Inicie a conexão com StartAsync .Start the connection with StartAsync.

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

namespace SignalRChatClient
{
    public partial class MainWindow : Window
    {
        HubConnection connection;
        public MainWindow()
        {
            InitializeComponent();

            connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:53353/ChatHub")
                .Build();

            connection.Closed += async (error) =>
            {
                await Task.Delay(new Random().Next(0,5) * 1000);
                await connection.StartAsync();
            };
        }

        private async void connectButton_Click(object sender, RoutedEventArgs e)
        {
            connection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                this.Dispatcher.Invoke(() =>
                {
                   var newMessage = $"{user}: {message}";
                   messagesList.Items.Add(newMessage);
                });
            });

            try
            {
                await connection.StartAsync();
                messagesList.Items.Add("Connection started");
                connectButton.IsEnabled = false;
                sendButton.IsEnabled = true;
            }
            catch (Exception ex)
            {
                messagesList.Items.Add(ex.Message);
            }
        }

        private async void sendButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                await connection.InvokeAsync("SendMessage", 
                    userTextBox.Text, messageTextBox.Text);
            }
            catch (Exception ex)
            {                
                messagesList.Items.Add(ex.Message);                
            }
        }
    }
}

Tratar conexão perdidaHandle lost connection

Reconectar automaticamenteAutomatically reconnect

O HubConnection pode ser configurado para reconectar-se automaticamente usando o WithAutomaticReconnect método no HubConnectionBuilder .The HubConnection can be configured to automatically reconnect using the WithAutomaticReconnect method on the HubConnectionBuilder. Ele não se reconectará automaticamente por padrão.It won't automatically reconnect by default.

HubConnection connection= new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
    .WithAutomaticReconnect()
    .Build();

Sem parâmetros, WithAutomaticReconnect() o configura o cliente para aguardar 0, 2, 10 e 30 segundos, respectivamente, antes de tentar cada tentativa de reconexão, parando após quatro tentativas com falha.Without any parameters, WithAutomaticReconnect() configures the client to wait 0, 2, 10, and 30 seconds respectively before trying each reconnect attempt, stopping after four failed attempts.

Antes de iniciar qualquer tentativa de reconexão, o HubConnection fará a transição para o HubConnectionState.Reconnecting estado e acionará o Reconnecting evento.Before starting any reconnect attempts, the HubConnection will transition to the HubConnectionState.Reconnecting state and fire the Reconnecting event. Isso fornece uma oportunidade para avisar os usuários de que a conexão foi perdida e para desabilitar os elementos da interface do usuário.This provides an opportunity to warn users that the connection has been lost and to disable UI elements. Aplicativos não interativos podem começar a enfileirar ou descartar mensagens.Non-interactive apps can start queuing or dropping messages.

connection.Reconnecting += error =>
{
    Debug.Assert(connection.State == HubConnectionState.Reconnecting);

    // Notify users the connection was lost and the client is reconnecting.
    // Start queuing or dropping messages.

    return Task.CompletedTask;
};

Se o cliente se reconectar com êxito dentro de suas primeiras quatro tentativas, o HubConnection fará a transição de volta para o Connected estado e acionará o Reconnected evento.If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire the Reconnected event. Isso fornece uma oportunidade de informar aos usuários que a conexão foi restabelecida e remover todas as mensagens na fila.This provides an opportunity to inform users the connection has been reestablished and dequeue any queued messages.

Como a conexão é totalmente nova no servidor, um novo ConnectionId será fornecido para os Reconnected manipuladores de eventos.Since the connection looks entirely new to the server, a new ConnectionId will be provided to the Reconnected event handlers.

Aviso

O Reconnected parâmetro do manipulador de eventos connectionId será NULL se o HubConnection tiver sido configurado para ignorar a negociação.The Reconnected event handler's connectionId parameter will be null if the HubConnection was configured to skip negotiation.

connection.Reconnected += connectionId =>
{
    Debug.Assert(connection.State == HubConnectionState.Connected);

    // Notify users the connection was reestablished.
    // Start dequeuing messages queued while reconnecting if any.

    return Task.CompletedTask;
};

WithAutomaticReconnect() não configurará o HubConnection para tentar falhas de início inicial, portanto, as falhas de início precisam ser manipuladas manualmente:WithAutomaticReconnect() won't configure the HubConnection to retry initial start failures, so start failures need to be handled manually:

public static async Task<bool> ConnectWithRetryAsync(HubConnection connection, CancellationToken token)
{
    // Keep trying to until we can start or the token is canceled.
    while (true)
    {
        try
        {
            await connection.StartAsync(token);
            Debug.Assert(connection.State == HubConnectionState.Connected);
            return true;
        }
        catch when (token.IsCancellationRequested)
        {
            return false;
        }
        catch
        {
            // Failed to connect, trying again in 5000 ms.
            Debug.Assert(connection.State == HubConnectionState.Disconnected);
            await Task.Delay(5000);
        }
    }
}

Se o cliente não se reconectar com êxito dentro de suas primeiras quatro tentativas, o HubConnection fará a transição para o Disconnected estado e acionará o Closed evento.If the client doesn't successfully reconnect within its first four attempts, the HubConnection will transition to the Disconnected state and fire the Closed event. Isso oferece uma oportunidade de tentar reiniciar a conexão manualmente ou informar aos usuários que a conexão foi permanentemente perdida.This provides an opportunity to attempt to restart the connection manually or inform users the connection has been permanently lost.

connection.Closed += error =>
{
    Debug.Assert(connection.State == HubConnectionState.Disconnected);

    // Notify users the connection has been closed or manually try to restart the connection.

    return Task.CompletedTask;
};

Para configurar um número personalizado de tentativas de reconexão antes de desconectar ou alterar o tempo de reconexão, o WithAutomaticReconnect aceita uma matriz de números que representa o atraso em milissegundos para aguardar antes de iniciar cada tentativa de reconexão.In order to configure a custom number of reconnect attempts before disconnecting or change the reconnect timing, WithAutomaticReconnect accepts an array of numbers representing the delay in milliseconds to wait before starting each reconnect attempt.

HubConnection connection= new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
    .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(10) })
    .Build();

    // .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30) }) yields the default behavior.

O exemplo anterior configura o HubConnection para iniciar a tentativa de reconectar imediatamente após a perda da conexão.The preceding example configures the HubConnection to start attempting reconnects immediately after the connection is lost. Isso também é verdadeiro para a configuração padrão.This is also true for the default configuration.

Se a primeira tentativa de reconexão falhar, a segunda tentativa de reconexão também será iniciada imediatamente, em vez de esperar 2 segundos, como seria na configuração padrão.If the first reconnect attempt fails, the second reconnect attempt will also start immediately instead of waiting 2 seconds like it would in the default configuration.

Se a segunda tentativa de reconexão falhar, a terceira tentativa de reconexão será iniciada em 10 segundos, o que é novamente como a configuração padrão.If the second reconnect attempt fails, the third reconnect attempt will start in 10 seconds which is again like the default configuration.

O comportamento personalizado, em seguida, deriva novamente do comportamento padrão ao parar após a terceira falha de tentativa de reconexão.The custom behavior then diverges again from the default behavior by stopping after the third reconnect attempt failure. Na configuração padrão, haveria mais uma tentativa de reconexão em outros 30 segundos.In the default configuration there would be one more reconnect attempt in another 30 seconds.

Se você quiser ainda mais controle sobre o tempo e o número de tentativas de reconexão automática, o WithAutomaticReconnect aceitará um objeto que implementa a IRetryPolicy interface, que tem um único método chamado NextRetryDelay .If you want even more control over the timing and number of automatic reconnect attempts, WithAutomaticReconnect accepts an object implementing the IRetryPolicy interface, which has a single method named NextRetryDelay.

NextRetryDelay usa um único argumento com o tipo RetryContext .NextRetryDelay takes a single argument with the type RetryContext. O RetryContext tem três propriedades: PreviousRetryCount , ElapsedTime e RetryReason , que são a long , a TimeSpan e uma Exception respectivamente.The RetryContext has three properties: PreviousRetryCount, ElapsedTime and RetryReason, which are a long, a TimeSpan and an Exception respectively. Antes da primeira tentativa de reconexão, PreviousRetryCount e ElapsedTime será zero, e RetryReason será a exceção que causou a perda da conexão.Before the first reconnect attempt, both PreviousRetryCount and ElapsedTime will be zero, and the RetryReason will be the Exception that caused the connection to be lost. Após cada tentativa de repetição com falha, o PreviousRetryCount será incrementado em um, ElapsedTime será atualizado para refletir a quantidade de tempo gasto reconectando até o momento, e o RetryReason será a exceção que causou a falha da última tentativa de reconexão.After each failed retry attempt, PreviousRetryCount will be incremented by one, ElapsedTime will be updated to reflect the amount of time spent reconnecting so far, and the RetryReason will be the Exception that caused the last reconnect attempt to fail.

NextRetryDelay deve retornar um TimeSpan que representa o tempo de espera antes da próxima tentativa de reconexão ou null se o HubConnection deve parar de reconectar.NextRetryDelay must return either a TimeSpan representing the time to wait before the next reconnect attempt or null if the HubConnection should stop reconnecting.

public class RandomRetryPolicy : IRetryPolicy
{
    private readonly Random _random = new Random();

    public TimeSpan? NextRetryDelay(RetryContext retryContext)
    {
        // If we've been reconnecting for less than 60 seconds so far,
        // wait between 0 and 10 seconds before the next reconnect attempt.
        if (retryContext.ElapsedTime < TimeSpan.FromSeconds(60))
        {
            return TimeSpan.FromSeconds(_random.NextDouble() * 10);
        }
        else
        {
            // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
            return null;
        }
    }
}
HubConnection connection = new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
    .WithAutomaticReconnect(new RandomRetryPolicy())
    .Build();

Como alternativa, você pode escrever um código que reconectará o cliente manualmente, conforme demonstrado na reconexão manual.Alternatively, you can write code that will reconnect your client manually as demonstrated in Manually reconnect.

Reconectar manualmenteManually reconnect

Aviso

Antes do 3,0, o cliente .NET do SignalR não se reconecta automaticamente.Prior to 3.0, the .NET client for SignalR doesn't automatically reconnect. Você deve escrever um código que reconectará o cliente manualmente.You must write code that will reconnect your client manually.

Use o Closed evento para responder a uma conexão perdida.Use the Closed event to respond to a lost connection. Por exemplo, talvez você queira automatizar a reconexão.For example, you might want to automate reconnection.

O Closed evento requer um delegado que retorne um Task , que permite que o código assíncrono seja executado sem usar o async void .The Closed event requires a delegate that returns a Task, which allows async code to run without using async void. Para satisfazer a assinatura de delegado em um Closed manipulador de eventos executado de forma síncrona, retorne Task.CompletedTask :To satisfy the delegate signature in a Closed event handler that runs synchronously, return Task.CompletedTask:

connection.Closed += (error) => {
    // Do your close logic.
    return Task.CompletedTask;
};

O principal motivo para o suporte assíncrono é que você pode reiniciar a conexão.The main reason for the async support is so you can restart the connection. Iniciar uma conexão é uma ação assíncrona.Starting a connection is an async action.

Em um Closed manipulador que reinicia a conexão, considere aguardar um atraso aleatório para evitar sobrecarregar o servidor, conforme mostrado no exemplo a seguir:In a Closed handler that restarts the connection, consider waiting for some random delay to prevent overloading the server, as shown in the following example:

connection.Closed += async (error) =>
{
    await Task.Delay(new Random().Next(0,5) * 1000);
    await connection.StartAsync();
};

Métodos do hub de chamadas do clienteCall hub methods from client

InvokeAsync chama métodos no Hub.InvokeAsync calls methods on the hub. Passe o nome do método de Hub e quaisquer argumentos definidos no método de Hub para InvokeAsync .Pass the hub method name and any arguments defined in the hub method to InvokeAsync. SignalR é assíncrona, portanto, use async e await ao fazer as chamadas.SignalR is asynchronous, so use async and await when making the calls.

await connection.InvokeAsync("SendMessage", 
    userTextBox.Text, messageTextBox.Text);

O InvokeAsync método retorna um Task que é concluído quando o método de servidor retorna.The InvokeAsync method returns a Task which completes when the server method returns. O valor de retorno, se houver, é fornecido como o resultado do Task .The return value, if any, is provided as the result of the Task. Todas as exceções geradas pelo método no servidor produzem uma falha Task .Any exceptions thrown by the method on the server produce a faulted Task. Use a await sintaxe para aguardar a conclusão do método de servidor e a try...catch sintaxe para lidar com erros.Use await syntax to wait for the server method to complete and try...catch syntax to handle errors.

O SendAsync método retorna um Task que é concluído quando a mensagem é enviada ao servidor.The SendAsync method returns a Task which completes when the message has been sent to the server. Nenhum valor de retorno é fornecido, pois isso Task não aguarda até que o método de servidor seja concluído.No return value is provided since this Task doesn't wait until the server method completes. Todas as exceções geradas no cliente durante o envio da mensagem produzem uma falha Task .Any exceptions thrown on the client while sending the message produce a faulted Task. Use await e try...catch sintaxe para lidar com erros de envio.Use await and try...catch syntax to handle send errors.

Observação

Somente há suporte para métodos de Hub de chamada de um cliente ao usar o serviço do Azure SignalR no modo padrão .Calling hub methods from a client is only supported when using the Azure SignalR Service in Default mode. Para obter mais informações, consulte perguntas frequentes (repositório GitHub do Azure-signalr).For more information, see Frequently Asked Questions (azure-signalr GitHub repository).

Chamar métodos de cliente do HubCall client methods from hub

Defina os métodos que o Hub chama usando connection.On após a compilação, mas antes de iniciar a conexão.Define methods the hub calls using connection.On after building, but before starting the connection.

connection.On<string, string>("ReceiveMessage", (user, message) =>
{
    this.Dispatcher.Invoke(() =>
    {
       var newMessage = $"{user}: {message}";
       messagesList.Items.Add(newMessage);
    });
});

O código anterior em connection.On é executado quando o código do lado do servidor o chama usando o SendAsync método.The preceding code in connection.On runs when server-side code calls it using the SendAsync method.

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

Registro em log e tratamento de errosError handling and logging

Tratar erros com uma instrução try-catch.Handle errors with a try-catch statement. Inspecione o Exception objeto para determinar a ação apropriada a ser tomada após ocorrer um erro.Inspect the Exception object to determine the proper action to take after an error occurs.

try
{
    await connection.InvokeAsync("SendMessage", 
        userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{                
    messagesList.Items.Add(ex.Message);                
}

Recursos adicionaisAdditional resources