WebAssembly Blazor: local storage


In this post, we discuss an example of a WebAssembly Blazor application using the browser’s local storage.

We create a dummy Login page that stores the authentication state persistently in the local storage. Of course, because this is a dummy Login page no real authentication happens here, we just want to demonstrate how we can use the local storage of the browser to persistently store something, in this case, the state of our pseudo dummy authentication.

We expect the dummy authentication state to be persistent meaning that once we click on the Login button, the state of authentication is set to true and remains true even if change the page by selecting another menu item.

Create a default WebAssembly Blazor application using VS 2022.

Add the new razor page DummyLoginPage.razor to the pages folder.

Add the Login page to the navigation menu:

Shared/NavMenu.razor:

...
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="DummyLoginPage">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Login
            </NavLink>
        </div>
    </nav>
</div>

...

Add the following code to DummyLoginPage.razor:

@page "/DummyLoginPage"

@inject HttpClient Http
@inject IJSRuntime jsr

<PageTitle>Login</PageTitle>

<h1>Login</h1>

@if (!_isAuthenticated)
{
    <table>
        <tr>
            <td>Login:</td>
            <td><input Id="idLogin" @bind="_login" /></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input Id="idPassword" @bind="_password" /></td>
        </tr>
        <tr>
            <td><button class="btn btn-primary" @onclick="_submitCredentials">Login</button></td>
        </tr>
    </table>
}
else
{
    <p>Welcome, @_username! You are already authenticated.</p>
}


@code {
    string _login = "";
    string _password = "";
    private bool _isAuthenticated = false;
    private string _username = "";

    protected override async Task OnInitializedAsync()
    {
        var isAuthenticated = await jsr.InvokeAsync<string>("localStorage.getItem", "isAuthenticated");
        Console.WriteLine($"isAuthenticated: {isAuthenticated}");

        bool value;

        if (bool.TryParse(isAuthenticated, out value))
        {
            Console.WriteLine($"_isAuthenticated: {_isAuthenticated}");
            _isAuthenticated = value;
        }
    }

    private async Task _submitCredentials()
    {
        _isAuthenticated = true;
        await jsr.InvokeVoidAsync("localStorage.setItem", "isAuthenticated", _isAuthenticated).ConfigureAwait(false);
    }
}

Explanation of the code:

The login and password fields are only dummy fields and are not evaluated at all. When we arrive at the first time on the page the OnInitializedAsync() is called. Here we try to read the local storage value and if a value is stored there we set _isAuthenticated to that value.

Because at the beginning there is no value in the local storage _isAuthenticated will remain false and therefore the part of the HTML with login and password fields is rendered.

Once we click on the [Login] button to simulate a login action on our pseudo dummy login page, we land in the _submitCredentials() method. Here we set the value to true and store it persistently in the local storage.

From now on the second part of the HTML is rendered even if we switch to another page and back to the login page.