Local storage

🟨 Slightly different to Blazor WebAssembly

Local storage is a convenient and efficient way to store a small amount of data on the client-side, which can be easily accessed and updated by a web application.

  • What is Local storage?
  • Comparing local storage access methods in Blazor Server.
  • Accessing local storage using ProtectedLocalStorage.
  • Accessing local storage using JavaScript API.
  • Key differences between Blazor WebAssembly and Blazor Server.
You can download the example code used in this topic on GitHub.

What is Local storage?

Local storage is a modern technique that allows developers to store data in a key-value pair format. It can be thought of as a persistent browser dictionary with string-based keys and values. If non-string data is entered, it will be automatically converted to a string. For instance, if the key/value is set as the number 1, local storage will store it as a string "1". Data in local storage is isolated by domain, meaning that one domain cannot access another domain's resources. For instance, data created by blazorschool.com cannot be accessed by google.com and vice versa.

How to access the Local storage in the browser?

In Firefox, you can find the Local storage under the Storage tab, as shown in the image below:

firefox-local-storage.png

In Chrome and Edge, you can find the Local storage under the Application tab, as shown in the images below:

chrome-local-storage.png

edge-local-storage.png


Comparing local storage access methods in Blazor Server

Blazor Server provides two methods for accessing local storage: ProtectedLocalStorage and JavaScript API.

  • ProtectedLocalStorage is a built-in function that encrypts data before storing it. This means that data stored using this approach can only be retrieved using ProtectedLocalStorage and cannot be decrypted by other Blazor Server projects, even within the same domain. However, ProtectedLocalStorage does not provide an option to retrieve or delete all the data stored in local storage at once.
  • JavaScript API, on the other hand, allows you to access local storage using JavaScript. Data stored using this approach is not encrypted and can be retrieved by other Blazor Server projects within the same domain. Additionally, JavaScript API provides the ability to retrieve or delete all the data stored in local storage at once.

Accessing local storage using ProtectedLocalStorage

To use ProtectedLocalStorage, you can inject it into your Blazor Server component and call its methods. For example:

@inject ProtectedLocalStorage ProtectedLocalStorage

<form>
    <label>
        Key
        <input type="text" @bind-value="Key" />
    </label>
    <label>
        Value
        <input type="text" @bind-value="Value" />
    </label>
    <button type="button" @onclick="SetValueAsync">Set Value</button>
</form>
<div>Stored Value: @StoredValue</div>
<button type="button" @onclick="GetValueAsync">Get Value</button>
<button type="button" @onclick="RemoveAsync">Remove Value</button>

@code {
    public string Key { get; set; } = "";
    public string Value { get; set; } = "";
    public string StoredValue { get; set; } = "";

    public async Task SetValueAsync()
    {
        await ProtectedLocalStorage.SetAsync(Key, Value);
    }

    public async Task GetValueAsync()
    {
        var result = await ProtectedLocalStorage.GetAsync<string>(Key);
        StoredValue = result.Success ? result.Value! : "Failed to fetch result";
    }

    public async Task RemoveAsync()
    {
        await ProtectedLocalStorage.DeleteAsync(Key);
    }
}

Accessing local storage using JavaScript API

Another way to access local storage in Blazor Server is through JavaScript API.

Set up the base code

To use local storage in Blazor Server, you can create a JavaScript module and call its exported functions using C# code. Here are the steps:

  1. Create a new JavaScript file under the wwwroot folder. For example, you can create a file named /js/LocalStorageAccessor.js.
  2. Create a C# class with the following base implementation:
public class LocalStorageAccessor : IAsyncDisposable
{
    private Lazy<IJSObjectReference> _accessorJsRef = new();
    private readonly IJSRuntime _jsRuntime;

    public LocalStorageAccessor(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public async Task<T> GetValueAsync<T>(string key)
    {
        await WaitForReference();
        var result = await _accessorJsRef.Value.InvokeAsync<T>("get", key);

        return result;
    }

    public async Task SetValueAsync<T>(string key, T value)
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("set", key, value);
    }

    public async Task Clear()
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("clear");
    }

    public async Task RemoveAsync(string key)
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("remove", key);
    }

    private async Task WaitForReference()
    {
        if (_accessorJsRef.IsValueCreated is false)
        {
            _accessorJsRef = new(await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "/js/LocalStorageAccessor.js"));
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (_accessorJsRef.IsValueCreated)
        {
            await _accessorJsRef.Value.DisposeAsync();
        }
    }
}
  1. Register the IndexedDbAccessorclass in the Program.cs file:
builder.Services.AddScoped<LocalStorageAccessor>();

Add common operations

In this section, we will demonstrate how to perform basic Local storage operations in JavaScript and C#. With the provided code, you can easily store, get, and delete data from the Local. Additionally, you can customize the code to add your own operations as well.

  1. To store, get and delete data, add the following functions to your JavaScript module:
export function get(key)
{
    return window.localStorage.getItem(key);
}

export function set(key, value)
{
    window.localStorage.setItem(key, value);
}

export function clear()
{
    window.localStorage.clear();
}

export function remove(key)
{
    window.localStorage.removeItem(key);
}
  1. To use these operations in your C# class, add a method for each operation, and call WaitForReference() in all of them. Here is an example implementation:
public class LocalStorageAccessor : IAsyncDisposable
{
    ...
    public async Task<T> GetValueAsync<T>(string key)
    {
        await WaitForReference();
        var result = await _accessorJsRef.Value.InvokeAsync<T>("get", key);

        return result;
    }

    public async Task SetValueAsync<T>(string key, T value)
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("set", key, value);
    }

    public async Task Clear()
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("clear");
    }

    public async Task RemoveAsync(string key)
    {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("remove", key);
    }
}

Use the LocalStorageAccessor

Once you have completed all the previous steps, you can use the LocalStorageAccessor as follows:

@inject LocalStorageAccessor LocalStorageAccessor

<form>
    <label>
        Key
        <input type="text" @bind-value="Key" />
    </label>
    <label>
        Value
        <input type="text" @bind-value="Value" />
    </label>
    <button type="button" @onclick="SetValueAsync">Set Value</button>
</form>
<div>Stored Value: @StoredValue</div>
<button type="button" @onclick="GetValueAsync">Get Value</button>
<button type="button" @onclick="RemoveAsync">Remove Value</button>
<button type="button" @onclick="ClearAllAsync">Clear All</button>

@code {
    public string Key { get; set; } = "";
    public string Value { get; set; } = "";
    public string StoredValue { get; set; } = "";

    public async Task SetValueAsync()
    {
        await LocalStorageAccessor.SetValueAsync(Key, Value);
    }

    public async Task GetValueAsync()
    {
        StoredValue = await LocalStorageAccessor.GetValueAsync<string>(Key);
    }

    public async Task RemoveAsync()
    {
        await LocalStorageAccessor.RemoveAsync(Key);
    }

    public async Task ClearAllAsync()
    {
        await LocalStorageAccessor.Clear();
    }
}

Key differences between Blazor WebAssembly and Blazor Server

In Blazor WebAssembly, you cannot use ProtectedLocalStorage. However, you can use the InertopServices.JavaScript to interact with the local storage through the JavaScript API.

BLAZOR SCHOOL
Designed and built with care by our dedicated team, with contributions from a supportive community. We strive to provide the best learning experience for our users.
Docs licensed CC-BY-SA-4.0
Copyright © 2021-2024 Blazor School
An unhandled error has occurred. Reload 🗙