Bagikan melalui


panduan ASP.NET Core BlazorSignalR

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Artikel ini menjelaskan cara mengonfigurasi dan mengelola SignalR koneksi di Blazor aplikasi.

Untuk panduan umum tentang konfigurasi ASP.NET CoreSignalR, lihat topik dalam SignalRdokumentasi, terutama SignalR ASP.NET Core.

Aplikasi sisi server menggunakan ASP.NET Core SignalR untuk berkomunikasi dengan browser. SignalRKondisi hosting dan penskalakan berlaku untuk aplikasi sisi server.

Blazor berfungsi paling baik saat menggunakan WebSocket sebagai SignalR transportasi karena latensi, keandalan, dan keamanan yang lebih rendah. Polling Panjang digunakan oleh SignalR saat WebSockets tidak tersedia atau ketika aplikasi secara eksplisit dikonfigurasi untuk menggunakan Long Polling.

Layanan Azure SignalR dengan koneksi ulang stateful

Azure SignalR Service dengan SDK v1.26.1 atau yang lebih baru mendukung SignalR (WithStatefulReconnect).

Kompresi WebSocket untuk komponen Server Interaktif

Secara default, komponen Server Interaktif:

  • Aktifkan pemadatan untuk koneksi WebSocket. DisableWebSocketCompression (default: false) mengontrol kompresi WebSocket.

  • frame-ancestors Mengadopsi direktif Kebijakan Keamanan Konten (CSP) yang diatur ke 'self', yang adalah pengaturan bawaan dan hanya mengizinkan penyematan aplikasi di <iframe> dari asal tempat aplikasi disajikan ketika pemadatan diaktifkan atau ketika konfigurasi untuk konteks WebSocket disediakan.

CSP default frame-ancestors dapat diubah dengan mengatur nilai ContentSecurityFrameAncestorsPolicy ke null jika Anda ingin mengonfigurasi CSP dengan cara terpusat atau 'none' untuk kebijakan yang lebih ketat. frame-ancestors Ketika CSP dikelola dengan cara terpusat, perawatan harus diambil untuk menerapkan kebijakan setiap kali dokumen pertama dirender. Kami tidak menyarankan untuk menghapus kebijakan sepenuhnya, karena akan membuat aplikasi rentan terhadap serangan. Untuk informasi selengkapnya, lihat Menerapkan Kebijakan Keamanan Konten untuk ASP.NET Core Blazor dan Panduan CSP MDN.

Gunakan ConfigureWebSocketAcceptContext untuk mengonfigurasi WebSocketAcceptContext untuk koneksi WebSocket yang digunakan oleh komponen server. Secara default, kebijakan yang memungkinkan pemadatan dan mengatur CSP untuk nenek moyang bingkai yang ditentukan ContentSecurityFrameAncestorsPolicy diterapkan.

Contoh penggunaan:

Nonaktifkan kompresi dengan mengatur DisableWebSocketCompression ke true, yang mengurangi kerentanan aplikasi untuk menyerang tetapi dapat mengakibatkan penurunan performa:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.DisableWebSocketCompression = true)

Saat kompresi diaktifkan, konfigurasikan CSP yang lebih frame-ancestors ketat dengan nilai 'none' (tanda kutip tunggal diperlukan), yang memungkinkan kompresi WebSocket tetapi mencegah browser menyematkan aplikasi ke dalam <iframe>:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

Saat pemadatan diaktifkan, hapus frame-ancestors CSP dengan mengatur ContentSecurityFrameAncestorsPolicy ke null. Skenario ini hanya direkomendasikan untuk aplikasi yang mengatur CSP dengan cara terpusat:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = null)

Penting

Browser menerapkan arahan CSP dari beberapa header CSP menggunakan nilai arahan kebijakan paling ketat. Oleh karena itu, pengembang tidak dapat menambahkan kebijakan yang lebih frame-ancestors lemah daripada 'self' sengaja atau secara tidak sengaja.

Tanda kutip tunggal diperlukan pada nilai string yang diteruskan ke ContentSecurityFrameAncestorsPolicy:

Nilai yang tidak didukung:none, self

Opsi tambahan termasuk menentukan satu atau beberapa sumber host dan sumber skema.

Untuk implikasi keamanan, lihat Blazor sisi server interaktif Core. Untuk informasi selengkapnya, lihat Menerapkan Kebijakan Keamanan Konten untuk ASP.NET Core Blazor dan CSP: frame-ancestors (dokumentasi MDN).

Menonaktifkan kompresi respons untuk Hot Reload

Saat menggunakan Hot Reload, nonaktifkan Middleware Kompresi Respons di Development lingkungan. Apakah kode default dari templat proyek digunakan atau tidak, selalu panggil UseResponseCompression terlebih dahulu dalam alur pemrosesan permintaan.

Dalam file Program:

if (!app.Environment.IsDevelopment())
{
    app.UseResponseCompression();
}

Negosiasi lintas asal sisi SignalR klien untuk autentikasi

Bagian ini menjelaskan cara mengonfigurasi SignalRklien yang mendasar untuk mengirim kredensial, seperti cookie atau header autentikasi HTTP.

Gunakan SetBrowserRequestCredentials untuk mengatur Include permintaan lintas asal fetch .

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Http;

public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
        return base.SendAsync(request, cancellationToken);
    }
}

Di mana koneksi hub dibangun, tetapkan ke HttpMessageHandlerHttpMessageHandlerFactory opsi :

private HubConnectionBuilder? hubConnection;

...

hubConnection = new HubConnectionBuilder()
    .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options =>
    {
        options.HttpMessageHandlerFactory = innerHandler => 
            new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler };
    }).Build();

Contoh sebelumnya mengonfigurasi URL koneksi hub ke alamat URI absolut di /chathub. URI juga dapat diatur melalui string, misalnya https://signalr.example.com, atau melalui konfigurasi. Navigation adalah disuntikkan NavigationManager.

Untuk informasi selengkapnya, lihat SignalR ASP.NET Core.

Penyajian sisi klien

Jika pra-penyajian dikonfigurasi, pra-penyajian terjadi sebelum koneksi klien ke server dibuat. Untuk informasi selengkapnya, lihat Razor ASP.NET Core.

Jika pra-penyajian dikonfigurasi, pra-penyajian terjadi sebelum koneksi klien ke server dibuat. Untuk informasi lebih lanjut, baca artikel berikut:

Ukuran status dan SignalR batas ukuran pesan yang telah dirender sebelumnya

Ukuran status besar yang telah dirender mungkin melebihi Blazorbatas ukuran pesan sirkuit, SignalR yang menghasilkan hal berikut:

  • SignalR Sirkuit gagal diinisialisasi dengan kesalahan pada klien:Circuit host not initialized.
  • Antarmuka pengguna koneksi ulang pada klien muncul ketika sirkuit gagal. Pemulihan tidak dimungkinkan.

Untuk mengatasi masalah tersebut, gunakan salah satu pendekatan berikut:

  • Kurangi jumlah data yang Anda masukkan ke dalam status yang telah dirender sebelumnya.
  • Tingkatkan SignalR batas ukuran pesan. PERINGATAN: Meningkatkan batas dapat meningkatkan risiko serangan Denial of Service (DoS).

Sumber daya sisi klien tambahan

Gunakan afinitas sesi (sesi lekat) untuk hosting farm web sisi server

