100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

Local Storage and Session Storage

Persist Blazor app state in the browser using localStorage and sessionStorage via JS interop or community libraries.

State & ServicesIntermediate8 min readJul 10, 2026
Analogies

Why Persist State to Browser Storage

Blazor components lose all in-memory state on a full page reload in WebAssembly, and Blazor Server loses circuit state entirely if the SignalR connection drops and can't reconnect, so persisting anything that should survive those events, like a user's theme preference or a partially filled form, requires writing it into the browser's storage APIs rather than keeping it only in a C# field. Blazor has no native storage API, so this always goes through JavaScript interop, either hand-written or via a NuGet package like Blazored.LocalStorage.

🏏

Cricket analogy: A scorer who only keeps the tally on a chalkboard loses everything if rain washes it away mid-match, just as a Blazor component's in-memory state vanishes on reload unless it's written somewhere durable like localStorage.

localStorage vs. sessionStorage

localStorage persists key-value string data with no expiration until explicitly cleared, and it's shared across every tab and window for the same origin, making it right for durable preferences like theme or language. sessionStorage is scoped to a single browser tab and is cleared the moment that tab closes, even if the same page is reopened in a new tab, which makes it appropriate for data that should not survive beyond the current visit, like a multi-step form's in-progress draft.

🏏

Cricket analogy: A player's career batting average is recorded permanently in the official records regardless of which match you're watching, like localStorage persisting across every tab; a single innings' live scorecard resets each new match, like sessionStorage resetting per tab.

Accessing Browser Storage from Blazor

Because browser storage APIs are JavaScript, not .NET, Blazor reaches them through IJSRuntime.InvokeAsync, calling a small JS function like localStorage.setItem(key, value) that you either hand-write in a wwwroot .js file or install via the Blazored.LocalStorage package, which wraps that interop in an injectable ILocalStorageService with typed GetItemAsync<T> and SetItemAsync<T> methods. Blazor Server code must additionally guard against calling storage during prerendering, since there's no browser JS runtime available until the SignalR circuit actually connects.

🏏

Cricket analogy: A team's video analyst can't request footage from the broadcaster's system until the satellite uplink is actually connected, similar to how Blazor Server can't call JS interop for localStorage until the SignalR circuit connects after prerendering.

javascript
// wwwroot/storageInterop.js
window.storageInterop = {
    setItem: (key, value) => localStorage.setItem(key, value),
    getItem: (key) => localStorage.getItem(key)
};
csharp
@inject IJSRuntime JS
@inject Blazored.LocalStorage.ILocalStorageService LocalStorage

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var theme = await JS.InvokeAsync<string>("storageInterop.getItem", "theme");
            currentTheme = theme ?? "light";

            draftForm = await LocalStorage.GetItemAsync<CheckoutDraft>("checkout-draft")
                        ?? new CheckoutDraft();

            StateHasChanged();
        }
    }

    private async Task SaveDraftAsync()
        => await LocalStorage.SetItemAsync("checkout-draft", draftForm);
}

Storage calls should only happen after the component has actually rendered, since IJSRuntime.InvokeAsync requires a live browser JS environment: use OnAfterRenderAsync(firstRender) in Blazor Server, or note that Blazor WASM has no prerendering step by default so storage calls in OnInitializedAsync generally work fine there.

Both localStorage and sessionStorage store plain, unencrypted strings that are fully readable by any script running on the page or through the browser's dev tools, so sensitive data like auth tokens or personal information should never be stored there without additional encryption, and ideally should use an httpOnly cookie instead.

  • localStorage persists indefinitely across tabs and browser restarts until explicitly cleared
  • sessionStorage is scoped to one tab and clears when that tab closes
  • Blazor has no native storage API; access always goes through JS interop via IJSRuntime
  • Blazored.LocalStorage wraps interop in a typed, injectable ILocalStorageService
  • Blazor Server must wait for the SignalR circuit to connect before storage calls succeed (no interop during prerendering)
  • Storage data is plain-text and readable via browser dev tools — never store secrets there unencrypted
  • OnAfterRenderAsync(firstRender) is the safe place for storage calls in Blazor Server components

Practice what you learned

Was this page helpful?

Topics covered

#BlazorStudyNotes#MicrosoftTechnologies#LocalStorageAndSessionStorage#Local#Storage#Session#Persist#StudyNotes#SkillVeris#ExamPrep