Aracılığıyla paylaş


ASP.NET Core Blazor durum yönetimi

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

Uyarı

ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

Bu makalede, bir uygulamayı kullanırken ve tarayıcı oturumlarında kullanıcının verilerini (durumunu) korumaya yönelik yaygın yaklaşımlar açıklanmaktadır.

Not

Bu makaledeki kod örnekleri, .NET 6 veya sonraki sürümlerindeki ASP.NET Core'da desteklenen null atanabilir başvuru türlerini (NTS) ve .NET derleyici null durum statik analizini benimser. .NET 5 veya önceki sürümleri hedeflerken, makalenin örneklerindeki türlerden null tür atamasını (?) kaldırın.

Kullanıcı durumunu koruma

Sunucu tarafı Blazor durum bilgisi olan bir uygulama çerçevesidir. Çoğu zaman uygulama sunucuya bir bağlantı tutar. Kullanıcının durumu, sunucunun belleğinde bir devre içinde tutulur.

Bir bağlantı hattında tutulan kullanıcı durumu örnekleri şunlardır:

  • Bileşen örneklerinin hiyerarşisi ve işlenen kullanıcı arabirimindeki en son işleme çıktısı.
  • Bileşen örneklerindeki alanların ve özelliklerin değerleri.
  • Devreye yönelik bağımlılık ekleme (DI) hizmet örneklerinde tutulan veriler.

Kullanıcı durumu, JavaScript birlikte çalışma çağrıları aracılığıyla tarayıcının bellek kümesindeki JavaScript değişkenlerinde de bulunabilir.

Bir kullanıcı geçici bir ağ bağlantısı kaybıyla karşılaşırsa, Blazor kullanıcıyı özgün durumuyla özgün bağlantı hattına yeniden bağlamayı dener. Ancak, bir kullanıcıyı sunucunun belleğindeki özgün bağlantı hattına yeniden bağlamak her zaman mümkün değildir:

  • Sunucu bağlantısı kesilmiş bir devreyi sonsuza kadar tutamaz. Sunucunun zaman aşımından sonra veya sunucu bellek baskısı altındayken bağlantısı kesilmiş bir bağlantı hattını serbest bırakması gerekir.
  • Çok sunuculu, yük dengeli dağıtım ortamlarında tek tek sunucular başarısız olabilir veya isteklerin genel hacmini işlemek için artık gerekli olmadığında otomatik olarak kaldırılabilir. Kullanıcının özgün sunucu işleme istekleri, kullanıcı yeniden bağlanmayı denediğinde kullanılamaz duruma gelebilir.
  • Kullanıcı tarayıcısını kapatıp yeniden açabileceği gibi, tarayıcının belleğinde tutulan tüm durumları kaldıran sayfayı yeniden yükleyebilir. Örneğin, JavaScript birlikte çalışma çağrıları aracılığıyla ayarlanan JavaScript değişken değerleri kaybolur.

Bir kullanıcı özgün bağlantı hattına yeniden bağlanamayınca, kullanıcı boş durumda yeni bir bağlantı hattı alır. Bu, masaüstü uygulamasını kapatıp yeniden açmakla eşdeğerdir.

Devreler arasında kalıcı durum

Genel olarak, kullanıcıların zaten var olan verileri okumak yerine etkin bir şekilde veri oluşturduğu devreler arasında durumu koruyun.

Devreler arasında durumu korumak için uygulamanın verileri sunucunun belleğinden başka bir depolama konumuna kalıcı hale getirebilmesi gerekir. Durum kalıcılığı otomatik değildir. Uygulamayı geliştirirken, durumsal veri kalıcılığını uygulamak için önlemler almalısınız.

Veri kalıcılığı genellikle yalnızca kullanıcıların oluşturmak için çaba harcamış olduğu yüksek değerli durum için gereklidir. Aşağıdaki örneklerde kalıcı durum, ya zaman tasarrufu sağlar ya da ticari faaliyetlerde yardımcı olur:

  • Çok adımlı web formları: Bir kullanıcının durumu kaybolursa, çok adımlı bir web formunun tamamlanmış birkaç adımı için verileri yeniden girmesi zaman alır. Bir kullanıcı formdan uzaklaşıp daha sonra geri dönerse bu senaryoda durumu kaybeder.
  • Alışveriş sepetleri: Bir uygulamanın potansiyel geliri temsil eden ticari açıdan önemli bileşenleri korunabilir. Durumunu ve dolayısıyla alışveriş sepetini kaybeden bir kullanıcı, daha sonra siteye geri döndüğünde daha az ürün veya hizmet satın alabilir.