Ketika lebih dari satu server backend sedang digunakan, aplikasi harus menerapkan afinitas sesi, juga disebut sesi lengket. Afinitas sesi memastikan bahwa sirkuit klien terhubung kembali ke server yang sama jika koneksi terputus, yang penting karena status klien hanya disimpan dalam memori server yang pertama kali menetapkan sirkuit klien.

Kesalahan berikut terjadi pada aplikasi yang belum mengaktifkan afinitas sesi di lingkungan web.

Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed.

Untuk informasi selengkapnya tentang afinitas sesi dengan hosting Azure App Service, lihat Blazor sisi server ASP.NET Core.

Layanan Azure SignalR

Layanan Azure SignalR opsional berfungsi bersama dengan hub aplikasi SignalR untuk meningkatkan skala aplikasi sisi server ke sejumlah besar koneksi bersamaan. Selain itu, jangkauan global layanan dan pusat data berkinerja tinggi secara signifikan membantu mengurangi latensi karena geografi.

Layanan ini tidak diperlukan untuk Blazor aplikasi yang dihosting di Azure App Service atau Azure Container Apps tetapi dapat membantu di lingkungan hosting lainnya:

  • Untuk memfasilitasi peluasan skala koneksi.
  • Menangani distribusi global.

Untuk informasi selengkapnya, lihat Blazor sisi server ASP.NET Core.

Opsi penanganan sirkuit sisi server

Konfigurasikan sirkuit dengan CircuitOptions. Lihat nilai default di sumber referensi.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Membaca atau mengatur opsi dalam Program file dengan opsi yang mendelegasikan ke AddInteractiveServerComponents. Tempat {OPTION} penampung mewakili opsi, dan {VALUE} tempat penampung adalah nilainya.

Dalam file Program:

builder.Services.AddRazorComponents().AddInteractiveServerComponents(options =>
{
    options.{OPTION} = {VALUE};
});

Membaca atau mengatur opsi dalam Program file dengan opsi yang mendelegasikan ke AddServerSideBlazor. Tempat {OPTION} penampung mewakili opsi, dan {VALUE} tempat penampung adalah nilainya.

Dalam file Program:

builder.Services.AddServerSideBlazor(options =>
{
    options.{OPTION} = {VALUE};
});

Membaca atau mengatur opsi di Startup.ConfigureServices dengan opsi yang mendelegasikan ke AddServerSideBlazor. Tempat {OPTION} penampung mewakili opsi, dan {VALUE} tempat penampung adalah nilainya.

Dalam Startup.ConfigureServices dari Startup.cs:

services.AddServerSideBlazor(options =>
{
    options.{OPTION} = {VALUE};
});

Untuk mengonfigurasi HubConnectionContext, gunakan HubConnectionContextOptions dengan AddHubOptions. Lihat default untuk opsi konteks koneksi hub di sumber referensi. Untuk deskripsi opsi dalam SignalR dokumentasi, lihat SignalR ASP.NET Core. Tempat {OPTION} penampung mewakili opsi, dan {VALUE} tempat penampung adalah nilainya.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Dalam file Program:

builder.Services.AddRazorComponents().AddInteractiveServerComponents().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

Dalam file Program:

builder.Services.AddServerSideBlazor().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

Dalam Startup.ConfigureServices dari Startup.cs:

services.AddServerSideBlazor().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

Peringatan

Nilai MaximumReceiveMessageSize default adalah 32 KB. Meningkatkan nilai dapat meningkatkan risiko serangan Denial of Service (DoS).

Blazor bergantung pada MaximumParallelInvocationsPerClient atur ke 1, yang merupakan nilai default. Untuk informasi selengkapnya, lihat MaximumParallelInvocationsPerClient > 1 memutus unggahan file dalam Blazor Server mode (dotnet/aspnetcore #53951).

Untuk informasi tentang manajemen memori, lihat Mengelola memori di aplikasi sisi Blazor server ASP.NET Core yang disebarkan.

Blazor opsi hub

Konfigurasikan MapBlazorHub opsi untuk mengontrol HttpConnectionDispatcherOptionsBlazor hub. Lihat default untuk opsi dispatcher koneksi hub di sumber referensi. Tempat {OPTION} penampung mewakili opsi, dan {VALUE} tempat penampung adalah nilainya.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Lakukan panggilan app.MapBlazorHub setelah panggilan ke app.MapRazorComponents dalam file aplikasi Program :

app.MapBlazorHub(options =>
{
    options.{OPTION} = {VALUE};
});

Mengonfigurasi hub yang digunakan oleh AddInteractiveServerRenderMode dengan MapBlazorHub gagal dengan AmbiguousMatchException:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints.

Untuk mengatasi masalah untuk aplikasi yang menargetkan .NET 8, berikan hub yang dikonfigurasi Blazor khusus lebih diutamakan menggunakan WithOrder metode :

app.MapBlazorHub(options =>
{
    options.CloseOnAuthenticationExpiration = true;
}).WithOrder(-1);

Untuk informasi selengkapnya, lihat sumber daya berikut:

Berikan opsi ke app.MapBlazorHub dalam file aplikasi Program :

app.MapBlazorHub(options =>
{
    options.{OPTION} = {VALUE};
});

Berikan opsi ke app.MapBlazorHub dalam konfigurasi perutean titik akhir:

app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub(options =>
    {
        options.{OPTION} = {VALUE};
    });
    ...
});

Ukuran pesan penerimaan maksimum

Bagian ini hanya berlaku untuk proyek yang mengimplementasikan SignalR.

Ukuran pesan masuk SignalR maksimum yang diizinkan untuk metode hub dibatasi oleh HubOptions.MaximumReceiveMessageSize (default: 32 KB). SignalR pesan yang lebih besar dari MaximumReceiveMessageSize melemparkan kesalahan. Kerangka kerja tidak memberlakukan batasan SignalR ukuran pesan dari hub ke klien.

Saat SignalR pengelogan tidak diatur ke Debug atau Pelacakan, kesalahan ukuran pesan hanya muncul di konsol alat pengembang browser:

Kesalahan: Koneksi terputus dengan kesalahan 'Kesalahan: Server mengembalikan kesalahan saat ditutup: Koneksi ditutup dengan kesalahan.'.

Saat SignalR pengelogan sisi server diatur ke Debug atau Pelacakan, pengelogan sisi server menampilkan InvalidDataException kesalahan ukuran pesan.

appsettings.Development.json:

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      ...
      "Microsoft.AspNetCore.SignalR": "Debug"
    }
  }
}

Kesalahan:

System.IO.InvalidDataException: Ukuran pesan maksimum 32768B terlampaui. Ukuran pesan dapat dikonfigurasi di AddHubOptions.

Salah satu pendekatan melibatkan peningkatan batas dengan mengatur MaximumReceiveMessageSize dalam Program file. Contoh berikut mengatur ukuran pesan penerimaan maksimum menjadi 64 KB:

builder.Services.AddRazorComponents().AddInteractiveServerComponents()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

SignalR Meningkatkan batas ukuran pesan masuk dikenakan biaya untuk membutuhkan lebih banyak sumber daya server, dan meningkatkan risiko serangan Denial of Service (DoS). Selain itu, membaca sejumlah besar konten ke memori sebagai string atau array byte juga dapat mengakibatkan alokasi yang bekerja dengan buruk dengan pengumpul sampah, yang mengakibatkan hukuman performa tambahan.

