Local storage is an internal database created into the browser, which you can use to save data in a key-value format. The data stored in local storage has no expiration date and will persist until the user decides to delete it.
This guide describes how to manage the data from local storage.
You can download the example code used in this topic on GitHub.
ProtectedLocalStorage
ProtectedLocalStorage
is a built-in class that allows programmers to manage local storage. The data stored by ProtectedLocalStorage
is encrypted but at the cost of incrementing the size of the data. Local storage has a limit of 5MB per site unless the user wants more.
ProtectedLocalStorage
only available on the client side. If you use ProtectedLocalStorage
on any server life cycle methods like OnInitialized()
you will get an error. Look at Lifecycle event sequence table to see what lifecycle methods are triggered by the client side.
ProtectedLocalStorage
in a componentTo use ProtectedLocalStorage
in a component, you need to inject it in the directive section of the component.
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @inject ProtectedLocalStorage ProtectedLocalStorage
ProtectedLocalStorage
in a serviceTo use ProtectedLocalStorage
in a service, you need to inject it in the constructor of the service.
public class <Class Name> { private readonly ProtectedLocalStorage _protectedLocalStorage; public <Class Name>(ProtectedLocalStorage protectedLocalStorage) { _protectedLocalStorage = protectedLocalStorage; } }
To store data in local storage, you need to call the method SetAsync(key, value)
of ProtectedLocalStorage
. In our example, we have set up a form to store data to the local storage.
<form> <div> <label>Key: <input type="text" @bind-value="LocalStorageKey" /></label> </div> <div> <label>Value: <input type="text" @bind-value="LocalStorageValue" /></label> </div> <div> <button type="button" @onclick="StoreKeyAsync">Store Key</button> </div> </form> @code { public string LocalStorageKey { get; set; } public string LocalStorageValue { get; set; } private async Task StoreKeyAsync() { await ProtectedLocalStorage.SetAsync(LocalStorageKey, LocalStorageValue); } }
To retrieve data from local storage, you need to call the method GetAsync(key)
of ProtectedLocalStorage
. In our example, we have set up a form to get the data from local storage.
<form> <div> <label>Key: <input type="text" @bind-value="LocalStorageQueryKey" /></label> </div> <div> <button type="button" @onclick="GetValueAsync">Get Value</button> </div> <div>Value: @LocalStorageQueryValue</div> </form> @code { public string LocalStorageQueryKey { get; set; } public string LocalStorageQueryValue { get; set; } private async Task GetValueAsync() { var result = await ProtectedLocalStorage.GetAsync<string>(LocalStorageQueryKey); if (result.Success) { LocalStorageQueryValue = result.Value; } } }
If you use the ProtectedLocalStorage
to store the data then you can only use ProtectedLocalStorage
to retrieve the value back because the actual data stored in the browser will be encrypted.
SetAsync(purpose, key, value)
of ProtectedLocalStorage
. The purpose
parameter is important as it will be used to retrieve the key later on. You can reuse the previous example and change the SetAsync
method as:... private async Task StoreKeyAsync() { await ProtectedLocalStorage.SetAsync("login", LocalStorageKey, LocalStorageValue); }
To retrieve the data in scope, you need to call the method GetAsync(purpose, key)
of ProtectedLocalStorage
.
... private async Task GetValueAsync() { ProtectedBrowserStorageResult<string> result = new(); try { result = await ProtectedLocalStorage.GetAsync<string>("login", LocalStorageQueryKey); } catch { } finally { LocalStorageQueryValue = result.Success ? result.Value : "Not success."; } }
Anytime you are accessing the scoped local storage, you should wrap it in a try catch block because if you don't, Blazor Server will emit an error Error: System.Security.Cryptography.CryptographicException: The payload was invalid
and stop the website.
DeleteAsync(key)
of ProtectedLocalStorage
. Deleting a key does not distinguish if the data is scoped data or not.Although you can use ProtectedLocalStorage
to access local storage, you can also use JavaScript to access the local storage. There are several advantages when using JavaScript to deal with local storage, some of them are:
JavaScript is only available on the client side. If you use JavaScript on any server life cycle methods like OnInitialized()
you will get an error. Look at Lifecycle event sequence table to see what lifecycle methods are triggered by the client side. The following are the steps for using JavaScript to manage local storage, it does not cover how to interact with JavaScript in Blazor Server. For understand how to interact with JavaScript, look at JavaScript Interaction.
BlazorUtil.js
file under folder wwwroot/js
.class BlazorUtil { getAllStorage() { return Object.entries(localStorage); }; } window.BlazorUtil = new BlazorUtil();
BlazorUtil.js
file in _Host.cshtml
.IJSRunTime
into the component or the service.To store the data in local storage, call the setItem(keyName, keyValue)
of the localStorage
. In our example, we have set up a form to store data to the local storage.
<form> <div> <label>Key: <input type="text" @bind-value="LocalStorageKey" /></label> </div> <div> <label>Value: <input type="text" @bind-value="LocalStorageValue" /></label> </div> <div> <button type="button" @onclick="StoreKeyAsync">Store Key</button> </div> </form> @code { public string LocalStorageKey { get; set; } public string LocalStorageValue { get; set; } private async Task StoreKeyAsync() { await JSRuntime.InvokeVoidAsync("localStorage.setItem", LocalStorageKey, LocalStorageValue); } }
To retrieve the data in local storage, call the getItem(keyName)
of the localStorage
. In our example, we have set up a form to retrieve data from the local storage.
<form> <div> <label>Key: <input type="text" @bind-value="LocalStorageQueryKey" /></label> </div> <div> <button type="button" @onclick="GetValueAsync">Get Value</button> <button type="button" @onclick="DeleteValueAsync">Delete Key</button> </div> <div>Value: @LocalStorageQueryValue</div> </form> @code { public string LocalStorageQueryKey { get; set; } public string LocalStorageQueryValue { get; set; } private async Task GetValueAsync() { LocalStorageQueryValue = await JSRuntime.InvokeAsync<string>("localStorage.getItem", LocalStorageQueryKey); } private async Task DeleteValueAsync() { await JSRuntime.InvokeAsync<string>("localStorage.removeItem", LocalStorageQueryKey); } }
To retrieve all the data in the local storage is a bit different because in .NET 5, Blazor Server is not supporting for referring JavaScript objects, you have to use the method we have created BlazorUtil.js
. In our example, we have created a form to demonstrate the feature.
<div> <div>All local storage data:</div> <button type="button" @onclick="GetAllLocalStorageDataAsync">Refresh</button> <button type="button" @onclick="ClearAllDataAsync">Clean All</button> @foreach (KeyValuePair<string, string> keyValuePair in AllData) { <div>@keyValuePair.Key: @keyValuePair.Value</div> } </div> @code { public Dictionary<string, string> AllData { get; set; } = new(); private async Task GetAllLocalStorageDataAsync() { var jsonElement = await JSRuntime.InvokeAsync<JsonElement>("BlazorUtil.getAllStorage"); var enumerator = jsonElement.EnumerateArray(); AllData.Clear(); while (enumerator.MoveNext()) { var keyValue = JsonConvert.DeserializeObject<List<string>>(enumerator.Current.GetRawText()); AllData.Add(keyValue[0], keyValue[1]); } } private async Task ClearAllDataAsync() { await JSRuntime.InvokeVoidAsync("localStorage.clear"); } }