Bir uygulama yalnızca uygulama durumunu kalıcı hale gelebilir. Kullanıcı Arabirimleri, bileşen örnekleri ve bunların işleme ağaçları gibi öğeler kalıcı hale getirilemiyor. Bileşenler ve işleme ağaçları genellikle seri hale getirilemez. Ağaç görünümü denetiminin genişletilmiş düğümleri gibi ui durumunu kalıcı hale getirmek için uygulamanın kullanıcı arabirimi durumunun davranışını serileştirilebilir uygulama durumu olarak modellemek için özel kod kullanması gerekir.

Durumun nerede saklanacağı

Kalıcı durum için ortak konumlar vardır:

Kalıcı durum için bildirim temelli model

Özel bir hizmet türü ve işleme modu ile RegisterPersistentService bileşenler oluşturucuya RazorAddRazorComponents çağrısı yaparak uygulamada kullanılmak üzere bir bağımlılık enjeksiyon hizmetinde bildirimci durum oluşturun. Daha fazla bilgi için bkz. Prerender ASP.NET Core Razor bileşenleri.

Sunucu tarafı depolama

Uygulama, birden çok kullanıcıya ve cihaza yayılan kalıcı veri kalıcılığı için sunucu tarafı depolamayı kullanabilir. Seçenekler arasında bulunanlar:

  • Blob depolama
  • Anahtar-değer depolama
  • İlişkisel veritabanı
  • Tablo veri depolama

Veriler kaydedildikten sonra, kullanıcının durumu korunur ve herhangi bir yeni bağlantı hattında kullanılabilir.

Azure veri depolama seçenekleri hakkında daha fazla bilgi için aşağıdakilere bakın:

URL

Gezinti durumunu temsil eden geçici veriler için verileri URL'nin bir parçası olarak modellenin. URL'de modellenen kullanıcı durumu örnekleri şunlardır:

  • Görüntülenen varlığın kimliği.
  • Sayfalanmış kılavuzdaki geçerli sayfa numarası.

Tarayıcının adres çubuğunun içeriği korunur:

  • Kullanıcı sayfayı el ile yeniden yüklerse.
  • Web sunucusu kullanılamaz duruma gelirse ve kullanıcı farklı bir sunucuya bağlanmak için sayfayı yeniden yüklemeye zorlanırsa.

yönergesiyle @page URL desenlerini tanımlama hakkında bilgi için bkz . ASP.NET Çekirdek Blazor yönlendirme ve gezinti.

Tarayıcı depolama alanı

Kullanıcının etkin olarak oluşturduğu geçici veriler için yaygın olarak kullanılan depolama konumu tarayıcının localStorage ve sessionStorage koleksiyonlarıdır:

  • localStorage, tarayıcının belirli örneğiyle sınırlıdır. Kullanıcı sayfayı yeniden yüklerse veya tarayıcıyı kapatıp yeniden açarsa durum devam eder. Kullanıcı birden çok tarayıcı sekmesi açarsa, durum sekmeler arasında paylaşılır. Veriler, açıkça temizlenene kadar localStorage'da kalır. "Özel gözatma" veya "gizli" oturumda yüklenen bir belgenin localStorage verileri, son "özel" sekme kapatıldığında temizlenir.
  • sessionStorage kapsamı tarayıcı sekmesine göre belirlenmiştir. Kullanıcı sekmeyi yeniden yüklerse durum devam eder. Kullanıcı sekmeyi veya tarayıcıyı kapatırsa durum kaybolur. Kullanıcı birden çok tarayıcı sekmesi açarsa, her sekmenin kendi bağımsız veri sürümü vardır.

sessionStorage Genellikle kullanımı daha güvenlidir. sessionStorage kullanıcının birden çok sekme açması ve aşağıdakilerle karşılaşması riskini önler:

  • Sekmeler arasında durum depolamadaki hatalar.
  • Bir sekmenin, diğer sekmelerin durumunu değiştirmesi kafa karıştırıcı bir davranış.

localStorage , uygulamanın tarayıcıyı kapatma ve yeniden açma işlemi boyunca durumu kalıcı hale döndürmesi gerekiyorsa daha iyi bir seçenektir.

