klien ASP.NET Core SignalR .NET

Pustaka klien ASP.NET Core SignalR .NET memungkinkan Anda berkomunikasi dengan SignalR hub dari aplikasi .NET. Artikel ini menjelaskan cara menggunakan API untuk menyambungkan ke hub SignalR, dan memanggil hub .NET dan metode klien. Sampel kode dalam artikel ini adalah aplikasi Windows Presentation Foundation (WPF) yang menggunakan klien ASP.NET Core SignalR .NET.

Melihat atau mengunduh kode sampel (cara mengunduh)

SignalR Menginstal paket klien .NET

Microsoft.AspNetCore.SignalR. Paket klien diperlukan agar klien .NET tersambung ke SignalR hub. Anda dapat menginstal pustaka klien dari Visual Studio Package Manager Console atau dengan menggunakan .NET CLI.

Jalankan perintah berikut di jendela Package Manager Console:

Install-Package Microsoft.AspNetCore.SignalR.Client

Sambungkan ke hub

Untuk membuat koneksi, buat HubConnectionBuilder dan panggil Build. URL hub, protokol, jenis transportasi, tingkat log, header, dan opsi lainnya dapat dikonfigurasi saat membangun koneksi. Konfigurasikan opsi yang diperlukan dengan menyisipkan metode apa pun dari HubConnectionBuilder ke dalam Build. Mulai koneksi dengan 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);                
            }
        }
    }
}

Menangani koneksi yang hilang

Untuk terhubung kembali dengan klien, Anda dapat menyiapkan koneksi ulang otomatis atau mengonfigurasi koneksi ulang secara manual.

Menyambungkan ulang secara otomatis

HubConnection dapat dikonfigurasi untuk terhubung kembali secara otomatis dengan menggunakan WithAutomaticReconnect metode pada HubConnectionBuilder. Ini tidak akan tersambung kembali secara otomatis secara bawaan.

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

Tanpa parameter apa pun, WithAutomaticReconnect() mengonfigurasi klien untuk menunggu masing-masing 0, 2, 10, dan 30 detik sebelum mencoba setiap upaya koneksi ulang. Ini berhenti setelah empat upaya gagal.

Sebelum memulai upaya koneksi ulang, HubConnection beralih ke keadaan HubConnectionState.Reconnecting dan memicu peristiwa Reconnecting. Pendekatan ini memberikan kesempatan untuk memperingatkan pengguna bahwa koneksi hilang dan untuk menonaktifkan elemen UI. Aplikasi non-interaktif dapat mulai mengantre atau menghilangkan pesan.

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;
};

Jika klien berhasil terhubung kembali dalam empat percobaan pertamanya, HubConnection beralih kembali ke status Connected dan memicu peristiwa Reconnected. Pendekatan ini memberikan kesempatan untuk memberi tahu pengguna bahwa koneksi kini telah tersambung kembali dan untuk mengeluarkan semua pesan yang ada dalam antrean.

Karena koneksi terlihat sama sekali baru ke server, baru ConnectionId disediakan untuk penanganan Reconnected aktivitas.

Warning

Parameter connectionId milik penangan peristiwa Reconnected adalah null jika HubConnection dikonfigurasi untuk melewati negosiasi.

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() tidak mengonfigurasi HubConnection untuk mencoba lagi saat kegagalan awal terjadi, jadi kegagalan saat memulai perlu ditangani secara manual:

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

Jika klien tidak berhasil terhubung kembali dalam empat percobaan pertamanya, HubConnection beralih ke status Disconnected dan memicu peristiwa Closed. Pendekatan ini memberikan kesempatan untuk mencoba memulai ulang koneksi secara manual atau memberi tahu pengguna bahwa koneksi sekarang hilang secara permanen.

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;
};

Untuk mengonfigurasi jumlah kustom upaya koneksi ulang sebelum memutuskan sambungan atau mengubah waktu koneksi ulang, WithAutomaticReconnect menerima array angka yang mewakili penundaan dalam milidetik untuk menunggu sebelum memulai setiap upaya koneksi ulang.

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.

Contoh sebelumnya mengonfigurasi HubConnection untuk mulai mencoba menyambungkan kembali segera setelah koneksi hilang. Pendekatan ini juga berlaku untuk konfigurasi default.

  • Jika upaya koneksi ulang pertama gagal, upaya koneksi ulang kedua juga segera dimulai alih-alih menunggu 2 detik seperti yang didefinisikan dalam konfigurasi default.

  • Jika upaya koneksi ulang kedua gagal, upaya koneksi ulang ketiga dimulai dalam 10 detik, yang merupakan perilaku yang sama yang ditentukan dalam konfigurasi default.

  • Perilaku kustom kemudian beralih lagi dari perilaku default dengan berhenti setelah kegagalan upaya koneksi ulang ketiga. Dalam konfigurasi default, satu lagi upaya koneksi ulang dilakukan setelah 30 detik lagi.

