How To Work With The Browser's Local Storage in Blazor
Tags: dotnet, csharp, webdev, tutorial
Published: 2023-09-15 18:19:12

## Introduction 👋🏻
If you've used the browser's dev tools, you have probably seen the **Storage** tab, this is a storage mechanism that allows websites to store data in the browser's storage. There're different types of storages in the browser, those types are: **Cookies Storage**, **Session Storage** and **Local Storage**, we're interested in the last one.

## What's The Local Storage? 💽
The local storage can store large amounts of data, and the data it can store varies, from user preferences, language used in the website, theme, and more complex things such as persisting form data, which means the data will be cached and can be retrieved if the application was closed unintentionally, or maybe the user closed the browser by accident, now that's a different topic, called **State Management**, so for the time being, we'll focus on how we can interact with the local storage from a **Blazor Application**.

## How is Data Stored in Local Storage? ⚙️
Data is stored as **key-value pairs**, the data is saved in the browser and is specific to the website that created it, so if a website stored for instance, a language code in the local storage, and you navigated to another website, that language code will not be there anymore until you navigate back to the original application that had created it.

## Working With The Local Storage From Blazor
When Blazor was immature and young, the task of working with the local storage required developers to write **JavaScript**   to interact with the browser's local storage. However, Blazor is more grown right now, and thanks to community developed packages, we can now reach the local storage with only C# code.

## Setting up The Project 🧠
If you want to follow along, then go through the following steps:
**1:** Create An Empty Blazor WebAssembly Project

> **💡 NOTE:** The same code works for **Blazor Server** as well, so if you want to go with that project type, it's also fine.

**2:** Download the package **Blazored.LocalStorage**.
To do that, use on of the following methods:

- .NET CLI Command:

```csharp

dotnet add package Blazored.LocalStorage --version 4.4.0

```

- NuGet Package Manager Console:

```csharp

NuGet\Install-Package Blazored.LocalStorage -Version 4.4.0

```

- NuGet Package Manager:
You can use NPM's GUI if you're using Vs for Windows or Vs for Mac

**3:** Register the service in DI container.
We want to inject instances of the **ILocalStorageServices** into the components where we want to access the local storage, so inside **Program.cs**, add this line:

```csharp

builder.Services.AddBlazoredLocalStorage();

```

> **💡 NOTE:** Make sure to import `Blazored.LocalStorage` at the top of **Program.cs** so you can access the method to register the service.

And we're all done for the set up, now we can do some operations with the local storage from our Blazor Application

## Adding an Item To The Local Storage
Inside **Index.razor**, we'll override the virtual method `OnInitializedAsync` to add a string message inside the local storage:

```csharp

@page "/"
@inject ILocalStorageService LocalStorage

<h1>@message</h1>

@code {
    private string message = "";
    protected override async Task OnInitializedAsync()
    {
        await LocalStorage.SetItemAsStringAsync("message", "Hello World!");
        message = await LocalStorage.GetItemAsStringAsync("message");
    }
}

```

Let's walk through the code now.
**Firstly**, I'm injecting an instance of `ILocalStorageService` into the component, I'm calling it **LocalStorage**, this instance will provide us with methods to set items and retrieve data from the local storage.

**Secondly**, inside the code directory, I'm creating a variable called message of type string, the reason for this is because I want the string to be fetched from the local storage, and set to the variable `message` therefore I can display it in an **h1**.

**Thirdly**, inside `OnInitializedAsync`, I'm calling the method `SetItemAsStringAsync`, this method is very intuitive, it takes two arguments, the key name, and the value, in that context, we're storing a string value, that has a key named **message**.

**Lastly**, I'm reaching out to the local storage to retrieve the message value by using `GetItemAsStringAsync`, this method takes a single argument, that is the name of the key whose value is what we want to retrieve.

If you run the application now, and navigate to the storage tab, click on Local Storage, you should see something similar to this:

![Preview of local storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0u6fx1zt22b3t1ct29p.png)

## Storing Complex Objects 🥸
So far we've worked with setting and getting merely string items, which is great, but we can do more than that! Say you want to store a whole object for example, you might want to use `SetItemAsync<T>`, this method is generic, and **T** is the type of object you want to store. Here's a code example to help you better understand this idea:

```csharp

@code {
    private Person bob = new()
    {
        FirstName = "Bob",
        LastName = "Smith"
    };
    protected override async Task OnInitializedAsync()
    {
        await LocalStorage.SetItemAsync<Person>("bob", bob);
    }

    private class Person
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
    }
}

```

> **💡 NOTE:** When you set an object in the local storage, it gets serialized into a string using **JSON format**, and when you want to retrieve it, it gets the string which is then deserialized into a **C# object**.

The result should look like this:

![Storing objects in the local storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2aatkpvm9n7ssqlnsra1.png)

If you want to get the object, you can call `GetItemAsync<T>`, where again **T** is the type to deserialize the object into, in the case of our previous example, it's **Person**.

## Checking If A Key Exists In The Local Storage
In many cases, you want to check if there's already an existing entry in the local storage, I'll give you a real world example:
If you are using **Token Based Authentication** in your project, then there'll be a **Json Web Token** which will be used to hold the claims of the user, and that token should be sent along with every request the user makes inside the application to show that they're authorized, the token should be stored in the local storage, so what you can do, you can check if it exists there, if it does, you get it and read its claims to create the user's identity and so on, this way you know that the user is authenticated, so how do you check if the local storage contains a particular item?

Using a method called **ContainsKeyAsync**, this method takes a key name as a parameter, a string, and it checks if the local storage does in fact contain that key or not, if so, returns true, and false otherwise.

We'll use our friend **Bob** from the previous example to see this method in action.
When the index page gets initialized, I want to check if Bob is there or not, and display a message based on that:

```csharp

<h1>@bobState</h1>

@code {
    private string bobState = "";
    private Person bob = new()
    {
        FirstName = "Bob",
        LastName = "Smith"
    };
    protected override async Task OnInitializedAsync()
    {
        await LocalStorage.SetItemAsync<Person>("bob", bob);

        if (await LocalStorage.ContainKeyAsync("bob"))
        {
            bobState = "Bob is HERE!";
        }
        else
        {
            bobState = "Bob is no where to be found :-(";
        }
    }
    // removed for brevity
}

```

Since we're first adding **Bob** to the local storage every time the page is initialized, we should see **Bob is HERE!** printed on the page. However, if we removed **Bob** before doing the check, we should see a different message, do this by adding the following line after the line that adds Bob to the local storage:

```csharp

 await LocalStorage.RemoveItemAsync("bob");

```
I guess this is pretty much self explanatory, the output now will change to this:

![Removing Bob from the local storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7t6gnz70cg2oatjol1lv.png)

## Practice Project 🏗️
Perhaps a nice practice can be theming, try to implement a way the user can change the color of the background, and make it a persisted change that even if the project was stopped, the color will remain there in the storage so when the app is reopened, the background color gets set to the color the user chose before closing the application.

## Conclusion ✅
In this post, we discovered how we can interact with the browser's local storage by using a third party package, we've looked at how to setup the service and access it from every component where it's needed, and we've fiddled around with the main methods it provides, we wrote, read, and also removed data from the local storage all by writing pure C# code, I highly encourage you to dive deeper and play around with the package to see what else you can do. Good Luck!










....