Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La bibliothèque de client .NET SignalR ASP.NET Core vous permet de communiquer avec les hubs SignalR des applications .NET. Cet article explique comment utiliser les API pour se connecter à un hub SignalR et appeler le hub .NET et les méthodes clientes. L’exemple de code de cet article est une application Windows Presentation Foundation (WPF) qui utilise le client ASP.NET Core SignalR .NET.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Installer le package client .NET SignalR
Le package Microsoft.AspNetCore.SignalR.Client est requis pour permettre aux clients .NET de se connecter aux hubs SignalR. Vous pouvez installer la bibliothèque cliente à partir de la console Visual Studio Gestionnaire de package ou à l’aide de l’interface CLI .NET.
Exécutez la commande suivante dans la fenêtre Gestionnaire de package Console :
Install-Package Microsoft.AspNetCore.SignalR.Client
Se connecter à un hub
Pour établir une connexion, créez un HubConnectionBuilder et appelez Build. L’URL du hub, le protocole, le type de transport, le niveau du journal, les en-têtes et d’autres options peuvent être configurés lors de la création d’une connexion. Configurez toute option requise en insérant l'une des méthodes HubConnectionBuilder dans Build. Démarrez la connexion avec 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);
}
}
}
}
Gérer une connexion perdue
Pour vous reconnecter avec les clients, vous pouvez configurer la reconnexion automatique ou configurer la reconnexion manuellement.
Reconnecter automatiquement
Le HubConnection peut être configuré pour se reconnecter automatiquement à l’aide de la méthode WithAutomaticReconnect du HubConnectionBuilder. Elle ne se reconnecte pas automatiquement par défaut.
HubConnection connection= new HubConnectionBuilder()
.WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
.WithAutomaticReconnect()
.Build();
Sans aucun paramètre, WithAutomaticReconnect() configure le client pour attendre 0, 2, 10 et 30 secondes respectivement avant d’essayer chaque tentative de reconnexion. Il s’arrête après quatre tentatives ayant échoué.
Avant de démarrer toute tentative de reconnexion, HubConnection passe à l’état HubConnectionState.Reconnecting et déclenche l’événement Reconnecting. Cette approche permet d’avertir les utilisateurs que la connexion est perdue et de désactiver les éléments de l’interface utilisateur. Les applications non interactives peuvent commencer à mettre des messages en file d’attente ou à les annuler.
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;
};
Si le client se reconnecte correctement dans ses quatre premières tentatives, le HubConnection passage à l’état Connected et déclenche l’événement Reconnected . Cette approche permet d’informer les utilisateurs que la connexion est désormais rétablie et de retirer de la file d’attente tous les messages en attente.
Comme la connexion semble entièrement nouvelle au serveur, un nouveau ConnectionId est fourni aux gestionnaires de l’événement Reconnected.
Warning
Le Reconnected paramètre du gestionnaire d’événements connectionId est null s’il est configuré pour HubConnection la négociation.
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() ne configure pas le HubConnection pour réessayer en cas d’échec du démarrage initial ; les échecs de démarrage doivent donc être gérés manuellement :
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);
}
}
}
Si le client ne se reconnecte pas avec succès au cours de ses quatre premières tentatives, le HubConnection passe à l’état Disconnected et déclenche l’événement Closed. Cette approche offre la possibilité de tenter de redémarrer la connexion manuellement ou d’informer les utilisateurs que la connexion est maintenant définitivement perdue.
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;
};
Pour configurer un nombre personnalisé de tentatives de reconnexion avant de déconnecter ou de modifier le minutage de la reconnexion, WithAutomaticReconnect accepte un tableau de nombres représentant le délai en millisecondes à attendre avant de démarrer chaque tentative de reconnexion.
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.
L'exemple précédent configure le HubConnection pour qu'il commence à tenter des reconnexions immédiatement après la perte de la connexion. Cette approche est également vraie pour la configuration par défaut.
Si la première tentative de reconnexion échoue, la deuxième tentative de reconnexion démarre également immédiatement au lieu d’attendre 2 secondes, comme défini dans la configuration par défaut.
Si la deuxième tentative de reconnexion échoue, la troisième tentative de reconnexion démarre en 10 secondes, ce qui est le même comportement défini dans la configuration par défaut.
Le comportement personnalisé s’écarte à nouveau du comportement par défaut en s’arrêtant après l’échec de la troisième tentative de reconnexion. Dans la configuration par défaut, une nouvelle tentative de reconnexion est effectuée après 30 secondes.
Pour plus de contrôle sur la synchronisation et le nombre de tentatives de reconnexion automatique, WithAutomaticReconnect accepte un objet implémentant l'interface IRetryPolicy, qui a une seule méthode nommée NextRetryDelay.
NextRetryDelay prend un seul argument de type RetryContext. L’objet RetryContext a trois propriétés : PreviousRetryCount (type long), ElapsedTime (type TimeSpan) et RetryReason (type Exception).
Avant la première tentative de reconnexion,
PreviousRetryCountetElapsedTimeest à la fois zéro (0), etRetryReasonest l’exception qui a provoqué la perte de connexion.Après chaque tentative de réessai ayant échoué,
PreviousRetryCountest incrémenté de un,ElapsedTimeest mis à jour pour refléter le temps passé à se reconnecter jusqu’à présent, etRetryReasonest l’exception qui a provoqué l’échec de la dernière tentative de reconnexion.
NextRetryDelay doit retourner soit une valeur TimeSpan indiquant le délai à attendre avant la prochaine tentative de reconnexion, soit null si le HubConnection doit cesser de se reconnecter.
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();
Vous pouvez également écrire du code pour reconnecter votre client manuellement, comme illustré dans la section suivante.
Reconnecter manuellement
Warning
Dans les versions antérieures à la version 3.0, le client .NET pour SignalR ne se reconnecte pas automatiquement. Vous devez écrire du code pour reconnecter votre client manuellement.
Utilisez l’événement Closed pour répondre à une connexion perdue. Par exemple, vous pouvez tenter d’automatiser la reconnexion.
L’événement Closed nécessite un délégué qui retourne une Task, permettant au code asynchrone de s’exécuter sans utiliser async void. Pour satisfaire la signature déléguée dans un gestionnaire d’événements Closed qui s’exécute de manière synchrone, retournez Task.CompletedTask :
connection.Closed += (error) => {
// Do your close logic.
return Task.CompletedTask;
};
La prise en charge asynchrone a pour motif principal le redémarrage de la connexion. Le démarrage d’une connexion est une action asynchrone.
Dans un gestionnaire Closed qui redémarre la connexion, envisagez d’attendre un délai aléatoire pour éviter la surcharge du serveur, comme illustré dans l’exemple suivant :
connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0,5) * 1000);
await connection.StartAsync();
};
Appeler des méthodes hub à partir du client
InvokeAsync appelle des méthodes sur le hub. Transmettez le nom de la méthode hub et tout argument défini dans la méthode hub à InvokeAsync.
SignalR étant asynchrone, utilisez async et await lors des appels.
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
La méthode InvokeAsync renvoie un Task qui s’achève lorsque la méthode du serveur renvoie un résultat. La valeur de retour, le cas échéant, est fournie en tant que résultat de la Task. Toutes les exceptions jetées par la méthode sur le serveur produisent une Task en défaut. Utilisez la syntaxe await pour attendre que la méthode serveur se termine et la syntaxe try...catch pour gérer les erreurs.
La méthode SendAsync renvoie un(e) Task qui s’achève lorsque le message est envoyé au serveur. Aucune valeur de retour n’est fournie, car ce Task n’attend pas que la méthode du serveur se termine. Toutes les exceptions jetées sur le client lors de l’envoi du message produisent une Task en défaut. Utilisez await et try...catch syntaxe pour gérer les erreurs d’envoi de messages.
Note
L’appel de méthodes hub à partir d’un client est pris en charge uniquement lors de l’utilisation du service Azure SignalR en mode Default. Pour plus d’informations, voir Forum aux questions.
Appeler des méthodes client depuis le hub
Définissez, à l’aide de connection.On, les méthodes que le hub doit appeler après avoir créé l’objet, mais avant de démarrer la connexion :
connection.On<string, string>("ReceiveMessage", (user, message) =>
{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{user}: {message}";
messagesList.Items.Add(newMessage);
});
});
Le code précédent dans connection.On s’exécute lorsque le code côté serveur l’appelle en utilisant la méthode SendAsync :
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Note
Bien que le côté hub de la connexion prenne en charge la messagerie fortement typée, le client doit s’enregistrer en utilisant la méthode générique HubConnection.On avec le nom de la méthode. Pour voir un exemple, consultez Host ASP.NET Core SignalR dans les services en arrière-plan.
Gestion et journalisation des erreurs
Gérer les erreurs avec une try...catch instruction. Inspectez l’objet Exception pour déterminer l’action appropriée à entreprendre après une erreur :
try
{
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}