Store Data of Your Blazor App in the Local Storage and in the Session Storage

To store local data, today’s browsers support a local storage and a session storage. The difference between the two is that the session storage is only available per tab, and the stored data is deleted once you close the tab with the application. The local storage on the other side stores data across sessions. Even when you close the browser and when you re-open it again, the data of the local storage is still there. It will be there as long until you delete it.

So, the difference between the two is how long the data is stored. Beside that, they work exactly the same. Both can store key/value pairs, and those key/value pairs are stored in plain text.

In this blog post, let’s look at how to use the local storage and the session storage in your Blazor App.

In the first Blazor versions, you had to use JavaScript Interop to add or remove key/value pairs from the local storage or from the session storage. By default, both storages store the data in plain text, and a user can open the developer tools of their browser to view the data. This means that if you want to store sensible data, you have to protect it.

To help you with all of this, Microsoft released a preview of the NuGet package Microsoft.AspNetCore.ProtectedBrowserStorage that helps you to store protected data in the local storage and also in the session storage. With the release candidate of .NET 5.0, they renamed the NuGet package to Microsoft.AspNetCore.Components.ProtectedBrowserStorage, and with the release of .NET 5.0, they included the functionality directly in .NET 5.0.

But note: That functionality relies on ASP.NET Core data protection, which is only available on the server, but not in the client. This means for you that you can use it in a Blazor Server App, but not in a Blazor WebAssembly App (see also this GitHub issue here and here the official docs)

That means for you: If you want to use the classes from Microsoft in your Blazor Server app to store data in the local storage or in the session storage, you don’t have to add a reference to a NuGet package. Everything is already available by default in your Blazor Server app. Let’s look at this.

How to Use the Local Storage

Let’s create a brand-new Blazor Server App with .NET 5.0. Replace the code in the Index.razor file with the code that you see in the following code snippet. Note at the top the using directive for the namespace Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage. This namespace contains the ProtectedLocalStorage class that gets injected into the index component with the @inject directive. The instance is stored in a BrowserStorage property.

The component contains an input field and three buttons to save, read, and delete the the data of that input field to/from the local storage. In the code block you can see in the Save method how the method SetAsync is used to store the string from the input field under the key name in the local storage. In the Read method the GetAsync method is used to read the value of the name key from the local storage. In the Delete method, the key name and its value are deleted from the local storage.

@page "/"
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedLocalStorage BrowserStorage

<h1>Local Storage!</h1>

<input class="form-control" @bind="currentInputValue" />
<button class="btn btn-secondary" @onclick="Save">Save</button>
<button class="btn btn-secondary" @onclick="Read">Read</button>
<button class="btn btn-secondary" @onclick="Delete">Delete</button>

@code {
  string currentInputValue;

  public async Task Save()
  {
    await BrowserStorage.SetAsync("name", currentInputValue);
  }

  public async Task Read()
  {
    var result = await BrowserStorage.GetAsync<string>("name");
    currentInputValue = result.Success ? result.Value : "";
  }

  public async Task Delete()
  {
    await BrowserStorage.DeleteAsync("name");
  }
}

That’s it. So, add the above to the Index.razor file of a new Blazor Server app, and then run the application. Enter something into the input field and click the Save button. In the screenshot below I entered the text Thomas, I clicked the Save button, and then I opened the developer tools. Under the Application tab you can see the local storage and also the session storage. As you can see, in the local storage under the key name the value Thomas is stored. But you can’t see that it’s the value Thomas, as it is protected. Now, when you remove the text from the input field and when you click the Read button, the value Thomas is read from the local storage, and the input field will display it again. Also close the browser and start the application again, then you’ll see that the data in the local storage is still there, and you can click the Read button to read it into the input field.

How to Use the Session Storage

Using the Session Storage works exactly the same way. Just take the code snippet from above, and instead of injecting the ProtectedLocalStorage class, you inject the ProtectedSessionStorage class:

@inject ProtectedSessionStorage BrowserStorage

That’s it! Both classes have the same public APIs, as they both inherit from the base class ProtectdBrowserStorage. That base class defines the methods SetAsync, GetAsync, and DeleteAsync.

Behind the scences, JavaScript Interop is used to access the browser’s storage. When you look for example at the constructor of the ProtectedLocalStorage class, you can see that it has an IJSRuntime parameter:

public ProtectedLocalStorage(IJSRuntime jsRuntime, IDataProtectionProvider dataProtectionProvider);

Luckily all these constructor parameters are injected for you when you use Blazor’s dependency injection with the @inject directive like we did in this blog post.

Use Browser Storage in Blazor WebAssembly

As mentioned, in Blazor WebAssembly you can’t use those classes to access the local storage and the session storage, as they depend on ASP.NET Core data protection, which is a server-side technology.

In Blazor WebAssebmly, you have to use JavaScript Interop – or you can reference a third-party NuGet package that wraps that JavaScript Interop code for you.

In the following code snippet I use the IJSRuntime to access the localStorage JavaScript API of the browser to store data. You can create a new Blazor WebAssembly app and you can replace the code of your Index.razor component with the following code to play around with it. The following code would also work in a Blazor Server app.

@page "/"
@inject IJSRuntime JSRuntime  

<h1>Local Storage!</h1>

<input class="form-control" @bind="currentInputValue" />
<button class="btn btn-secondary" @onclick="Save">Save</button>
<button class="btn btn-secondary" @onclick="Read">Read</button>
<button class="btn btn-secondary" @onclick="Delete">Delete</button>

@code {
  string currentInputValue;

  public async Task Save()
  {
    await JSRuntime.InvokeVoidAsync("localStorage.setItem", "name", currentInputValue);
  }

  public async Task Read()
  {
    currentInputValue = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "name");
  }

  public async Task Delete()
  {
    await JSRuntime.InvokeAsync<string>("localStorage.removeItem", "name");
  }
}

Note that the code snippet above does not protect your data. In the screenshot below you can see that the value Thomas is visibile in plain text in the developer tools of the browser. Be aware of this. Depending on the data that you are storing in the local storage, this can be a problem or not.

Of course, you can wrap the JavaScript Interop code to access the local storage for example in a service class that you inject into your Blazor component. If you want to learn how to do this and if you want to learn more about JavaScript Interop in Blazor applications, please take a look at my Pluralsight course:

Pluralsight course
JavaScript Interop in Blazor applications

Happy coding,
Thomas

Share this post

Comments (3)

  • Guillermo J Perez Reply

    Excellent teacher! yes, my confusion was between ProtectedBrowserStorage and the one injected, in this case ProtectedLocalStorage. The example is very clear, I did a test and it works! fantastic, love your explanation, clear. Thank you so much!

    April 23, 2021 at 8:48 pm
  • Ben Junior Reply

    Nice article. Simple, direct and complete with the necessary details/comments.

    July 21, 2021 at 11:06 pm

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.