Opsi yang lebih baik untuk membaca payload besar adalah mengirim konten dalam gugus yang lebih kecil dan memproses payload sebagai Stream. Ini dapat digunakan saat membaca payload JSON interop JavaScript (JS) besar atau jika JS data interop tersedia sebagai byte mentah. Misalnya yang menunjukkan pengiriman payload biner besar di aplikasi sisi server yang menggunakan teknik yang mirip InputFile dengan komponen, lihat aplikasi sampel Binary Submit danBlazorInputLargeTextArea Sampel Komponen.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Formulir yang memproses payload besar juga SignalR dapat menggunakan interop streaming JS secara langsung. Untuk informasi selengkapnya, lihat Memanggil metode .NET dari fungsi JavaScript di ASP.NET Core Blazor. Untuk contoh formulir yang mengalirkan <textarea> data ke server, lihat Blazor ASP.NET Core.

Salah satu pendekatan melibatkan peningkatan batas dengan mengatur MaximumReceiveMessageSize dalam Program file. Contoh berikut mengatur ukuran pesan penerimaan maksimum menjadi 64 KB:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

SignalR Meningkatkan batas ukuran pesan masuk dikenakan biaya untuk membutuhkan lebih banyak sumber daya server, dan meningkatkan risiko serangan Denial of Service (DoS). Selain itu, membaca sejumlah besar konten ke memori sebagai string atau array byte juga dapat mengakibatkan alokasi yang bekerja dengan buruk dengan pengumpul sampah, yang mengakibatkan hukuman performa tambahan.

Opsi yang lebih baik untuk membaca payload besar adalah mengirim konten dalam gugus yang lebih kecil dan memproses payload sebagai Stream. Ini dapat digunakan saat membaca payload JSON interop JavaScript (JS) besar atau jika JS data interop tersedia sebagai byte mentah. Misalnya yang menunjukkan pengiriman payload biner besar dalam Blazor Server yang menggunakan teknik yang mirip InputFile dengan komponen, lihat aplikasi sampel Binary Submit danBlazorInputLargeTextAreaSampel Komponen.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Formulir yang memproses payload besar juga SignalR dapat menggunakan interop streaming JS secara langsung. Untuk informasi selengkapnya, lihat Memanggil metode .NET dari fungsi JavaScript di ASP.NET Core Blazor. Untuk contoh formulir yang mengalirkan data dalam <textarea> aplikasi, lihat Blazor Server ASP.NET CoreBlazor.

Tingkatkan batas dengan mengatur MaximumReceiveMessageSize di Startup.ConfigureServices:

services.AddServerSideBlazor()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

SignalR Meningkatkan batas ukuran pesan masuk dikenakan biaya untuk membutuhkan lebih banyak sumber daya server, dan meningkatkan risiko serangan Denial of Service (DoS). Selain itu, membaca sejumlah besar konten ke memori sebagai string atau array byte juga dapat mengakibatkan alokasi yang bekerja dengan buruk dengan pengumpul sampah, yang mengakibatkan hukuman performa tambahan.

Pertimbangkan panduan berikut saat mengembangkan kode yang mentransfer sejumlah besar data:

  • Ikat data menjadi potongan yang lebih kecil, dan kirim segmen data secara berurutan hingga semua data diterima oleh server.
  • Jangan alokasikan objek besar dalam JS dan kode C#.
  • Jangan memblokir utas UI utama untuk jangka waktu yang lama saat mengirim atau menerima data.
  • Memori gratis yang dikonsumsi ketika proses selesai atau dibatalkan.
  • Berlakukan persyaratan tambahan berikut untuk tujuan keamanan:
    • Deklarasikan file maksimum atau ukuran data yang dapat diteruskan.
    • Nyatakan tingkat unggahan minimum dari klien ke server.
  • Setelah data diterima oleh server, data dapat berupa:
    • Disimpan sementara dalam buffer memori hingga semua segmen dikumpulkan.
    • Segera dikonsumsi. Misalnya, data dapat segera disimpan dalam database atau ditulis ke disk saat setiap segmen diterima.

Blazor konfigurasi rute titik akhir Hub sisi server

Program Dalam file, panggil MapBlazorHub untuk memetakan BlazorHub ke jalur default aplikasi. Blazor Skrip (blazor.*.js) secara otomatis menunjuk ke titik akhir yang dibuat oleh MapBlazorHub.

Mencerminkan status koneksi sisi server di UI

Jika klien mendeteksi koneksi yang hilang ke server, UI default ditampilkan kepada pengguna saat klien mencoba menyambungkan kembali:

Antarmuka pengguna koneksi ulang default.

Antarmuka pengguna koneksi ulang default.

Jika koneksi ulang gagal, pengguna diinstruksikan untuk mencoba kembali atau memuat ulang halaman:

UI coba lagi default.

UI coba lagi default.

Jika koneksi ulang berhasil, status pengguna sering hilang. Kode kustom dapat ditambahkan ke komponen apa pun untuk menyimpan dan memuat ulang status pengguna di seluruh kegagalan koneksi. Untuk informasi selengkapnya, lihat Blazor status ASP.NET Core.

Untuk membuat elemen UI yang melacak status koneksi ulang, tabel berikut ini menjelaskan:

  • Sekumpulan components-reconnect-* kelas CSS (kolom kelas Css) yang disetel atau tidak disetel oleh Blazor pada elemen dengan id dari components-reconnect-modal.
  • components-reconnect-state-changed Peristiwa (Kolom peristiwa) yang menunjukkan perubahan status koneksi ulang.
Kelas CSS Peristiwa Menunjukkan...
components-reconnect-show show Koneksi yang hilang. Klien mencoba menyambungkan kembali. Modal koneksi ulang ditampilkan.
components-reconnect-hide hide Koneksi aktif dibuat ulang ke server. Model koneksi ulang ditutup.
components-reconnect-retrying retrying Klien mencoba menyambungkan kembali.
components-reconnect-failed failed Koneksi ulang gagal, mungkin karena kegagalan jaringan.
components-reconnect-rejected rejected Koneksi ulang ditolak.

Ketika status koneksi ulang berubah components-reconnect-state-changed menjadi failed, gunakan Blazor.reconnect() di JavaScript untuk mencoba menyambungkan kembali.

Ketika perubahan status koneksi ulang adalah rejected, server dihubungi namun menolak koneksi, dan status koneksi pengguna di server hilang. Untuk memuat ulang aplikasi, panggil location.reload() di JavaScript. Status koneksi ini dapat mengakibatkan ketika:

  • Crash di sirkuit sisi server terjadi.
  • Klien terputus cukup lama bagi server untuk menghilangkan status pengguna. Instans komponen pengguna dibuang.
  • Server dimulai ulang, atau proses pekerja aplikasi didaur ulang.

Pengembang menambahkan pendengar peristiwa pada elemen modal koneksi ulang untuk memantau dan bereaksi terhadap perubahan status koneksi ulang, seperti yang terlihat dalam contoh berikut:

const reconnectModal = document.getElementById("components-reconnect-modal");
reconnectModal.addEventListener("components-reconnect-state-changed", 
  handleReconnectStateChanged);

function handleReconnectStateChanged(event) {
  if (event.detail.state === "show") {
    reconnectModal.showModal();
  } else if (event.detail.state === "hide") {
    reconnectModal.close();
  } else if (event.detail.state === "failed") {
    Blazor.reconnect();
  } else if (event.detail.state === "rejected") {
    location.reload();
  }
}