Tarayıcı depolamayı kullanmayla ilgili uyarılar:

  • Sunucu tarafı veritabanı kullanımına benzer şekilde, verileri yükleme ve kaydetme zaman uyumsuz bir işlemdir.
  • İstenen sayfa, ön kayıt sırasında tarayıcıda mevcut olmadığından, yerel depolama önceden kullanım sırasında kullanılamaz.
  • Sunucu tarafı Blazor uygulamalar için birkaç kilobaytlık veri depolamanın kalıcı olması mantıklıdır. Veriler ağ üzerinden yüklenip kaydedildiğinden, birkaç kilobayttan fazla performans etkilerini göz önünde bulundurmanız gerekir.
  • Kullanıcılar verileri görüntüleyebilir veya üzerinde değişiklik yapabilir. ASP.NET Core Data Protection riski azaltabilir. Örneğin, ASP.NET Core Protected Browser Storage ASP.NET Core Data Protection kullanır.

Üçüncü taraf NuGet paketleri, localStorage ve sessionStorage ile çalışmak için API'ler sağlar. ASP.NET Core Data Protection'ı saydam olarak kullanan bir paket seçmeyi göz önünde bulundurmak değerlidir. Veri Koruması depolanan verileri şifreler ve depolanan verilerle oynanma riskini azaltır. JSON serileştirilmiş verileri düz metin olarak depolanıyorsa, kullanıcılar tarayıcı geliştirici araçlarını kullanarak verileri görebilir ve depolanan verileri değiştirebilir. Önemsiz verilerin güvenliğini sağlamak bir sorun değildir. Örneğin, kullanıcı arabirimi öğesinin depolanan rengini okumak veya değiştirmek kullanıcı veya kuruluş için önemli bir güvenlik riski değildir. Kullanıcıların hassas verileri incelemesine veya kurcalamasına izin vermekten kaçının.

ASP.NET Core Korumalı Tarayıcı Depolama alanı

ASP.NET Core Protected Browser Storage, ASP.NET Core Veri Koruma'yı ve için kullanır.

Not

Protected Browser Storage, ASP.NET Core Data Protection'a dayanır ve yalnızca sunucu tarafı Blazor uygulamalar için desteklenir.

Uyarı

Microsoft.AspNetCore.ProtectedBrowserStorage , üretim kullanımına yönelik olmayan desteklenmeyen, deneysel bir pakettir.

Paket yalnızca ASP.NET Core 3.1 uygulamalarında kullanılabilir.

Yapılandırma

  1. Microsoft.AspNetCore.ProtectedBrowserStorage öğesine bir paket başvurusu ekleyin.

    Not

    .NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri)paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.

  2. Dosyada _Host.cshtml, kapanış </body> etiketinin içine aşağıdaki komutu ekleyin:

    <script src="_content/Microsoft.AspNetCore.ProtectedBrowserStorage/protectedBrowserStorage.js"></script>
    
  3. Startup.ConfigureServices içinde, AddProtectedBrowserStorage hizmetlerini ve localStorage hizmetlerini hizmet koleksiyonuna eklemek için sessionStorage çağrısını yapın.

    services.AddProtectedBrowserStorage();
    

Bir bileşen içindeki verileri kaydetme ve yükleme

Tarayıcı depolama alanına veri yüklemeyi veya kaydetmeyi gerektiren herhangi bir bileşende @inject , aşağıdakilerden birinin örneğini eklemek için yönergesini kullanın:

  • ProtectedLocalStorage
  • ProtectedSessionStorage

Seçim, kullanmak istediğiniz tarayıcı depolama konumuna bağlıdır. Aşağıdaki örnekte, sessionStorage kullanılır:

@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore

@using yönergesi, bileşeni yerine uygulamanın _Imports.razor dosyasına yerleştirilebilir. _Imports.razor Dosyanın kullanılması, ad alanını uygulamanın daha büyük kesimleri veya uygulamanın tamamı için kullanılabilir hale getirir.

Proje şablonuna dayalı bir uygulamanın currentCount bileşenindeki Counter değerini kalıcı hale getirmek için Blazor yöntemini kullanacak şekilde değiştirin.

private async Task IncrementCount()
{
    currentCount++;
    await ProtectedSessionStore.SetAsync("count", currentCount);
}

