Bagikan melalui


panduan ASP.NET Core BlazorSignalR

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 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 8 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 8 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 Gambaran Umum area ASP.NET CoreSignalRdokumentasi, terutama konfigurasi ASP.NET CoreSignalR.

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

Koneksi ulang stateful (WithStatefulReconnect) dirilis dengan .NET 8 tetapi saat ini tidak didukung untuk Layanan Azure SignalR . Untuk informasi selengkapnya, lihat Dukungan Sambungkan Ulang Stateful? (Azure/azure-signalr #1878).

Kompresi WebSocket untuk komponen Server Interaktif

Secara default, komponen Server Interaktif:

  • Aktifkan pemadatan untuk koneksi WebSocket. ConfigureWebsocketOptions mengontrol kompresi WebSocket.

  • frame-ancestorsMengadopsi direktif Kebijakan Keamanan Konten (CSP) diatur ke 'self', yang hanya mengizinkan penyematan aplikasi di <iframe> asal tempat aplikasi dilayani saat kompresi diaktifkan atau saat konfigurasi untuk konteks WebSocket disediakan. ContentSecurityFrameAncestorPolicyframe-ancestors mengontrol CSP.

frame-ancestors CSP dapat dihapus secara manual dengan mengatur nilai ConfigureWebSocketOptions ke null, karena Anda mungkin ingin mengonfigurasi CSP dengan cara terpusat. 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 mungkin membuat aplikasi rentan terhadap serangan.

Contoh penggunaan:

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

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

Saat pemadatan 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

'self'

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

Untuk implikasi keamanan, lihat Panduan mitigasi ancaman untuk ASP.NET penyajian sisi server interaktif CoreBlazor. Untuk informasi selengkapnya tentang arahan frame-ancestors , lihat 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 cookieheader autentikasi HTTP atau s.

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 konfigurasi ASP.NET CoreSignalR.

Penyajian sisi klien

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

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 SignalR batas ukuran pesan sirkuit, 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

Menggunakan sesi lekat untuk hosting webfarm sisi server

Aplikasi Blazor melakukan prarender sebagai respons terhadap permintaan klien pertama, yang membuat status UI di server. Ketika klien mencoba membuat SignalR koneksi, klien harus terhubung kembali ke server yang sama. Ketika lebih dari satu server backend sedang digunakan, aplikasi harus menerapkan sesi lengket untuk SignalR koneksi.

Catatan

Kesalahan berikut dilemparkan oleh aplikasi yang belum mengaktifkan sesi lengket di webfarm:

blazor.server.js:1 Kesalahan Tidak Tertangkap (dijanjikan) : Pemanggilan dibatalkan karena koneksi yang mendasar ditutup.

Layanan Azure SignalR sisi server

Sebaiknya gunakan Layanan Azure SignalR untuk pengembangan sisi server yang dihosting di Microsoft Azure. Layanan ini berfungsi bersama dengan Hub aplikasi Blazor untuk meningkatkan skala aplikasi sisi server ke sejumlah besar koneksi bersamaan SignalR . Selain itu, SignalR jangkauan global Layanan dan pusat data berkinerja tinggi secara signifikan membantu mengurangi latensi karena geografi.

Sesi sticky diaktifkan untuk Layanan Azure SignalR dengan mengatur opsi layanan ServerStickyMode atau nilai konfigurasi ke Required. Untuk informasi selengkapnya, lihat Menghosting dan menyebarkan aplikasi sisi Blazor 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 konfigurasi ASP.NET CoreSignalR. 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 Menghosting dan menyebarkan aplikasi sisi Blazor server ASP.NET Core.

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

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 Interop JSON 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 Memecahkan masalah formulir ASP.NET CoreBlazor.

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 Interop JSON 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 danInputLargeTextAreaBlazorSampel 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 Blazor Server aplikasi, lihat Memecahkan masalah formulir ASP.NET CoreBlazor.<textarea>

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

Ketika klien mendeteksi bahwa koneksi telah hilang, antarmuka pengguna default ditampilkan kepada pengguna saat klien mencoba menyambungkan kembali. Jika koneksi ulang gagal, pengguna disediakan opsi untuk mencoba kembali.

Untuk menyesuaikan UI, tentukan elemen tunggal dengan id dari components-reconnect-modal. Contoh berikut menempatkan elemen dalam App komponen.

App.razor:

Untuk menyesuaikan UI, tentukan elemen tunggal dengan id dari components-reconnect-modal. Contoh berikut menempatkan elemen di halaman host.

Pages/_Host.cshtml:

Untuk menyesuaikan UI, tentukan elemen tunggal dengan id dari components-reconnect-modal. Contoh berikut menempatkan elemen di halaman tata letak.

Pages/_Layout.cshtml:

Untuk menyesuaikan UI, tentukan elemen tunggal dengan id dari components-reconnect-modal. Contoh berikut menempatkan elemen di halaman host.

Pages/_Host.cshtml:

<div id="components-reconnect-modal">
    There was a problem with the connection!
</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;
}

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 yang mirip dengan yang berikut ini berdasarkan kode sebelumnya:

There was a problem with the connection! (Current reconnect attempt: 3 / 8)

Penyajian sisi server

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

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 Blazor manual sirkuit aplikasi SignalR dalam App.razor file Blazor Aplikasi Web:

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

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

Konfigurasikan awal Blazor manual sirkuit aplikasi SignalR 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 startup ASP.NET CoreBlazor.

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 Aplikasi Web) menunjukkan penetapan nilai default.

Blazor Aplikasi Web:

<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 struktur proyek ASP.NET CoreBlazor.

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 struktur proyek ASP.NET CoreBlazor.

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 Aplikasi Web:

<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 struktur proyek ASP.NET CoreBlazor.

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 struktur proyek ASP.NET CoreBlazor.

Buat file berikut wwwroot/boot.js .

Blazor Aplikasi Web:

(() => {
  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 Aplikasi Web:

<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 struktur proyek ASP.NET CoreBlazor.

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 ServerProgram 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 Aplikasi Web:

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

Memutuskan sambungan Blazor sirkuit dari klien

Secara default, Blazor 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 Skenario keamanan tambahan sisi server ASP.NET CoreBlazor.

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.

IHttpContextAccessor/HttpContext dalam Razor komponen

IHttpContextAccessor harus dihindari dengan penyajian interaktif karena tidak tersedia yang valid HttpContext .

IHttpContextAccessor dapat digunakan untuk komponen yang dirender secara statis di server. Namun, sebaiknya hindari jika memungkinkan.

HttpContext dapat digunakan sebagai parameter kaskading hanya dalam komponen akar yang dirender secara statis untuk tugas umum, seperti memeriksa dan memodifikasi header atau properti lain dalam App komponen (Components/App.razor). Nilainya selalu null untuk penyajian interaktif.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Untuk skenario di mana HttpContext diperlukan dalam komponen interaktif, sebaiknya mengalirkan data melalui status komponen persisten dari server. Untuk informasi selengkapnya, lihat Skenario keamanan tambahan ASP.NET Core Blazor sisi server.

Jangan gunakan IHttpContextAccessor/HttpContext secara langsung atau tidak langsung dalam Razor komponen aplikasi sisi Blazor server. Blazor aplikasi berjalan di luar konteks alur ASP.NET Core. HttpContext tidak dijamin tersedia dalam IHttpContextAccessor, dan HttpContext tidak dijamin untuk menyimpan konteks yang memulai Blazor aplikasi.

Pendekatan yang direkomendasikan untuk meneruskan status permintaan ke Blazor aplikasi adalah melalui parameter komponen akar selama penyajian awal aplikasi. Atau, aplikasi dapat menyalin data ke dalam layanan tercakup dalam peristiwa siklus hidup inisialisasi komponen akar untuk digunakan di seluruh aplikasi. Untuk informasi selengkapnya, lihat Skenario keamanan tambahan ASP.NET Core Blazor sisi server.

Aspek penting dari keamanan sisi Blazor server adalah bahwa pengguna yang melekat pada sirkuit tertentu mungkin diperbarui pada beberapa titik setelah Blazor sirkuit dibuat tetapi IHttpContextAccessortidak diperbarui. Untuk informasi selengkapnya tentang mengatasi situasi ini dengan layanan kustom, lihat Skenario keamanan tambahan ASP.NET Core Blazor sisi server.

Sumber daya sisi server tambahan