Elemen dengan id senilai components-reconnect-max-retries menampilkan jumlah maksimum percobaan koneksi ulang.

<span id="components-reconnect-max-retries"></span>

Elemen dengan id dari components-reconnect-current-attempt menampilkan upaya koneksi ulang saat ini:

<span id="components-reconnect-current-attempt"></span>

Elemen yang memiliki id dari components-seconds-to-next-attempt menampilkan jumlah detik ke sesi koneksi ulang berikutnya.

<span id="components-seconds-to-next-attempt"></span>

Blazor Web App Templat proyek mencakup ReconnectModal komponen (Layout/ReconnectModal.razor) dengan lembar gaya yang dikolokasi dan file JavaScript (ReconnectModal.razor.css, ReconnectModal.razor.js) yang dapat disesuaikan sesuai kebutuhan. File-file ini dapat diperiksa di sumber referensi ASP.NET Core atau dengan memeriksa aplikasi yang dibuat dari Blazor Web App templat proyek. Komponen ditambahkan ke proyek ketika proyek dibuat di Visual Studio dengan mode render Interaktif diatur ke Server atau Otomatis atau dibuat dengan .NET CLI dengan opsi --interactivity server (default) atau --interactivity auto.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Untuk mengkustomisasi UI, tentukan elemen tunggal dengan salah satu id dari components-reconnect-modal konten <body> elemen. Contoh berikut menempatkan elemen dalam App komponen.

App.razor:

Untuk mengkustomisasi UI, tentukan elemen tunggal dengan salah satu id dari components-reconnect-modal konten <body> elemen. Contoh berikut menempatkan elemen di halaman host.

Pages/_Host.cshtml:

Untuk mengkustomisasi UI, tentukan elemen tunggal dengan salah satu id dari components-reconnect-modal konten <body> elemen. Contoh berikut menempatkan elemen di halaman tata letak.

Pages/_Layout.cshtml:

Untuk mengkustomisasi UI, tentukan elemen tunggal dengan salah satu id dari components-reconnect-modal konten <body> elemen. Contoh berikut menempatkan elemen di halaman host.

Pages/_Host.cshtml:

<div id="components-reconnect-modal">
    Connection lost.<br>Attempting to reconnect...
</div>

Catatan

Jika lebih dari satu elemen dengan id dirender components-reconnect-modal oleh aplikasi, hanya elemen pertama yang dirender yang menerima perubahan kelas CSS untuk menampilkan atau menyembunyikan elemen.

Tambahkan gaya CSS berikut ke lembar gaya situs.

wwwroot/app.css:

wwwroot/css/site.css:

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show, 
#components-reconnect-modal.components-reconnect-failed, 
#components-reconnect-modal.components-reconnect-rejected {
    display: block;
    background-color: white;
    padding: 2rem;
    border-radius: 0.5rem;
    text-align: center;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    margin: 50px 50px;
    position: fixed;
    top: 0;
    z-index: 10001;
}

Tabel berikut ini menjelaskan kelas CSS yang diterapkan ke components-reconnect-modal elemen oleh Blazor kerangka kerja.

Kelas CSS Menunjukkan...
components-reconnect-show Koneksi yang hilang. Klien mencoba menyambungkan kembali. Tampilkan modal.
components-reconnect-hide Koneksi aktif dibuat ulang ke server. Sembunyikan modal.
components-reconnect-failed Koneksi ulang gagal, mungkin karena kegagalan jaringan. Untuk mencoba menyambungkan kembali, panggil window.Blazor.reconnect() di JavaScript.
components-reconnect-rejected Koneksi ulang ditolak. Server tercapai tetapi menolak koneksi, dan status pengguna di server hilang. Untuk memuat ulang aplikasi, panggil location.reload() di JavaScript. Status koneksi ini dapat mengakibatkan ketika:
  • Crash di sirkuit sisi server terjadi.
  • Klien terputus cukup lama bagi server untuk menghilangkan status pengguna. Instans komponen pengguna dibuang.
  • Server dimulai ulang, atau proses pekerja aplikasi didaur ulang.

Kustomisasi penundaan sebelum antarmuka pengguna koneksi ulang muncul dengan mengatur transition-delay properti di CSS situs untuk elemen modal. Contoh berikut mengatur penundaan transisi dari 500 md (default) menjadi 1.000 md (1 detik).

wwwroot/app.css:

wwwroot/css/site.css:

#components-reconnect-modal {
    transition: visibility 0s linear 1000ms;
}

Untuk menampilkan upaya koneksi ulang saat ini, tentukan elemen dengan id .components-reconnect-current-attempt Untuk menampilkan jumlah maksimum percobaan ulang koneksi ulang, tentukan elemen dengan id .components-reconnect-max-retries Contoh berikut menempatkan elemen-elemen ini di dalam elemen modal upaya koneksi ulang mengikuti contoh sebelumnya.

<div id="components-reconnect-modal">
    There was a problem with the connection!
    (Current reconnect attempt: 
    <span id="components-reconnect-current-attempt"></span> /
    <span id="components-reconnect-max-retries"></span>)
</div>

Saat modal koneksi ulang kustom muncul, ini merender konten berikut dengan penghitung upaya koneksi ulang:

Ada masalah dengan koneksi! (Upaya koneksi ulang saat ini: 1 / 8)

Penyajian sisi server

Secara default, komponen telah dirender di server sebelum koneksi klien ke server dibuat. Untuk informasi selengkapnya, lihat Razor ASP.NET Core.

Secara default, komponen telah dirender di server sebelum koneksi klien ke server dibuat. Untuk informasi selengkapnya, lihat Pembantu Tag Komponen di ASP.NET Core.

Memantau aktivitas sirkuit sisi server

Pantau aktivitas sirkuit masuk menggunakan CreateInboundActivityHandler metode pada CircuitHandler. Aktivitas sirkuit masuk adalah aktivitas apa pun yang dikirim dari browser ke server, seperti peristiwa UI atau panggilan interop JavaScript-to-.NET.

Misalnya, Anda dapat menggunakan handler aktivitas sirkuit untuk mendeteksi apakah klien menganggur dan mencatat ID sirkuitnya (Circuit.Id):

using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.Options;
using Timer = System.Timers.Timer;

public sealed class IdleCircuitHandler : CircuitHandler, IDisposable
{
    private Circuit? currentCircuit;
    private readonly ILogger logger;
    private readonly Timer timer;

    public IdleCircuitHandler(ILogger<IdleCircuitHandler> logger, 
        IOptions<IdleCircuitOptions> options)
    {
        timer = new Timer
        {
            Interval = options.Value.IdleTimeout.TotalMilliseconds,
            AutoReset = false
        };

        timer.Elapsed += CircuitIdle;
        this.logger = logger;
    }

    private void CircuitIdle(object? sender, System.Timers.ElapsedEventArgs e)
    {
        logger.LogInformation("{CircuitId} is idle", currentCircuit?.Id);
    }

    public override Task OnCircuitOpenedAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        currentCircuit = circuit;

        return Task.CompletedTask;
    }

    public override Func<CircuitInboundActivityContext, Task> CreateInboundActivityHandler(
        Func<CircuitInboundActivityContext, Task> next)
    {
        return context =>
        {
            timer.Stop();
            timer.Start();

            return next(context);
        };
    }

    public void Dispose() => timer.Dispose();
}

