manajemen status ASP.NET Core Blazor
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 pendekatan umum untuk mempertahankan data pengguna (status) saat mereka menggunakan aplikasi dan di seluruh sesi browser.
Catatan
Contoh kode dalam artikel ini mengadopsi jenis referensi nullable (NRTs) dan .NET compiler null-state static analysis, yang didukung di ASP.NET Core di .NET 6 atau yang lebih baru. Saat menargetkan ASP.NET Core 5.0 atau yang lebih lama, hapus penunjukan jenis null (?
) dari jenis dalam contoh artikel.
Pertahankan status pengguna
Sisi server Blazor adalah kerangka kerja aplikasi stateful. Sebagian besar waktu, aplikasi mempertahankan koneksi ke server. Status pengguna disimpan dalam memori server di sirkuit.
Contoh status pengguna yang disimpan di sirkuit meliputi:
- Hierarki instans komponen dan output render terbarunya di UI yang dirender.
- Nilai bidang dan properti dalam instans komponen.
- Data yang disimpan dalam instans layanan injeksi dependensi (DI) yang tercakup ke sirkuit.
Status pengguna mungkin juga ditemukan dalam variabel JavaScript di set memori browser melalui panggilan interop JavaScript.
Jika pengguna mengalami kehilangan koneksi jaringan sementara, Blazor mencoba menyambungkan kembali pengguna ke sirkuit asli mereka dengan status aslinya. Namun, menyambungkan kembali pengguna ke sirkuit asli mereka dalam memori server tidak selalu memungkinkan:
- Server tidak dapat mempertahankan sirkuit yang terputus selamanya. Server harus merilis sirkuit yang terputus setelah waktu habis atau ketika server berada di bawah tekanan memori.
- Di lingkungan penyebaran multi-server, penyebaran yang seimbang beban, server individual mungkin gagal atau dihapus secara otomatis ketika tidak lagi diperlukan untuk menangani volume permintaan secara keseluruhan. Permintaan pemrosesan server asli untuk pengguna mungkin menjadi tidak tersedia ketika pengguna mencoba menyambungkan kembali.
- Pengguna mungkin menutup dan membuka kembali browser mereka atau memuat ulang halaman, yang menghapus status apa pun yang disimpan di memori browser. Misalnya, nilai variabel JavaScript yang diatur melalui panggilan interop JavaScript hilang.
Ketika pengguna tidak dapat terhubung kembali ke sirkuit asli mereka, pengguna menerima sirkuit baru dengan status kosong. Ini setara dengan menutup dan membuka kembali aplikasi desktop.
Mempertahankan status di seluruh sirkuit
Umumnya, pertahankan status di seluruh sirkuit tempat pengguna secara aktif membuat data, bukan hanya membaca data yang sudah ada.
Untuk mempertahankan status di seluruh sirkuit, aplikasi harus menyimpan data ke beberapa lokasi penyimpanan lain daripada memori server. Persistensi status tidak otomatis. Anda harus mengambil langkah-langkah saat mengembangkan aplikasi untuk menerapkan persistensi data stateful.
Persistensi data biasanya hanya diperlukan untuk status bernilai tinggi yang dikeluarkan pengguna untuk dibuat. Dalam contoh berikut, status bertahan menghemat waktu atau membantu dalam aktivitas komersial:
- Formulir web multi-langkah: Ini memakan waktu bagi pengguna untuk memasukkan kembali data untuk beberapa langkah lengkap formulir web multi-langkah jika statusnya hilang. Pengguna kehilangan status dalam skenario ini jika mereka menavigasi menjauh dari formulir dan kembali nanti.
- Kelir belanja: Setiap komponen aplikasi yang penting secara komersial yang mewakili potensi pendapatan dapat dipertahankan. Pengguna yang kehilangan status mereka, dan dengan demikian kelir belanja mereka, dapat membeli lebih sedikit produk atau layanan ketika mereka kembali ke situs nanti.
Aplikasi hanya dapat mempertahankan status aplikasi. UI tidak dapat dipertahankan, seperti instans komponen dan pohon rendernya. Komponen dan pohon render umumnya tidak dapat diserialisasikan. Untuk mempertahankan status UI, seperti simpul kontrol tampilan pohon yang diperluas, aplikasi harus menggunakan kode kustom untuk memodelkan perilaku status UI sebagai status aplikasi yang dapat diserialisasikan.
Tempat untuk mempertahankan status
Lokasi umum ada untuk status bertahan:
Penyimpanan sisi server
Untuk persistensi data permanen yang mencakup beberapa pengguna dan perangkat, aplikasi dapat menggunakan penyimpanan sisi server. Opsi meliputi:
- Penyimpanan Blob
- Penyimpanan kunci-nilai
- Database hubungan
- Penyimpanan Tabel
Setelah data disimpan, status pengguna dipertahankan dan tersedia di sirkuit baru apa pun.
Untuk informasi selengkapnya tentang opsi penyimpanan data Azure, lihat yang berikut ini:
URL
Untuk data sementara yang mewakili status navigasi, modelkan data sebagai bagian dari URL. Contoh status pengguna yang dimodelkan dalam URL meliputi:
- ID entitas yang dilihat.
- Nomor halaman saat ini dalam kisi halaman.
Konten bilah alamat browser dipertahankan:
- Jika pengguna memuat ulang halaman secara manual.
- Jika server web menjadi tidak tersedia, dan pengguna dipaksa memuat ulang halaman untuk menyambungkan ke server lain.
Untuk informasi tentang menentukan pola URL dengan direktif@page
, lihat perutean dan navigasi core Blazor ASP.NET.
Penyimpanan browser
Untuk data sementara yang dibuat pengguna secara aktif, lokasi penyimpanan yang umum digunakan adalah browser localStorage
dan sessionStorage
koleksi:
localStorage
dilingkup ke jendela browser. Jika pengguna memuat ulang halaman atau menutup dan membuka kembali browser, status tetap ada. Jika pengguna membuka beberapa tab browser, status dibagikan di seluruh tab. Data bertahan hingga dihapus secara eksplisitlocalStorage
.sessionStorage
dilingkup ke tab browser. Jika pengguna memuat ulang tab, status tetap ada. Jika pengguna menutup tab atau browser, status akan hilang. Jika pengguna membuka beberapa tab browser, setiap tab memiliki versi data independennya sendiri.
Umumnya, sessionStorage
lebih aman digunakan. sessionStorage
menghindari risiko pengguna membuka beberapa tab dan mengalami hal berikut:
- Bug dalam penyimpanan status di seluruh tab.
- Perilaku membingungkan saat tab menimpa status tab lain.
localStorage
adalah pilihan yang lebih baik jika aplikasi harus mempertahankan status di seluruh penutupan dan membuka kembali browser.
Peringatan untuk menggunakan penyimpanan browser:
- Mirip dengan penggunaan database sisi server, memuat dan menyimpan data bersifat asinkron.
- Halaman yang diminta tidak ada di browser selama pra-penyajian, sehingga penyimpanan lokal tidak tersedia selama pra-penyajian.
- Penyimpanan beberapa kilobyte data wajar untuk bertahan untuk aplikasi sisi Blazor server. Di luar beberapa kilobyte, Anda harus mempertimbangkan implikasi performa karena data dimuat dan disimpan di seluruh jaringan.
- Pengguna dapat melihat atau mengubah data. ASP.NET Core Data Protection dapat mengurangi risiko. Misalnya, ASP.NET Core Protected Browser Storage menggunakan ASP.NET Core Data Protection.
Paket NuGet pihak ketiga menyediakan API untuk bekerja dengan localStorage
dan sessionStorage
. Ada baiknya mempertimbangkan untuk memilih paket yang secara transparan menggunakan ASP.NET Core Data Protection. Perlindungan Data mengenkripsi data yang disimpan dan mengurangi potensi risiko perubahan data yang disimpan. Jika data serial JSON disimpan dalam teks biasa, pengguna dapat melihat data menggunakan alat pengembang browser dan juga memodifikasi data yang disimpan. Mengamankan data sepele bukanlah masalah. Misalnya, membaca atau memodifikasi warna elemen UI yang disimpan bukanlah risiko keamanan yang signifikan bagi pengguna atau organisasi. Hindari mengizinkan pengguna memeriksa atau mengubah data sensitif.
ASP.NET Penyimpanan Browser yang Dilindungi Inti
ASP.NET Penyimpanan Browser Yang Dilindungi Inti memanfaatkan ASP.NET Perlindungan Data Inti untuk localStorage
dan sessionStorage
.
Catatan
Penyimpanan Browser yang Dilindungi bergantung pada ASP.NET Core Data Protection dan hanya didukung untuk aplikasi sisi Blazor server.
Peringatan
Microsoft.AspNetCore.ProtectedBrowserStorage
adalah paket eksperimental yang tidak didukung yang tidak ditujukan untuk penggunaan produksi.
Paket ini hanya tersedia untuk digunakan di aplikasi ASP.NET Core 3.1.
Konfigurasi
Tambahkan referensi paket ke
Microsoft.AspNetCore.ProtectedBrowserStorage
.Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
_Host.cshtml
Dalam file, tambahkan skrip berikut di dalam tag penutup</body>
:<script src="_content/Microsoft.AspNetCore.ProtectedBrowserStorage/protectedBrowserStorage.js"></script>
Di
Startup.ConfigureServices
, panggilAddProtectedBrowserStorage
untuk menambahkanlocalStorage
dansessionStorage
layanan ke kumpulan layanan:services.AddProtectedBrowserStorage();
Menyimpan dan memuat data dalam komponen
Dalam komponen apa pun yang memerlukan pemuatan atau penyimpanan data ke penyimpanan browser, gunakan direktif @inject
untuk menyuntikkan instans dari salah satu hal berikut:
ProtectedLocalStorage
ProtectedSessionStorage
Pilihan tergantung pada lokasi penyimpanan browser mana yang ingin Anda gunakan. Dalam contoh berikut, sessionStorage
digunakan:
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
Arahan @using
dapat ditempatkan dalam file aplikasi _Imports.razor
alih-alih di komponen. Penggunaan _Imports.razor
file membuat namespace layanan tersedia untuk segmen aplikasi yang lebih besar atau seluruh aplikasi.
Untuk mempertahankan nilai dalam Counter
komponen aplikasi berdasarkan Blazor templat proyek, ubah IncrementCount
metode untuk menggunakan ProtectedSessionStore.SetAsync
:currentCount
private async Task IncrementCount()
{
currentCount++;
await ProtectedSessionStore.SetAsync("count", currentCount);
}
Dalam aplikasi yang lebih besar dan lebih realistis, penyimpanan bidang individual adalah skenario yang tidak mungkin. Aplikasi lebih cenderung menyimpan seluruh objek model yang menyertakan status kompleks. ProtectedSessionStore
secara otomatis menserialisasikan dan mendeserialisasi data JSON untuk menyimpan objek status yang kompleks.
Dalam contoh kode sebelumnya, currentCount
data disimpan seperti sessionStorage['count']
di browser pengguna. Data tidak disimpan dalam teks biasa melainkan dilindungi menggunakan ASP.NET Core Data Protection. Data terenkripsi dapat diperiksa jika sessionStorage['count']
dievaluasi di konsol pengembang browser.
Untuk memulihkan currentCount
data jika pengguna kembali ke Counter
komponen nanti, termasuk jika pengguna berada di sirkuit baru, gunakan ProtectedSessionStore.GetAsync
:
protected override async Task OnInitializedAsync()
{
var result = await ProtectedSessionStore.GetAsync<int>("count");
currentCount = result.Success ? result.Value : 0;
}
protected override async Task OnInitializedAsync()
{
currentCount = await ProtectedSessionStore.GetAsync<int>("count");
}
Jika parameter komponen menyertakan status navigasi, panggil ProtectedSessionStore.GetAsync
dan tetapkan non-hasilnull
di OnParametersSetAsync, bukan OnInitializedAsync. OnInitializedAsync hanya dipanggil sekali ketika komponen pertama kali dibuat. OnInitializedAsync tidak dipanggil lagi nanti jika pengguna menavigasi ke URL lain saat tetap berada di halaman yang sama. Untuk informasi lebih lanjut, lihat siklus hidup komponen Razor ASP.NET Core.
Peringatan
Contoh di bagian ini hanya berfungsi jika server tidak mengaktifkan pra-penyajian. Dengan prerendering diaktifkan, kesalahan dihasilkan menjelaskan bahwa panggilan interop JavaScript tidak dapat dikeluarkan karena komponen sedang dirender.
Nonaktifkan pra-penyajian atau tambahkan kode tambahan untuk bekerja dengan pra-penyajian. Untuk mempelajari selengkapnya tentang menulis kode yang berfungsi dengan pra-penyajian, lihat bagian Menangani pra-penyajian .
Menangani status pemuatan
Karena penyimpanan browser diakses secara asinkron melalui koneksi jaringan, selalu ada periode waktu sebelum data dimuat dan tersedia untuk komponen. Untuk hasil terbaik, render pesan saat pemuatan sedang berlangsung alih-alih menampilkan data kosong atau default.
Salah satu pendekatannya adalah melacak apakah data tersebut , null
yang berarti bahwa data masih dimuat. Dalam komponen default Counter
, hitungan disimpan dalam int
. Buat currentCount
nullable dengan menambahkan tanda tanya (?
) ke jenis (int
):
private int? currentCount;
Alih-alih menampilkan jumlah dan Increment
tombol secara tanpa syarat, tampilkan elemen-elemen ini hanya jika data dimuat dengan memeriksa HasValue:
@if (currentCount.HasValue)
{
<p>Current count: <strong>@currentCount</strong></p>
<button @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}
Menangani pra-penyajian
Selama pra-penyajian:
- Koneksi interaktif ke browser pengguna tidak ada.
- Browser belum memiliki halaman tempat browser dapat menjalankan kode JavaScript.
localStorage
atau sessionStorage
tidak tersedia selama pra-penyajian. Jika komponen mencoba berinteraksi dengan penyimpanan, kesalahan dihasilkan menjelaskan bahwa panggilan interop JavaScript tidak dapat dikeluarkan karena komponen sedang dirender.
Salah satu cara untuk mengatasi kesalahan adalah dengan menonaktifkan pra-penyajian. Ini biasanya merupakan pilihan terbaik jika aplikasi menggunakan penyimpanan berbasis browser dengan berat. Pra-penyajian menambah kompleksitas dan tidak menguntungkan aplikasi karena aplikasi tidak dapat merender konten yang berguna hingga localStorage
atau sessionStorage
tersedia.
Untuk menonaktifkan pra-penyajian, tunjukkan mode render dengan parameter yang prerender
diatur ke false
pada komponen tingkat tertinggi dalam hierarki komponen aplikasi yang bukan komponen root.
Catatan
Membuat komponen akar interaktif, seperti App
komponen, tidak didukung. Oleh karena itu, pra-penyajian tidak dapat dinonaktifkan secara langsung oleh App
komponen.
Untuk aplikasi berdasarkan Blazor Web App templat proyek, pra-penyajian biasanya dinonaktifkan di mana Routes
komponen digunakan dalam App
komponen (Components/App.razor
):
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
Selain itu, nonaktifkan pra-penyajian HeadOutlet
untuk komponen:
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
Untuk informasi selengkapnya, lihat mode render ASP.NET CoreBlazor.
Untuk menonaktifkan pra-penyajian_Host.cshtml
, buka file dan ubah render-mode
atribut Pembantu Tag Komponen menjadi Server:
<component type="typeof(App)" render-mode="Server" />
Saat pra-penyajian dinonaktifkan, pra-penyajian <head>
konten dinonaktifkan.
Pra-penyajian mungkin berguna untuk halaman lain yang tidak menggunakan localStorage
atau sessionStorage
. Untuk mempertahankan pra-penyajian, tangguhkan operasi pemuatan hingga browser terhubung ke sirkuit. Berikut ini adalah contoh untuk menyimpan nilai penghitung:
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedLocalStorage ProtectedLocalStore
@if (isConnected)
{
<p>Current count: <strong>@currentCount</strong></p>
<button @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}
@code {
private int currentCount;
private bool isConnected;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
isConnected = true;
await LoadStateAsync();
StateHasChanged();
}
}
private async Task LoadStateAsync()
{
var result = await ProtectedLocalStore.GetAsync<int>("count");
currentCount = result.Success ? result.Value : 0;
}
private async Task IncrementCount()
{
currentCount++;
await ProtectedLocalStore.SetAsync("count", currentCount);
}
}
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedLocalStorage ProtectedLocalStore
@if (isConnected)
{
<p>Current count: <strong>@currentCount</strong></p>
<button @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}
@code {
private int currentCount = 0;
private bool isConnected = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
isConnected = true;
await LoadStateAsync();
StateHasChanged();
}
}
private async Task LoadStateAsync()
{
currentCount = await ProtectedLocalStore.GetAsync<int>("count");
}
private async Task IncrementCount()
{
currentCount++;
await ProtectedLocalStore.SetAsync("count", currentCount);
}
}
Memperhitungkan pelestarian status ke lokasi umum
Jika banyak komponen mengandalkan penyimpanan berbasis browser, menerapkan kode penyedia status berkali-kali membuat duplikasi kode. Salah satu opsi untuk menghindari duplikasi kode adalah membuat komponen induk penyedia status yang merangkum logika penyedia status. Komponen anak dapat bekerja dengan data yang bertahan tanpa memperhatikan mekanisme kegigihan status.
Dalam contoh CounterStateProvider
komponen berikut, data penghitung dipertahankan ke sessionStorage
:
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
@if (isLoaded)
{
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
}
else
{
<p>Loading...</p>
}
@code {
private bool isLoaded;
[Parameter]
public RenderFragment? ChildContent { get; set; }
public int CurrentCount { get; set; }
protected override async Task OnInitializedAsync()
{
var result = await ProtectedSessionStore.GetAsync<int>("count");
CurrentCount = result.Success ? result.Value : 0;
isLoaded = true;
}
public async Task SaveChangesAsync()
{
await ProtectedSessionStore.SetAsync("count", CurrentCount);
}
}
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
@if (isLoaded)
{
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
}
else
{
<p>Loading...</p>
}
@code {
private bool isLoaded;
[Parameter]
public RenderFragment ChildContent { get; set; }
public int CurrentCount { get; set; }
protected override async Task OnInitializedAsync()
{
CurrentCount = await ProtectedSessionStore.GetAsync<int>("count");
isLoaded = true;
}
public async Task SaveChangesAsync()
{
await ProtectedSessionStore.SetAsync("count", CurrentCount);
}
}
Catatan
Untuk informasi selengkapnya tentang RenderFragment, lihat komponen ASP.NET CoreRazor.
Komponen CounterStateProvider
menangani fase pemuatan dengan tidak merender konten turunannya hingga pemuatan status selesai.
Untuk membuat status dapat diakses oleh semua komponen dalam aplikasi, bungkus CounterStateProvider
komponen di sekitar Router (<Router>...</Router>
) dalam Routes
komponen dengan penyajian sisi server interaktif global (SSR interaktif).
Dalam komponen App
(Components/App.razor
):
<Routes @rendermode="InteractiveServer" />
Dalam komponen Routes
(Components/Routes.razor
):
Untuk menggunakan CounterStateProvider
komponen, bungkus instans komponen di sekitar komponen lain yang memerlukan akses ke status penghitung. Untuk membuat status dapat diakses oleh semua komponen dalam aplikasi, bungkus CounterStateProvider
komponen di App
sekitar Router komponen (App.razor
):
<CounterStateProvider>
<Router ...>
...
</Router>
</CounterStateProvider>
Catatan
Dengan rilis ASP.NET Core 5.0.1 dan untuk rilis 5.x tambahan, komponen Router
menyertakan parameter PreferExactMatches
yang diatur ke @true
. Untuk informasi lebih lanjut, lihat Migrasi dari ASP.NET Core 3.1 ke 5.0.
Komponen yang dibungkus menerima dan dapat memodifikasi status penghitung yang bertahan. Komponen berikut Counter
mengimplementasikan pola:
@page "/counter"
<p>Current count: <strong>@CounterStateProvider?.CurrentCount</strong></p>
<button @onclick="IncrementCount">Increment</button>
@code {
[CascadingParameter]
private CounterStateProvider? CounterStateProvider { get; set; }
private async Task IncrementCount()
{
if (CounterStateProvider is not null)
{
CounterStateProvider.CurrentCount++;
await CounterStateProvider.SaveChangesAsync();
}
}
}
Komponen sebelumnya tidak diperlukan untuk berinteraksi dengan ProtectedBrowserStorage
, juga tidak berurusan dengan fase "pemuatan".
Untuk menangani pra-penyajian seperti yang dijelaskan sebelumnya, CounterStateProvider
dapat diubah sehingga semua komponen yang mengonsumsi data penghitung secara otomatis bekerja dengan pra-penyajian. Untuk informasi selengkapnya, lihat bagian Menangani pra-penyajian .
Secara umum, pola komponen induk penyedia status direkomendasikan:
- Untuk mengonsumsi status di banyak komponen.
- Jika hanya ada satu objek status tingkat atas yang akan dipertahankan.
Untuk mempertahankan banyak objek status yang berbeda dan mengonsumsi subset objek yang berbeda di tempat yang berbeda, lebih baik menghindari status bertahan secara global.
Status pengguna yang Blazor WebAssembly dibuat di aplikasi disimpan di memori browser.
Contoh status pengguna yang disimpan dalam memori browser meliputi:
- Hierarki instans komponen dan output render terbarunya di UI yang dirender.
- Nilai bidang dan properti dalam instans komponen.
- Data yang disimpan dalam instans layanan injeksi dependensi (DI ).
- Nilai yang diatur melalui panggilan interop JavaScript.
Saat pengguna menutup dan membuka kembali browser mereka atau memuat ulang halaman, status pengguna yang disimpan di memori browser hilang.
Catatan
Penyimpanan Browser Terproteksi (Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage namespace) bergantung pada ASP.NET Core Data Protection dan hanya didukung untuk aplikasi sisi Blazor server.
Mempertahankan status di seluruh sesi browser
Umumnya, pertahankan status di seluruh sesi browser di mana pengguna secara aktif membuat data, bukan hanya membaca data yang sudah ada.
Untuk mempertahankan status di seluruh sesi browser, aplikasi harus menyimpan data ke beberapa lokasi penyimpanan lain daripada memori browser. Persistensi status tidak otomatis. Anda harus mengambil langkah-langkah saat mengembangkan aplikasi untuk menerapkan persistensi data stateful.
Persistensi data biasanya hanya diperlukan untuk status bernilai tinggi yang dikeluarkan pengguna untuk dibuat. Dalam contoh berikut, status bertahan menghemat waktu atau membantu dalam aktivitas komersial:
- Formulir web multi-langkah: Ini memakan waktu bagi pengguna untuk memasukkan kembali data untuk beberapa langkah lengkap formulir web multi-langkah jika statusnya hilang. Pengguna kehilangan status dalam skenario ini jika mereka menavigasi menjauh dari formulir dan kembali nanti.
- Kelir belanja: Setiap komponen aplikasi yang penting secara komersial yang mewakili potensi pendapatan dapat dipertahankan. Pengguna yang kehilangan status mereka, dan dengan demikian kelir belanja mereka, dapat membeli lebih sedikit produk atau layanan ketika mereka kembali ke situs nanti.
Aplikasi hanya dapat mempertahankan status aplikasi. UI tidak dapat dipertahankan, seperti instans komponen dan pohon rendernya. Komponen dan pohon render umumnya tidak dapat diserialisasikan. Untuk mempertahankan status UI, seperti simpul kontrol tampilan pohon yang diperluas, aplikasi harus menggunakan kode kustom untuk memodelkan perilaku status UI sebagai status aplikasi yang dapat diserialisasikan.
Tempat untuk mempertahankan status
Lokasi umum ada untuk status bertahan:
Penyimpanan sisi server
Untuk persistensi data permanen yang mencakup beberapa pengguna dan perangkat, aplikasi dapat menggunakan penyimpanan sisi server independen yang diakses melalui API web. Opsi meliputi:
- Penyimpanan Blob
- Penyimpanan kunci-nilai
- Database hubungan
- Penyimpanan Tabel
Setelah data disimpan, status pengguna dipertahankan dan tersedia di sesi browser baru apa pun.
Karena Blazor WebAssembly aplikasi berjalan sepenuhnya di browser pengguna, aplikasi memerlukan langkah-langkah tambahan untuk mengakses sistem eksternal yang aman, seperti layanan penyimpanan dan database. Aplikasi Blazor WebAssembly diamankan dengan cara yang sama seperti aplikasi satu halaman (SPA). Biasanya, aplikasi mengautentikasi pengguna melalui OAuth/OpenID Connect (OIDC) lalu berinteraksi dengan layanan penyimpanan dan database melalui panggilan API web ke aplikasi sisi server. Aplikasi sisi server menengahi transfer data antara Blazor WebAssembly aplikasi dan layanan penyimpanan atau database. Aplikasi ini Blazor WebAssembly mempertahankan koneksi sementara ke aplikasi sisi server, sementara aplikasi sisi server memiliki koneksi persisten ke penyimpanan.
Untuk informasi selengkapnya, lihat sumber daya berikut:
- Memanggil API web dari aplikasi ASP.NET Core Blazor
- Amankan ASP.NET Core Blazor WebAssembly
- BlazorKeamanan dan Identity artikel
Untuk informasi selengkapnya tentang opsi penyimpanan data Azure, lihat yang berikut ini:
URL
Untuk data sementara yang mewakili status navigasi, modelkan data sebagai bagian dari URL. Contoh status pengguna yang dimodelkan dalam URL meliputi:
- ID entitas yang dilihat.
- Nomor halaman saat ini dalam kisi halaman.
Konten bilah alamat browser dipertahankan jika pengguna memuat ulang halaman secara manual.
Untuk informasi tentang menentukan pola URL dengan direktif@page
, lihat perutean dan navigasi core Blazor ASP.NET.
Penyimpanan browser
Untuk data sementara yang dibuat pengguna secara aktif, lokasi penyimpanan yang umum digunakan adalah browser localStorage
dan sessionStorage
koleksi:
localStorage
dilingkup ke jendela browser. Jika pengguna memuat ulang halaman atau menutup dan membuka kembali browser, status tetap ada. Jika pengguna membuka beberapa tab browser, status dibagikan di seluruh tab. Data bertahan hingga dihapus secara eksplisitlocalStorage
.sessionStorage
dilingkup ke tab browser. Jika pengguna memuat ulang tab, status tetap ada. Jika pengguna menutup tab atau browser, status akan hilang. Jika pengguna membuka beberapa tab browser, setiap tab memiliki versi data independennya sendiri.
Catatan
localStorage
dan sessionStorage
dapat digunakan di Blazor WebAssembly aplikasi tetapi hanya dengan menulis kode kustom atau menggunakan paket pihak ketiga.
Umumnya, sessionStorage
lebih aman digunakan. sessionStorage
menghindari risiko pengguna membuka beberapa tab dan mengalami hal berikut:
- Bug dalam penyimpanan status di seluruh tab.
- Perilaku membingungkan saat tab menimpa status tab lain.
localStorage
adalah pilihan yang lebih baik jika aplikasi harus mempertahankan status di seluruh penutupan dan membuka kembali browser.
Peringatan
Pengguna dapat melihat atau mengubah data yang disimpan di localStorage
dan sessionStorage
.
Layanan kontainer status dalam memori
Komponen berlapis biasanya mengikat data menggunakan ikatan berantai seperti yang dijelaskan dalam pengikatan data ASP.NET CoreBlazor. Komponen berlapis dan tidak terencana dapat berbagi akses ke data menggunakan kontainer status dalam memori terdaftar. Kelas kontainer status kustom dapat menggunakan yang dapat Action ditetapkan untuk memberi tahu komponen di berbagai bagian aplikasi perubahan status. Dalam contoh berikut:
- Sepasang komponen menggunakan kontainer status untuk melacak properti.
- Satu komponen dalam contoh berikut disarangkan di komponen lain, tetapi bersarang tidak diperlukan agar pendekatan ini berfungsi.
Penting
Contoh di bagian ini menunjukkan cara membuat layanan kontainer status dalam memori, mendaftarkan layanan, dan menggunakan layanan dalam komponen. Contohnya tidak menyimpan data tanpa pengembangan lebih lanjut. Untuk penyimpanan data persisten, kontainer status harus mengadopsi mekanisme penyimpanan yang mendasar yang bertahan ketika memori browser dihapus. Ini dapat dicapai dengan localStorage
/sessionStorage
atau beberapa teknologi lainnya.
StateContainer.cs
:
public class StateContainer
{
private string? savedString;
public string Property
{
get => savedString ?? string.Empty;
set
{
savedString = value;
NotifyStateChanged();
}
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
Aplikasi sisi klien (Program
file):
builder.Services.AddSingleton<StateContainer>();
Aplikasi sisi server (Program
file, ASP.NET Core di .NET 6 atau yang lebih baru):
builder.Services.AddScoped<StateContainer>();
Aplikasi sisi server (Startup.ConfigureServices
dari Startup.cs
, ASP.NET Core lebih awal dari 6.0):
services.AddScoped<StateContainer>();
Shared/Nested.razor
:
@implements IDisposable
@inject StateContainer StateContainer
<h2>Nested component</h2>
<p>Nested component Property: <b>@StateContainer.Property</b></p>
<p>
<button @onclick="ChangePropertyValue">
Change the Property from the Nested component
</button>
</p>
@code {
protected override void OnInitialized()
{
StateContainer.OnChange += StateHasChanged;
}
private void ChangePropertyValue()
{
StateContainer.Property =
$"New value set in the Nested component: {DateTime.Now}";
}
public void Dispose()
{
StateContainer.OnChange -= StateHasChanged;
}
}
StateContainerExample.razor
:
@page "/state-container-example"
@implements IDisposable
@inject StateContainer StateContainer
<h1>State Container Example component</h1>
<p>State Container component Property: <b>@StateContainer.Property</b></p>
<p>
<button @onclick="ChangePropertyValue">
Change the Property from the State Container Example component
</button>
</p>
<Nested />
@code {
protected override void OnInitialized()
{
StateContainer.OnChange += StateHasChanged;
}
private void ChangePropertyValue()
{
StateContainer.Property = "New value set in the State " +
$"Container Example component: {DateTime.Now}";
}
public void Dispose()
{
StateContainer.OnChange -= StateHasChanged;
}
}
Komponen sebelumnya mengimplementasikan IDisposable, dan OnChange
delegasi tidak berlangganan dalam Dispose
metode, yang dipanggil oleh kerangka kerja ketika komponen dibuang. Untuk informasi lebih lanjut, lihat siklus hidup komponen Razor ASP.NET Core.
Pendekatan tambahan
Saat menerapkan penyimpanan status kustom, pendekatan yang berguna adalah mengadopsi nilai dan parameter berskala:
- Untuk mengonsumsi status di banyak komponen.
- Jika hanya ada satu objek status tingkat atas yang akan dipertahankan.
Pecahkan masalah
Dalam layanan manajemen status kustom, panggilan balik yang dipanggil di luar Blazorkonteks sinkronisasi harus membungkus logika panggilan balik ComponentBase.InvokeAsync untuk memindahkannya ke konteks sinkronisasi perender.
Saat layanan manajemen status tidak memanggil StateHasChanged Blazorkonteks sinkronisasi 's, kesalahan berikut akan muncul:
System.InvalidOperationException: 'Utas saat ini tidak terkait dengan Dispatcher. Gunakan InvokeAsync() untuk mengalihkan eksekusi ke Dispatcher saat memicu penyajian atau status komponen.'
Untuk informasi selengkapnya dan contoh cara mengatasi kesalahan ini, lihat ASP.NET penyajian komponen CoreRazor.
Sumber Daya Tambahan:
- Menyimpan status aplikasi sebelum operasi autentikasi (Blazor WebAssembly)
- Mengelola status melalui API server eksternal
ASP.NET Core