Untuk kontrol lebih besar atas waktu dan jumlah upaya koneksi ulang otomatis, WithAutomaticReconnect menerima objek yang mengimplementasikan IRetryPolicy antarmuka, yang memiliki satu metode bernama NextRetryDelay. NextRetryDelay mengambil satu argumen dengan jenis RetryContext. memiliki RetryContext tiga properti: PreviousRetryCount (jenis long), ElapsedTime (jenis TimeSpan), dan RetryReason (jenis Exception).

  • Sebelum upaya koneksi ulang pertama, PreviousRetryCount dan ElapsedTime keduanya nol (0), dan RetryReason merupakan Pengecualian yang menyebabkan koneksi yang hilang.

  • Setelah setiap percobaan ulang yang gagal, PreviousRetryCount bertambah satu, ElapsedTime diperbarui untuk mencerminkan lama waktu yang telah dihabiskan untuk menyambungkan kembali hingga saat ini, dan RetryReason adalah Exception yang menyebabkan percobaan penyambungan ulang terakhir gagal.

NextRetryDelay harus mengembalikan nilai TimeSpan yang merepresentasikan waktu tunggu sebelum upaya penyambungan ulang berikutnya, atau null jika HubConnection harus berhenti melakukan penyambungan ulang.

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

Atau, Anda dapat menulis kode untuk menyambungkan kembali klien Anda secara manual, seperti yang ditunjukkan di bagian berikutnya.

Menyambungkan ulang secara manual

Warning

Dalam versi yang lebih lama dari 3.0, klien .NET untuk SignalR tidak terhubung kembali secara otomatis. Anda harus menulis kode untuk menyambungkan kembali klien Anda secara manual.

Gunakan peristiwa Closed untuk menangani koneksi yang terputus. Misalnya, Anda mungkin ingin mengotomatiskan koneksi ulang.

Peristiwa Closed ini memerlukan delegate yang mengembalikan Task, yang memungkinkan kode asinkron berjalan tanpa menggunakan async void. Untuk memenuhi tanda tangan delegasi dalam Closed penanganan aktivitas yang berjalan secara sinkron, kembalikan Task.CompletedTask:

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

Alasan utama dukungan asinkron adalah agar Anda dapat memulai ulang koneksi. Memulai koneksi adalah tindakan asinkron.

Closed Dalam handler yang memulai ulang koneksi, pertimbangkan untuk menunggu beberapa penundaan acak untuk mencegah kelebihan beban server, seperti yang ditunjukkan dalam contoh berikut:

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

Metode hub panggilan dari klien

InvokeAsync memanggil metode di hub. Teruskan nama metode hub dan argumen apa pun yang ditentukan dalam metode hub ke InvokeAsync. SignalR asinkron, jadi gunakan async dan await saat melakukan panggilan.

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

Metode InvokeAsync mengembalikan Task yang selesai ketika metode server kembali. Nilai pengembalian, jika ada, disediakan sebagai hasil dari Task. Setiap pengecualian yang dilemparkan oleh metode di server menghasilkan kesalahan Task. Gunakan await sintaks untuk menunggu metode server selesai dan try...catch sintaks untuk menangani kesalahan.

Metode SendAsync mengembalikan Task yang selesai ketika pesan dikirim ke server. Tidak ada nilai balik yang diberikan karena Task ini tidak menunggu hingga metode server selesai. Setiap pengecualian yang dilemparkan pada klien saat mengirim pesan menghasilkan kesalahan Task. Gunakan await dan try...catch sintaks untuk menangani kesalahan pengiriman pesan.

Note

Metode hub panggilan dari klien hanya didukung saat menggunakan Azure SignalR Service dalam mode Default. Untuk informasi selengkapnya, lihat Tanya Jawab Umum.

Panggil metode klien dari hub

Tentukan metode yang dipanggil hub dengan menggunakan connection.On setelah membangun, tetapi sebelum memulai koneksi:

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

Kode sebelumnya dalam connection.On berjalan ketika kode sisi server memanggilnya dengan menggunakan SendAsync metode :

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

Note

Meskipun sisi hub pada koneksi mendukung pengiriman pesan bertipe kuat, klien harus mendaftar dengan menggunakan metode generik HubConnection.On dengan nama metode. Sebagai contoh, lihat Meng-host ASP.NET Core SignalR dalam layanan latar belakang.

Penanganan kesalahan dan pengelogan

Tangani kesalahan dengan pernyataan try...catch. Exception Periksa objek untuk menentukan tindakan yang tepat untuk diambil setelah kesalahan terjadi:

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