public class IdleCircuitOptions
{
    public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromMinutes(5);
}

public static class IdleCircuitHandlerServiceCollectionExtensions
{
    public static IServiceCollection AddIdleCircuitHandler(
        this IServiceCollection services, 
        Action<IdleCircuitOptions> configureOptions)
    {
        services.Configure(configureOptions);
        services.AddIdleCircuitHandler();

        return services;
    }

    public static IServiceCollection AddIdleCircuitHandler(
        this IServiceCollection services)
    {
        services.AddScoped<CircuitHandler, IdleCircuitHandler>();

        return services;
    }
}

Daftarkan layanan dalam Program file. Contoh berikut mengonfigurasi batas waktu menganggur default lima menit hingga lima detik untuk menguji implementasi sebelumnya IdleCircuitHandler :

builder.Services.AddIdleCircuitHandler(options => 
    options.IdleTimeout = TimeSpan.FromSeconds(5));

Penangan aktivitas sirkuit juga menyediakan pendekatan untuk mengakses layanan tercakup Blazor dari cakupan injeksi non-dependensiBlazor (DI) lainnya. Untuk informasi dan contoh selengkapnya, lihat:

Blazor Startup

Konfigurasikan awal BlazorSignalR manual sirkuit dalam App.razor file Blazor Web App:

Konfigurasikan awal BlazorSignalR manual sirkuit dalam Pages/_Host.cshtml file (Blazor Server):

Konfigurasikan awal BlazorSignalR manual sirkuit dalam Pages/_Layout.cshtml file (Blazor Server):

Konfigurasikan awal BlazorSignalR manual sirkuit dalam Pages/_Host.cshtml file (Blazor Server):

  • autostart="false" Tambahkan atribut ke <script> tag untuk blazor.*.js skrip.
  • Tempatkan skrip yang memanggil Blazor.start() setelah Blazor skrip dimuat dan di dalam tag penutup </body> .

Saat autostart dinonaktifkan, aspek apa pun dari aplikasi yang tidak bergantung pada sirkuit berfungsi secara normal. Misalnya, perutean sisi klien beroperasi. Namun, aspek apa pun yang tergantung pada sirkuit tidak beroperasi sampai Blazor.start() dipanggil. Perilaku aplikasi tidak dapat diprediksi tanpa sirkuit yang mapan. Misalnya, metode komponen gagal dijalankan saat sirkuit terputus.

Untuk informasi selengkapnya, termasuk cara menginisialisasi Blazor saat dokumen siap dan cara menautkan ke JS Promise, lihat Blazor ASP.NET Core.

Mengonfigurasi SignalR batas waktu dan Keep-Alive pada klien

Konfigurasikan nilai berikut untuk klien:

  • withServerTimeout: Mengonfigurasi batas waktu server dalam milidetik. Jika batas waktu ini berlalu tanpa menerima pesan apa pun dari server, koneksi dihentikan dengan kesalahan. Nilai batas waktu default adalah 30 detik. Batas waktu server harus setidaknya dua kali lipat nilai yang ditetapkan ke interval Keep-Alive (withKeepAliveInterval).
  • withKeepAliveInterval: Mengonfigurasi interval Keep-Alive dalam milidetik (interval default untuk melakukan ping server). Pengaturan ini memungkinkan server mendeteksi pemutusan sambungan keras, seperti ketika klien mencabut sambungan komputernya dari jaringan. Ping paling sering terjadi sesering ping server. Jika server melakukan ping setiap lima detik, menetapkan nilai yang lebih rendah dari 5000 (5 detik) ping setiap lima detik. Nilai defaultnya adalah 15 detik. Interval Keep-Alive harus kurang dari atau sama dengan setengah nilai yang ditetapkan ke batas waktu server (withServerTimeout).

Contoh berikut untuk App.razor file (Blazor Web App) menunjukkan penetapan nilai default.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.withServerTimeout(30000).withKeepAliveInterval(15000);
      }
    }
  });
</script>

Contoh berikut untuk Pages/_Host.cshtml file (Blazor Server, semua versi kecuali ASP.NET Core di .NET 6) atau Pages/_Layout.cshtml file (Blazor Server, ASP.NET Core di .NET 6).

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.withServerTimeout(30000).withKeepAliveInterval(15000);
    }
  });
</script>

Dalam contoh sebelumnya, {BLAZOR SCRIPT} tempat penampung adalah Blazor jalur skrip dan nama file. Untuk lokasi skrip dan jalur yang akan digunakan, lihat Blazor proyek ASP.NET Core.

Saat membuat koneksi hub dalam komponen, atur ServerTimeout (default: 30 detik) dan KeepAliveInterval (default: 15 detik) pada HubConnectionBuilder. Atur HandshakeTimeout (default: 15 detik) pada bawaan HubConnection. Contoh berikut menunjukkan penetapan nilai default:

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .WithServerTimeout(TimeSpan.FromSeconds(30))
        .WithKeepAliveInterval(TimeSpan.FromSeconds(15))
        .Build();

    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Konfigurasikan nilai berikut untuk klien:

  • serverTimeoutInMilliseconds: Batas waktu server dalam milidetik. Jika batas waktu ini berlalu tanpa menerima pesan apa pun dari server, koneksi dihentikan dengan kesalahan. Nilai batas waktu default adalah 30 detik. Batas waktu server harus setidaknya dua kali lipat nilai yang ditetapkan ke interval Keep-Alive (keepAliveIntervalInMilliseconds).
  • keepAliveIntervalInMilliseconds: Interval default untuk melakukan ping pada server. Pengaturan ini memungkinkan server mendeteksi pemutusan sambungan keras, seperti ketika klien mencabut sambungan komputernya dari jaringan. Ping paling sering terjadi sesering ping server. Jika server melakukan ping setiap lima detik, menetapkan nilai yang lebih rendah dari 5000 (5 detik) ping setiap lima detik. Nilai defaultnya adalah 15 detik. Interval Keep-Alive harus kurang dari atau sama dengan setengah nilai yang ditetapkan ke batas waktu server (serverTimeoutInMilliseconds).

Contoh berikut untuk Pages/_Host.cshtml file (Blazor Server, semua versi kecuali ASP.NET Core di .NET 6) atau Pages/_Layout.cshtml file (Blazor Server, ASP.NET Core di .NET 6):

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      let c = builder.build();
      c.serverTimeoutInMilliseconds = 30000;
      c.keepAliveIntervalInMilliseconds = 15000;
      builder.build = () => {
        return c;
      };
    }
  });
</script>

Dalam contoh sebelumnya, {BLAZOR SCRIPT} tempat penampung adalah Blazor jalur skrip dan nama file. Untuk lokasi skrip dan jalur yang akan digunakan, lihat Blazor proyek ASP.NET Core.

Saat membuat koneksi hub dalam komponen, atur ServerTimeout (default: 30 detik), HandshakeTimeout (default: 15 detik), dan KeepAliveInterval (default: 15 detik) di bawaan HubConnection. Contoh berikut menunjukkan penetapan nilai default:

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .Build();

    hubConnection.ServerTimeout = TimeSpan.FromSeconds(30);
    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15);
    hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Saat mengubah nilai batas waktu server (ServerTimeout) atau interval Keep-Alive (KeepAliveInterval):

  • Batas waktu server harus setidaknya dua kali lipat nilai yang ditetapkan ke interval Keep-Alive.
  • Interval Keep-Alive harus kurang dari atau sama dengan setengah nilai yang ditetapkan ke batas waktu server.