Daha büyük ve daha gerçekçi uygulamalarda, tek tek alanların depolanması olası olmayan bir senaryodur. Uygulamaların karmaşık durum içeren tüm model nesnelerini depolama olasılığı daha yüksektir. ProtectedSessionStore karmaşık durum nesnelerini depolamak için JSON verilerini otomatik olarak serileştirir ve seri durumdan çıkartır.

Yukarıdaki kod örneğinde currentCount veriler kullanıcının tarayıcısında olduğu gibi sessionStorage['count'] depolanır. Veriler düz metin olarak depolanmaz, bunun yerine ASP.NET Core Data Protection kullanılarak korunur. Şifrelenmiş veriler tarayıcının geliştirici konsolunda değerlendirilirse sessionStorage['count'] incelenebilir.

Kullanıcı daha sonra currentCount bileşenine geri dönerse, kullanıcının yeni bir bağlantı hattında olup olmadığını da içeren verileri kurtarmak için Counter kullanın.

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

Bileşenin parametreleri gezinti durumunu içeriyorsa, ProtectedSessionStore.GetAsync çağrısını yapın ve null'ye OnParametersSetAsync olmayan bir sonuç atayın, OnInitializedAsync'ye değil. OnInitializedAsync yalnızca bileşen ilk kez başlatıldığında çağrılır. OnInitializedAsync daha sonra kullanıcı aynı sayfada kalırken farklı bir URL'ye giderse yeniden çağrılmaz. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşeni yaşam döngüsü.

Uyarı

Bu bölümdeki örnekler yalnızca sunucuda ön kayıt etkinleştirilmemişse çalışır. Önceden sunum etkinleştirildiğinde, bileşen önceden sunulduğu için JavaScript birlikte çalışabilirlik çağrılarının yapılamadığını açıklayan bir hata oluşturulur.

Prerendering'i devre dışı bırakın veya ön kayıtla çalışmak için ek kod ekleyin. Prerendering ile çalışan kod yazma hakkında daha fazla bilgi edinmek için Ön belleklemeyi yönetme bölümüne bakın.

Yükleme durumunu işleme

Tarayıcı depolamaya bir ağ bağlantısı üzerinden zaman uyumsuz olarak erişildiğinden, veriler yüklenmeden ve bir bileşen tarafından kullanılabilir duruma gelmeden önce her zaman bir süre vardır. En iyi sonuçlar için, boş veya varsayılan veriler görüntülemek yerine yükleme işlemi devam ederken bir ileti işleyin.

Bir yaklaşım, verilerin null olup olmadığını izlemektir; bu da verilerin hala yüklendiği anlamına gelir. Varsayılan Counter bileşende, sayı bir intiçinde tutulur. currentCount

private int? currentCount;

Sayıyı ve Increment düğmeyi koşulsuz olarak görüntülemek yerine, yalnızca veriler denetlenerek HasValueyüklenirse bu öğeleri görüntüleyin:

@if (currentCount.HasValue)
{
    <p>Current count: <strong>@currentCount</strong></p>
    <button @onclick="IncrementCount">Increment</button>
}
else
{
    <p>Loading...</p>
}

Önceden render etmeyi işle

Önişleme sırasında:

  • Kullanıcının tarayıcısıyla etkileşimli bir bağlantı yoktur.
  • Tarayıcının henüz JavaScript kodu çalıştırabileceği bir sayfası yok.

localStorage veya sessionStorage prerendering sırasında kullanılamaz. Bileşen depolamayla etkileşim kurmaya çalışırsa, bileşen önceden oluşturulduğundan JavaScript birlikte çalışma çağrılarının verilemediğini açıklayan bir hata oluşturulur.

Hatayı düzeltmenin bir yolu, ön kayıt işlemini devre dışı bırakmaktır. Uygulama tarayıcı tabanlı depolamayı yoğun bir şekilde kullanıyorsa bu genellikle en iyi seçenektir. Prerendering karmaşıklık ekler ve localStorage veya sessionStorage kullanılabilir hale gelene kadar yararlı içerik önyazılamayacağı için uygulamaya fayda sağlamaz.

Ön işlemeyi devre dışı bırakmak için, uygulamanın bileşen hiyerarşisinde kök bileşen olmayan en üst düzey bileşende prerender parametresi false olarak ayarlanan işleme modunu belirtin.

Not

Kök bileşeni etkileşimli hale getirme (bileşen gibi App ) desteklenmez. Bu nedenle, prerendering bileşeni tarafından App doğrudan devre dışı bırakılamaz.