Untuk informasi selengkapnya, lihat bagian Penyebaran global dan kegagalan koneksi dari artikel berikut ini:

Mengubah handler koneksi ulang sisi server

Peristiwa koneksi sirkuit handler rekoneksi dapat dimodifikasi untuk perilaku kustom, seperti:

  • Untuk memberi tahu pengguna jika koneksi terputus.
  • Untuk melakukan pengelogan (dari klien) saat sirkuit tersambung.

Untuk mengubah peristiwa koneksi, daftarkan panggilan balik untuk perubahan koneksi berikut:

  • Koneksi yang dihilangkan menggunakan onConnectionDown.
  • Koneksi yang dibuat/dibuat ulang menggunakan onConnectionUp.

Keduanya onConnectionDown dan onConnectionUp harus ditentukan.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      reconnectionHandler: {
        onConnectionDown: (options, error) => console.error(error),
        onConnectionUp: () => console.log("Up, up, and away!")
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    reconnectionHandler: {
      onConnectionDown: (options, error) => console.error(error),
      onConnectionUp: () => console.log("Up, up, and away!")
    }
  });
</script>

Dalam contoh sebelumnya, {BLAZOR SCRIPT} tempat penampung adalah Blazor jalur skrip dan nama file. Untuk lokasi skrip dan jalur yang akan digunakan, lihat Blazor proyek ASP.NET Core.

Merefresh halaman secara otomatis saat koneksi ulang sisi server gagal

Perilaku koneksi ulang default mengharuskan pengguna untuk mengambil tindakan manual untuk menyegarkan halaman setelah koneksi ulang gagal. Namun, handler rekoneksi kustom dapat digunakan untuk me-refresh halaman secara otomatis:

App.razor:

Pages/_Host.cshtml:

<div id="reconnect-modal" style="display: none;"></div>
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script src="boot.js"></script>

Dalam contoh sebelumnya, {BLAZOR SCRIPT} tempat penampung adalah Blazor jalur skrip dan nama file. Untuk lokasi skrip dan jalur yang akan digunakan, lihat Blazor proyek ASP.NET Core.

Buat file berikut wwwroot/boot.js .

Blazor Web App:

(() => {
  const maximumRetryCount = 3;
  const retryIntervalMilliseconds = 5000;
  const reconnectModal = document.getElementById('reconnect-modal');

  const startReconnectionProcess = () => {
    reconnectModal.style.display = 'block';

    let isCanceled = false;

    (async () => {
      for (let i = 0; i < maximumRetryCount; i++) {
        reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`;

        await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds));

        if (isCanceled) {
          return;
        }

        try {
          const result = await Blazor.reconnect();
          if (!result) {
            // The server was reached, but the connection was rejected; reload the page.
            location.reload();
            return;
          }

          // Successfully reconnected to the server.
          return;
        } catch {
          // Didn't reach the server; try again.
        }
      }

      // Retried too many times; reload the page.
      location.reload();
    })();

    return {
      cancel: () => {
        isCanceled = true;
        reconnectModal.style.display = 'none';
      },
    };
  };

  let currentReconnectionProcess = null;

  Blazor.start({
    circuit: {
      reconnectionHandler: {
        onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
        onConnectionUp: () => {
          currentReconnectionProcess?.cancel();
          currentReconnectionProcess = null;
        }
      }
    }
  });
})();

Blazor Server:

(() => {
  const maximumRetryCount = 3;
  const retryIntervalMilliseconds = 5000;
  const reconnectModal = document.getElementById('reconnect-modal');

  const startReconnectionProcess = () => {
    reconnectModal.style.display = 'block';

    let isCanceled = false;

    (async () => {
      for (let i = 0; i < maximumRetryCount; i++) {
        reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`;

        await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds));

        if (isCanceled) {
          return;
        }

        try {
          const result = await Blazor.reconnect();
          if (!result) {
            // The server was reached, but the connection was rejected; reload the page.
            location.reload();
            return;
          }

          // Successfully reconnected to the server.
          return;
        } catch {
          // Didn't reach the server; try again.
        }
      }

      // Retried too many times; reload the page.
      location.reload();
    })();

    return {
      cancel: () => {
        isCanceled = true;
        reconnectModal.style.display = 'none';
      },
    };
  };

  let currentReconnectionProcess = null;

  Blazor.start({
    reconnectionHandler: {
      onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
      onConnectionUp: () => {
        currentReconnectionProcess?.cancel();
        currentReconnectionProcess = null;
      }
    }
  });
})();

Untuk informasi lebih lanjut tentang startup Blazor, lihat startup BlazorASP.NET Core.

Menyesuaikan jumlah dan interval coba lagi koneksi ulang sisi server

Untuk menyesuaikan jumlah dan interval coba lagi koneksi ulang, atur jumlah percobaan ulang (maxRetries) dan periode dalam milidetik yang diizinkan untuk setiap upaya coba lagi (retryIntervalMilliseconds).

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      reconnectionOptions: {
        maxRetries: 3,
        retryIntervalMilliseconds: 2000
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    reconnectionOptions: {
      maxRetries: 3,
      retryIntervalMilliseconds: 2000
    }
  });
</script>

Dalam contoh sebelumnya, {BLAZOR SCRIPT} tempat penampung adalah Blazor jalur skrip dan nama file. Untuk lokasi skrip dan jalur yang akan digunakan, lihat Blazor proyek ASP.NET Core.

Saat pengguna menavigasi kembali ke aplikasi dengan sirkuit yang terputus, koneksi ulang dicoba segera daripada menunggu durasi interval koneksi ulang berikutnya. Perilaku ini berusaha melanjutkan koneksi secepat mungkin untuk pengguna.

Waktu koneksi ulang default menggunakan strategi backoff komputasi. Beberapa upaya koneksi ulang pertama terjadi secara berturut-turut sebelum penundaan komputasi diperkenalkan di antara upaya. Logika default untuk menghitung interval coba lagi adalah detail implementasi yang dapat berubah tanpa pemberitahuan, tetapi Anda dapat menemukan logika default yang Blazor digunakan kerangka kerja dalam computeDefaultRetryInterval fungsi (sumber referensi).

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Sesuaikan perilaku interval coba lagi dengan menentukan fungsi untuk menghitung interval coba lagi. Dalam contoh backoff eksponensial berikut, jumlah upaya koneksi ulang sebelumnya dikalikan dengan 1.000 ms untuk menghitung interval coba lagi. Ketika jumlah upaya sebelumnya untuk menyambungkan kembali (previousAttempts) lebih besar dari batas coba lagi maksimum (maxRetries), null ditetapkan ke interval coba lagi (retryIntervalMilliseconds) untuk menghentikan upaya koneksi ulang lebih lanjut:

Blazor.start({
  circuit: {
    reconnectionOptions: {
      retryIntervalMilliseconds: (previousAttempts, maxRetries) => 
        previousAttempts >= maxRetries ? null : previousAttempts * 1000
    },
  },
});

Alternatifnya adalah menentukan urutan interval coba lagi yang tepat. Setelah interval coba lagi yang terakhir ditentukan, coba lagi berhenti karena retryIntervalMilliseconds fungsi mengembalikan undefined:

Blazor.start({
  circuit: {
    reconnectionOptions: {
      retryIntervalMilliseconds: 
        Array.prototype.at.bind([0, 1000, 2000, 5000, 10000, 15000, 30000]),
    },
  },
});

Untuk informasi lebih lanjut tentang startup Blazor, lihat startup BlazorASP.NET Core.

Kontrol saat antarmuka pengguna koneksi ulang muncul

Mengontrol kapan antarmuka pengguna koneksi ulang muncul dapat berguna dalam situasi berikut:

  • Aplikasi yang disebarkan sering menampilkan antarmuka pengguna koneksi ulang karena batas waktu ping yang disebabkan oleh jaringan internal atau latensi Internet, dan Anda ingin meningkatkan penundaan.
  • Aplikasi harus melaporkan kepada pengguna bahwa koneksi telah turun lebih cepat, dan Anda ingin mempersingkat penundaan.

Waktu munculnya UI koneksi ulang dipengaruhi oleh penyesuaian interval Keep-Alive dan batas waktu pada klien. UI koneksi ulang muncul ketika batas waktu server tercapai pada klien (withServerTimeout, bagian Konfigurasi klien). Namun, mengubah nilai withServerTimeout memerlukan perubahan pada pengaturan Keep-Alive, timeout, dan handshake lainnya yang dijelaskan dalam panduan berikut.

Sebagai rekomendasi umum untuk panduan yang mengikuti:

  • Interval Keep-Alive harus cocok antara konfigurasi klien dan server.
  • Batas waktu harus setidaknya dua kali lipat nilai yang ditetapkan ke interval Keep-Alive.

Konfigurasi server

Atur berikut ini:

  • ClientTimeoutInterval (default: 30 detik): Klien jendela waktu harus mengirim pesan sebelum server menutup koneksi.
  • HandshakeTimeout (default: 15 detik): Interval yang digunakan oleh server untuk waktu habis permintaan jabat tangan masuk oleh klien.
  • KeepAliveInterval (default: 15 detik): Interval yang digunakan oleh server untuk mengirim ping tetap hidup ke klien yang terhubung. Perhatikan bahwa ada juga pengaturan interval Keep-Alive pada klien, yang harus cocok dengan nilai server.

ClientTimeoutInterval dan HandshakeTimeout dapat ditingkatkan, dan KeepAliveInterval dapat tetap sama. Pertimbangan pentingnya adalah bahwa jika Anda mengubah nilai, pastikan bahwa batas waktu setidaknya dua kali lipat nilai interval Keep-Alive dan interval Keep-Alive cocok antara server dan klien. Untuk informasi selengkapnya, lihat bagian Mengonfigurasi SignalR batas waktu dan Keep-Alive di klien .

Dalam contoh berikut:

  • ditingkatkan ClientTimeoutInterval menjadi 60 detik (nilai default: 30 detik).
  • ditingkatkan HandshakeTimeout menjadi 30 detik (nilai default: 15 detik).
  • KeepAliveInterval tidak diatur dalam kode pengembang dan menggunakan nilai defaultnya 15 detik. Mengurangi nilai interval Keep-Alive meningkatkan frekuensi ping komunikasi, yang meningkatkan beban pada aplikasi, server, dan jaringan. Perawatan harus dilakukan untuk menghindari pengenalan performa yang buruk saat menurunkan interval Keep-Alive.

Blazor Web App (.NET 8 atau yang lebih baru) dalam file proyek Program server:

builder.Services.AddRazorComponents().AddInteractiveServerComponents()
    .AddHubOptions(options =>
{
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
    options.HandshakeTimeout = TimeSpan.FromSeconds(30);
});

Blazor Server Program dalam file:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
        options.HandshakeTimeout = TimeSpan.FromSeconds(30);
    });

Untuk informasi selengkapnya, lihat bagian Opsi penanganan sirkuit sisi server.

Konfigurasi klien

Atur berikut ini:

  • withServerTimeout (default: 30 detik): Mengonfigurasi batas waktu server, yang ditentukan dalam milidetik, untuk koneksi hub sirkuit.
  • withKeepAliveInterval (default: 15 detik): Interval, yang ditentukan dalam milidetik, di mana koneksi mengirim pesan Keep-Alive.

Batas waktu server dapat ditingkatkan, dan interval Keep-Alive dapat tetap sama. Pertimbangan pentingnya adalah bahwa jika Anda mengubah nilai, pastikan bahwa batas waktu server setidaknya dua kali lipat nilai interval Keep-Alive dan bahwa nilai interval Keep-Alive cocok antara server dan klien. Untuk informasi selengkapnya, lihat bagian Mengonfigurasi SignalR batas waktu dan Keep-Alive di klien .

Dalam contoh konfigurasi startup berikut (lokasi Blazor skrip), nilai kustom 60 detik digunakan untuk batas waktu server. Interval Keep-Alive (withKeepAliveInterval) tidak diatur dan menggunakan nilai defaultnya 15 detik.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.withServerTimeout(60000);
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.withServerTimeout(60000);
    }
  });
</script>

Saat membuat koneksi hub dalam komponen, atur batas waktu server (WithServerTimeout, default: 30 detik) pada HubConnectionBuilder. Atur HandshakeTimeout (default: 15 detik) pada bawaan HubConnection. Konfirmasikan bahwa batas waktu setidaknya dua kali lipat interval Keep-Alive (WithKeepAliveInterval/KeepAliveInterval) dan bahwa nilai Keep-Alive cocok antara server dan klien.

Contoh berikut didasarkan pada Index komponen dalam SignalR tutorial.Blazor Batas waktu server ditingkatkan menjadi 60 detik, dan batas waktu jabat tangan ditingkatkan menjadi 30 detik. Interval Keep-Alive tidak diatur dan menggunakan nilai defaultnya 15 detik.

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .WithServerTimeout(TimeSpan.FromSeconds(60))
        .Build();

    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Atur berikut ini:

  • serverTimeoutInMilliseconds (default: 30 detik): Mengonfigurasi batas waktu server, yang ditentukan dalam milidetik, untuk koneksi hub sirkuit.
  • keepAliveIntervalInMilliseconds (default: 15 detik): Interval, yang ditentukan dalam milidetik, di mana koneksi mengirim pesan Keep-Alive.

Batas waktu server dapat ditingkatkan, dan interval Keep-Alive dapat tetap sama. Pertimbangan pentingnya adalah bahwa jika Anda mengubah nilai, pastikan bahwa batas waktu server setidaknya dua kali lipat nilai interval Keep-Alive dan bahwa nilai interval Keep-Alive cocok antara server dan klien. Untuk informasi selengkapnya, lihat bagian Mengonfigurasi SignalR batas waktu dan Keep-Alive di klien .

Dalam contoh konfigurasi startup berikut (lokasi Blazor skrip), nilai kustom 60 detik digunakan untuk batas waktu server. Interval Keep-Alive (keepAliveIntervalInMilliseconds) tidak diatur dan menggunakan nilai defaultnya 15 detik.

Di Pages/_Host.cshtml:

<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      let c = builder.build();
      c.serverTimeoutInMilliseconds = 60000;
      builder.build = () => {
        return c;
      };
    }
  });
</script>