Proje şablonuna dayalı uygulamalarda, Blazor Web App bileşeni Routes bileşeninde kullanıldığında, ön işleme genellikle devre dışı bırakılır (AppComponents/App.razor).

<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Ayrıca, bileşen için HeadOutlet ön kayıt özelliğini devre dışı bırakın:

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Daha fazla bilgi için bkz . ASP.NET Core Blazor işleme modları.

Ön kayıt özelliğini devre dışı bırakmak için _Host.cshtml dosyasını açın ve render-mode özniteliğini olarak Server değiştirin.

<component type="typeof(App)" render-mode="Server" />

Ön işlemeyle oluşturma devre dışı bırakıldığında, [<head> içerik] ön işlemeyle oluşturma devre dışı bırakılır.

Önceden işleme, localStorage veya sessionStorage kullanmayan diğer sayfalar için yararlı olabilir. Ön çalıştırmayı korumak için, tarayıcı bağlantı hattına bağlanana kadar yükleme işlemini erteleyin. Aşağıda, sayaç değerini depolamak için bir örnek verilmiştir:

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

Durum korumayı ortak bir sağlayıcıya ayır

Birçok bileşen tarayıcı tabanlı depolamayı kullanırsa, durum sağlayıcısı kodunun birçok kez uygulanması kod yinelemesi oluşturur. Kod yinelemesini önlemenin bir seçeneği, durum sağlayıcısı mantığını kapsülleyen bir durum sağlayıcısı üst bileşeni oluşturmaktır. Alt bileşenler, durum kalıcılığı mekanizmasına bakılmaksızın kalıcı verilerle çalışabilir.

Aşağıdaki CounterStateProvider bileşeni örneğinde, sayaç verileri sessionStorageolarak kalıcı hale getirilir ve durum yüklemesi tamamlanana kadar alt içeriğini işlemeyerek yükleme aşamasını işler.

bileşeni, bileşen işlemesi tamamlandıktan sonra durumu yükleyerek prerendering işlemiyle ilgilenir. Bu durum, yaşam döngüsü yönteminde gerçekleşir ve ön işleme sırasında yürütülmez.

Bu bölümdeki yaklaşım, abone olunan birden çok bileşenin aynı sayfada yeniden yenilenmesi tetikleme özelliğine sahip değildir. Abone olunan bileşenlerden biri durumu değiştirirse, yeniden render edilir ve güncellenmiş durumu görüntüleyebilir, ancak aynı sayfada bu durumu görüntüleyen farklı bir bileşen, kendi bir sonraki yeniden render edilmesine kadar güncel olmayan verileri görüntüler. Bu nedenle, bu bölümde açıklanan yaklaşım, sayfadaki tek bir bileşende durum kullanmak için en uygun yöntemdir.

CounterStateProvider.razor:

@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 OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            isLoaded = true;
            await LoadStateAsync();
            StateHasChanged();
        }
    }

    private async Task LoadStateAsync()
    {
        var result = await ProtectedSessionStore.GetAsync<int>("count");
        CurrentCount = result.Success ? result.Value : 0;
        isLoaded = true;
    }

    public async Task IncrementCount()
    {
        CurrentCount++;
        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 OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            isLoaded = true;
            await LoadStateAsync();
            StateHasChanged();
        }
    }

    private async Task LoadStateAsync()
    {
        CurrentCount = await ProtectedSessionStore.GetAsync<int>("count");
        isLoaded = true;
    }

    public async Task IncrementCount()
    {
        CurrentCount++;
        await ProtectedSessionStore.SetAsync("count", CurrentCount);
    }
}

Not

hakkında RenderFragmentdaha fazla bilgi için bkz . ASP.NET Core Razor bileşenleri.

Durumu bir uygulamadaki tüm bileşenler için erişilebilir hale getirmek için, CounterStateProvider bileşenini Router bileşeni içindeki <Router>...</Router> (Routes) bileşeninin etrafına, genel etkileşimli sunucu tarafı işleme (etkileşimli SSR) ile sarın.

App bileşeninde (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Routes bileşeninde (Components/Routes.razor):

bileşenini kullanmak için, sayacın durumuna erişim gerektiren diğer bir bileşenin etrafına bileşenin bir örneğini sarın. Bir uygulamadaki tüm bileşenler için durumu erişilebilir hale getirmek amacıyla, CounterStateProvider bileşenini Router bileşeninde App etrafına sarın (App.razor):

<CounterStateProvider>
    <Router ...>
        ...
    </Router>
</CounterStateProvider>

Not

.NET 5.0.1 sürümünün çıkışı ve ek 5.x sürümleri için, Router bileşeni PreferExactMatches parametresini @true olarak ayarlayacaktır. Daha fazla bilgi için bkz. ASP.NET Core 3.1'den .NET 5'e geçiş.

Sarmalanmış bileşenler kalıcı sayaç durumunu alır ve değiştirebilir. Aşağıdaki Counter bileşen deseni uygular:

@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)
        {
            await CounterStateProvider.IncrementCount();
        }
    }
}

Önceki bileşenin ile ProtectedBrowserStorageetkileşim kurması gerekmez ve bir "yükleme" aşamasıyla ilgilenmez.

Genel olarak, durum sağlayıcısı üst bileşen deseni önerilir:

  • Birçok bileşende durumu tüketmek için.
  • Kalıcı olarak yalnızca bir üst düzey durum nesnesi varsa.

Birçok farklı durum nesnesini kalıcı hale getirmek ve farklı yerlerdeki nesnelerin farklı alt kümelerini kullanmak için, durumu genel olarak kalıcı hale getirmekten kaçınmak daha iyidir.

Bir Blazor WebAssembly uygulamada oluşturulan kullanıcı durumu tarayıcının belleğinde tutulur.

Tarayıcı belleğinde tutulan kullanıcı durumu örnekleri şunlardır:

  • Bileşen örneklerinin hiyerarşisi ve işlenen kullanıcı arabirimindeki en son işleme çıktısı.
  • Bileşen örneklerindeki alanların ve özelliklerin değerleri.
  • Bağımlılık ekleme (DI) hizmet örneklerinde tutulan veriler.
  • JavaScript interop çağrıları aracılığıyla ayarlanan değerler.

Kullanıcı tarayıcısını kapatıp yeniden açtığınızda veya sayfayı yeniden yüklediğinde, tarayıcının belleğinde tutulan kullanıcı durumu kaybolur.

Not

Protected Browser Storage (Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage ad alanı), ASP.NET Çekirdek Veri Koruması'nı temel alır ve yalnızca sunucu tarafı Blazor uygulamalar için desteklenir.

Tarayıcı oturumları boyunca durumu sürdürün

Genel olarak, kullanıcıların zaten var olan verileri okumak yerine etkin bir şekilde veri oluşturduğu tarayıcı oturumlarında durumu koruyun.

Tarayıcı oturumlarında durumu korumak için uygulamanın verileri tarayıcının belleğinden başka bir depolama konumuna kalıcı hale getirmek gerekir. Durum kalıcılığı otomatik değildir. Uygulamayı geliştirirken, durumsal veri kalıcılığını uygulamak için önlemler almalısınız.

Veri kalıcılığı genellikle yalnızca kullanıcıların oluşturmak için çaba harcamış olduğu yüksek değerli durum için gereklidir. Aşağıdaki örneklerde kalıcı durum, ya zaman tasarrufu sağlar ya da ticari faaliyetlerde yardımcı olur:

  • Çok adımlı web formları: Bir kullanıcının durumu kaybolursa, çok adımlı bir web formunun tamamlanmış birkaç adımı için verileri yeniden girmesi zaman alır. Bir kullanıcı formdan uzaklaşıp daha sonra geri dönerse bu senaryoda durumu kaybeder.
  • Alışveriş sepetleri: Bir uygulamanın potansiyel geliri temsil eden ticari açıdan önemli bileşenleri korunabilir. Durumunu ve dolayısıyla alışveriş sepetini kaybeden bir kullanıcı, daha sonra siteye geri döndüğünde daha az ürün veya hizmet satın alabilir.

Bir uygulama yalnızca uygulama durumunu kalıcı hale gelebilir. Kullanıcı Arabirimleri, bileşen örnekleri ve bunların işleme ağaçları gibi öğeler kalıcı hale getirilemiyor. Bileşenler ve işleme ağaçları genellikle seri hale getirilemez. Ağaç görünümü denetiminin genişletilmiş düğümleri gibi ui durumunu kalıcı hale getirmek için uygulamanın kullanıcı arabirimi durumunun davranışını serileştirilebilir uygulama durumu olarak modellemek için özel kod kullanması gerekir.

Durumun nerede saklanacağı