Saat membuat koneksi hub dalam komponen, atur ServerTimeout (default: 30 detik) dan HandshakeTimeout (default: 15 detik) pada bawaan HubConnection. Konfirmasikan bahwa batas waktu setidaknya dua kali lipat interval Keep-Alive. Konfirmasikan bahwa interval Keep-Alive cocok antara server dan klien.

Contoh berikut didasarkan pada Index komponen dalam SignalR tutorial.Blazor ditingkatkan ServerTimeout menjadi 60 detik, dan HandshakeTimeout ditingkatkan menjadi 30 detik. Interval Keep-Alive (KeepAliveInterval) tidak diatur dan menggunakan nilai defaultnya 15 detik.

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .Build();

    hubConnection.ServerTimeout = TimeSpan.FromSeconds(60);
    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Putuskan sambungan BlazorSignalR sirkuit dari klien

Blazor SignalR Sirkuit terputus saat unload peristiwa halaman dipicu. Untuk memutuskan sambungan sirkuit untuk skenario lain pada klien, panggil Blazor.disconnect di penanganan aktivitas yang sesuai. Dalam contoh berikut, sirkuit terputus saat halaman disembunyikan (pagehide peristiwa):

window.addEventListener('pagehide', () => {
  Blazor.disconnect();
});

Untuk informasi lebih lanjut tentang startup Blazor, lihat startup BlazorASP.NET Core.

Handler sirkuit sisi server

Anda dapat menentukan handler sirkuit, yang memungkinkan menjalankan kode pada perubahan pada status sirkuit pengguna. Handler sirkuit diimplementasikan dengan turunan dari CircuitHandler dan mendaftarkan kelas dalam kontainer layanan aplikasi. Contoh handler sirkuit berikut melacak koneksi terbuka SignalR .

TrackingCircuitHandler.cs:

using Microsoft.AspNetCore.Components.Server.Circuits;

public class TrackingCircuitHandler : CircuitHandler
{
    private HashSet<Circuit> circuits = new();

    public override Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Add(circuit);

        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Remove(circuit);

        return Task.CompletedTask;
    }

    public int ConnectedCircuits => circuits.Count;
}

Penangan sirkuit terdaftar menggunakan DI. Instans terlingkup dibuat per instans sirkuit. TrackingCircuitHandler Menggunakan dalam contoh sebelumnya, layanan singleton dibuat karena status semua sirkuit harus dilacak.

Dalam file Program:

builder.Services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

Dalam Startup.ConfigureServices dari Startup.cs:

services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

Jika metode handler sirkuit kustom melemparkan pengecualian yang tidak tertangani, pengecualiannya fatal bagi sirkuit. Untuk mentolerir pengecualian dalam kode handler atau metode yang disebut, bungkus kode dalam satu atau beberapa try-catch pernyataan dengan penanganan kesalahan dan pengelogan.

Ketika sirkuit berakhir karena pengguna telah terputus dan kerangka kerja membersihkan status sirkuit, kerangka kerja membuang cakupan DI sirkuit. Membuang cakupan membuang layanan DI cakupan sirkuit apa pun yang menerapkan System.IDisposable. Jika ada layanan DI yang melemparkan pengecualian yang tidak tertangani selama pembuangan, kerangka kerja mencatat pengecualian. Untuk informasi selengkapnya, lihat Injeksi dependensi ASP.NET Core Blazor.

Penanganan sirkuit sisi server untuk menangkap pengguna untuk layanan kustom

CircuitHandler Gunakan untuk mengambil pengguna dari dan mengatur pengguna tersebut AuthenticationStateProvider dalam layanan. Untuk informasi selengkapnya dan contoh kode, lihat ASP.NET sisi server Core dan Blazor Web App skenario keamanan tambahan.

Penutupan sirkuit ketika tidak ada komponen Server Interaktif yang tersisa

Komponen Server Interaktif menangani peristiwa UI web menggunakan koneksi real-time dengan browser yang disebut sirkuit. Sirkuit dan status terkait dibuat ketika komponen Server Interaktif akar dirender. Sirkuit ditutup ketika tidak ada komponen Server Interaktif yang tersisa di halaman, yang membebaskan sumber daya server.

Memulai sirkuit SignalR di URL yang berbeda

Cegah aplikasi agar tidak mulai secara otomatis dengan menambahkan autostart="false" ke tag Blazor<script> (mulai skrip Blazor di lokasi). Buat URL sirkuit secara manual menggunakan Blazor.start. Contoh berikut menggunakan jalur /signalr.

Blazor Web Apps:

- <script src="_framework/blazor.web.js"></script>
+ <script src="_framework/blazor.web.js" autostart="false"></script>
+ <script>
+   Blazor.start({
+     circuit: {
+       configureSignalR: builder => builder.withUrl("/signalr")
+     },
+   });
+ </script>

Blazor Server:

- <script src="_framework/blazor.server.js"></script>
+ <script src="_framework/blazor.server.js" autostart="false"></script>
+ <script>
+   Blazor.start({
+     configureSignalR: builder => builder.withUrl("/signalr")
+   });
+ </script>

Tambahkan panggilan MapBlazorHub berikut dengan jalur hub ke alur pemrosesan middleware di file Program aplikasi server.

Blazor Web Apps:

app.MapBlazorHub("/signalr");

Blazor Server:

Biarkan panggilan yang ada untuk MapBlazorHub dalam file dan tambahkan panggilan baru ke MapBlazorHub dengan jalur :

app.MapBlazorHub();
+ app.MapBlazorHub("/signalr");

Peniruan identitas untuk Autentikasi Windows

Koneksi hub terautentikasi (HubConnection) dibuat dengan UseDefaultCredentials untuk menunjukkan penggunaan kredensial default untuk permintaan HTTP. Untuk informasi selengkapnya, lihat Autentikasi dan otorisasi di ASP.NET Core SignalR.

Saat aplikasi berjalan di IIS Express sebagai pengguna aktif di bawah Autentikasi Windows, yang kemungkinan merupakan akun pribadi atau kerja pengguna, kredensial default adalah kredensial dari pengguna yang masuk.

Saat aplikasi diterbitkan ke IIS, aplikasi berjalan di bawah Kumpulan Aplikasi Identity. HubConnection terhubung sebagai akun "pengguna" IIS yang menghosting aplikasi, bukan pengguna yang mengakses halaman.

Terapkan peniruan dengan HubConnection untuk menggunakan identitas pengguna yang menjelajah.

Dalam contoh berikut:

protected override async Task OnInitializedAsync()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();

    if (authState?.User.Identity is not null)
    {
        var user = authState.User.Identity as WindowsIdentity;

        if (user is not null)
        {
            await WindowsIdentity.RunImpersonatedAsync(user.AccessToken, 
                async () =>
                {
                    hubConnection = new HubConnectionBuilder()
                        .WithUrl(NavManager.ToAbsoluteUri("/hub"), config =>
                        {
                            config.UseDefaultCredentials = true;
                        })
                        .WithAutomaticReconnect()
                        .Build();

                        hubConnection.On<string>("name", userName =>
                        {
                            name = userName;
                            InvokeAsync(StateHasChanged);
                        });

                        await hubConnection.StartAsync();
                });
        }
    }
}

Dalam kode sebelumnya, NavManager adalah NavigationManager, dan AuthenticationStateProvider adalah instans layanan AuthenticationStateProvider ( dokumentasiAuthenticationStateProvider).

Sumber daya sisi server tambahan