Kalıcı durum için ortak konumlar vardır:

Kalıcı durum için bildirim temelli model

Özel bir hizmet türü ve işleme modu ile RegisterPersistentService bileşenler oluşturucuya RazorAddRazorComponents çağrısı yaparak uygulamada kullanılmak üzere bir bağımlılık enjeksiyon hizmetinde bildirimci durum oluşturun. Daha fazla bilgi için bkz. Prerender ASP.NET Core Razor bileşenleri.

Sunucu tarafı depolama

Birden çok kullanıcıya ve cihaza yayılan kalıcı veri kalıcılığı için uygulama, bir web API'si aracılığıyla erişilen bağımsız sunucu tarafı depolamayı kullanabilir. Seçenekler arasında bulunanlar:

  • Blob depolama
  • Anahtar-değer depolama
  • İlişkisel veritabanı
  • Tablo veri depolama

Veriler kaydedildikten sonra, kullanıcının durumu korunur ve herhangi bir yeni tarayıcı oturumunda kullanılabilir.

Blazor WebAssembly Uygulamalar tamamen kullanıcının tarayıcısında çalıştığından, depolama hizmetleri ve veritabanları gibi güvenli dış sistemlere erişmek için ek ölçüler gerektirir. Blazor WebAssembly uygulamaları tek sayfalı uygulamalarla (SPA'lar) aynı şekilde güvenli hale getirilir. Genellikle, bir uygulama OAuthkullanıcının kimliğini doğrular ve ardından sunucu tarafı bir uygulamaya web API çağrıları aracılığıyla depolama hizmetleri ve veritabanlarıyla etkileşim kurar. Sunucu tarafı uygulaması, uygulama ile depolama hizmeti veya veritabanı arasında Blazor WebAssembly veri aktarımına aracılık eder. Uygulama Blazor WebAssembly , sunucu tarafı uygulamasına kısa ömürlü bir bağlantı tutarken, sunucu tarafı uygulamasının depolamaya kalıcı bir bağlantısı vardır.

Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Azure veri depolama seçenekleri hakkında daha fazla bilgi için aşağıdakilere bakın:

URL

Gezinti durumunu temsil eden geçici veriler için verileri URL'nin bir parçası olarak modellenin. URL'de modellenen kullanıcı durumu örnekleri şunlardır:

  • Görüntülenen varlığın kimliği.
  • Sayfalanmış kılavuzdaki geçerli sayfa numarası.

Kullanıcı sayfayı el ile yeniden yüklerse tarayıcının adres çubuğunun içeriği korunur.

yönergesiyle @page URL desenlerini tanımlama hakkında bilgi için bkz . ASP.NET Çekirdek Blazor yönlendirme ve gezinti.

Tarayıcı depolama alanı

Kullanıcının etkin olarak oluşturduğu geçici veriler için yaygın olarak kullanılan depolama konumu tarayıcının localStorage ve sessionStorage koleksiyonlarıdır:

  • localStorage, tarayıcının belirli örneğiyle sınırlıdır. Kullanıcı sayfayı yeniden yüklerse veya tarayıcıyı kapatıp yeniden açarsa durum devam eder. Kullanıcı birden çok tarayıcı sekmesi açarsa, durum sekmeler arasında paylaşılır. Veriler, açıkça temizlenene kadar localStorage'da kalır. "Özel gözatma" veya "gizli" oturumda yüklenen bir belgenin localStorage verileri, son "özel" sekme kapatıldığında temizlenir.
  • sessionStorage kapsamı tarayıcı sekmesine göre belirlenmiştir. Kullanıcı sekmeyi yeniden yüklerse durum devam eder. Kullanıcı sekmeyi veya tarayıcıyı kapatırsa durum kaybolur. Kullanıcı birden çok tarayıcı sekmesi açarsa, her sekmenin kendi bağımsız veri sürümü vardır.

Not

localStorage ve sessionStorage uygulamalarda yalnızca özel kod yazarak veya bir üçüncü taraf paketi kullanarak kullanılabilir Blazor WebAssembly .

sessionStorage Genellikle kullanımı daha güvenlidir. sessionStorage kullanıcının birden çok sekme açması ve aşağıdakilerle karşılaşması riskini önler:

  • Sekmeler arasında durum depolamadaki hatalar.
  • Bir sekmenin, diğer sekmelerin durumunu değiştirmesi kafa karıştırıcı bir davranış.

localStorage , uygulamanın tarayıcıyı kapatma ve yeniden açma işlemi boyunca durumu kalıcı hale döndürmesi gerekiyorsa daha iyi bir seçenektir.

Uyarı

Kullanıcılar ve localStorageiçinde sessionStorage depolanan verileri görüntüleyebilir veya üzerinde değişiklik yapabilir.

Hafıza tabanlı durum yönetimi hizmeti

İç içe bileşenler, genellikle ASP.NET Core veri bağlamasında açıklandığı gibi zincirlenmiş bağlama kullanarak verileri bağlar. İç içe olan ve olmayan bileşenler, kayıtlı bellek içi durum kapsayıcısı kullanarak veri erişimini paylaşabilir. Özel durum kapsayıcı sınıfı, uygulamanın farklı bölümlerindeki bileşenlere durum değişikliklerini bildirmek için atanabilir Action kullanabilir. Aşağıdaki örnekte:

  • İki bileşenden oluşan bir yapı, bir özelliği izlemek için bir durum kapsayıcı kullanır.
  • Aşağıdaki örnekteki bir bileşen diğer bileşende iç içe yerleştirilmiştir, ancak bu yaklaşımın çalışması için iç içe yerleştirme gerekli değildir.

Önemli

Bu bölümdeki örnekte bellek içi durum kapsayıcı hizmetinin nasıl oluşturulacağı, hizmetin nasıl kaydedilacağı ve hizmetin bileşenlerde nasıl kullanılacağı gösterilmektedir. Örnek, daha fazla geliştirme yapılmadan verileri kaydetmez. Verilerin kalıcı olarak depolanması için durum kapsayıcısının tarayıcı belleği temizlendiğinde devam eden temel bir depolama mekanizması benimsemesi gerekir. Bu, veya başka bir teknolojiyle localStorage/sessionStorage gerçekleştirilebilir.

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

İstemci tarafı uygulamaları (Program dosya):

builder.Services.AddSingleton<StateContainer>();

Sunucu tarafı uygulamalar (Program .NET 6 veya sonraki sürümlerde dosya, ASP.NET Core):

builder.Services.AddScoped<StateContainer>();

Sunucu tarafı uygulamaları (Startup.ConfigureServicesStartup.cs .NET 6 veya önceki sürümlerinde):

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

Önceki bileşenler IDisposable uygular ve bileşenler atıldığında çerçeve tarafından çağrılan OnChange yöntemlerinde Dispose temsilcilerin abonelikten çıkarılması sağlanır. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşen imhası.

Değerleri ve parametreleri basamaklandırma

Bir ata bileşeninden alt bileşenlere veri taşımak yoluyla durumu yönetmek için Razor parametreleri kullanın.

CascadingValueSource<TValue> olan kök düzeyinde basamaklı değerler, değiştirilen basamaklı değerlerin bileşen abone bildirimleri Razor izin verir. Daha fazla bilgi ve çalışan bir örnek için NotifyingDalek no'lu örneğe, ASP.NET Core Blazor parametreler ve basamaklı değerlerebakın.

Ek yaklaşımlar

Özel durum depolaması uygularken, basamaklı değerleri ve parametreleri benimsemek yararlı bir yaklaşımdır:

  • Birçok bileşende durumu tüketmek için.
  • Kalıcı olarak yalnızca bir üst düzey durum nesnesi varsa.

Sorun giderme

Blazoreşitleme bağlamı dışından durum değişikliklerini desteklemek istediğiniz bir özel durum yönetimi hizmeti kullanırken (örneğin, zamanlayıcı veya arka plan hizmetinden), tüm tüketen bileşenler StateHasChanged çağrısını ComponentBase.InvokeAsynciçinde sarmalamalıdır. Bu, değişiklik bildiriminin işleyicinin eşitleme bağlamında işlenmesini sağlar.

Durum yönetimi hizmeti StateHasChanged eşitleme bağlamında Blazor'ı çağırmazsa, aşağıdaki hata oluşur:

System.InvalidOperationException: 'Geçerli iş parçacığı Dispatcher (yönetici) ile ilişkili değil. İşleme veya bileşen durumunu tetiklerken yürütmeyi Dispatcher'a geçmek için InvokeAsync() kullanın.'

Bu hatayı giderme hakkında daha fazla bilgi ve örnek için bkz . ASP.NET Core Razor bileşeni işleme.

Ek kaynaklar