Migrating from Blazored.LocalStorage to D20Tek.Blazor.BrowserStorage
A complete, practical guide for Blazor developers
Blazored.LocalStorage served the Blazor community well for years. It wrapped browser storage behind a clean C# API and saved developers from writing JavaScript interop for simple persistence tasks. But the library was deprecated in 2025, later removed from NuGet.org, and the repository was archived.
If your Blazor WebAssembly or interactive render mode app still depends on Blazored.LocalStorage, now is the time to migrate. This guide walks you through the full process of replacing Blazored.LocalStorage with D20Tek.Blazor.BrowserStorage, a modern typed, async, DI‑friendly browser storage library built specifically for today’s Blazor ecosystem.
Why migrate?
Blazored.LocalStorage is no longer maintained. That means:
- No updates for .NET 8/9/10/11
- No fixes for browser API changes
- No support for interactive render modes
- No new features
- No security patches
D20Tek.Blazor.BrowserStorage provides:
- Typed reads/writes
- Async APIs
- No JS interop
- No exceptions for missing keys
- Batch operations
- Change events
- Key prefixing
- Custom JSON options
- One package for both local + session storage
It’s designed to be a drop‑in replacement with minimal code changes.
Step‑by‑Step Migration Guide
Below is a complete procedural guide showing exactly how to migrate your Blazor app.
1. Remove Blazored.LocalStorage from your project
Delete the NuGet package:
dotnet remove package Blazored.LocalStorage
Remove the registration from Program.cs:
// Remove this:
builder.Services.AddBlazoredLocalStorage();
2. Add D20Tek.Blazor.BrowserStorage
dotnet add package D20Tek.Blazor.BrowserStorage
Register the services:
using D20Tek.Blazor.BrowserStorage;
builder.Services.AddBrowserStorage();
This registers both local and session storage services.
3. Update your injected services
Replace:
using Blazored.LocalStorage;
with:
using D20Tek.Blazor.BrowserStorage;
Your injection stays the same:
[Inject]
private ILocalStorageService LocalStorage { get; set; } = default!;
4. Update your read operations
Blazored.LocalStorage (old):
var value = await LocalStorage.GetItemAsync<string>("username");
Throws if the key doesn’t exist.
BrowserStorage (new):
var result = await LocalStorage.GetAsync<string>("username");
if (result.IsSuccess)
{
var value = result.Value;
}
No exceptions. Missing keys return IsSuccess = false.
5. Update your write operations
Old:
await LocalStorage.SetItemAsync("username", "Alice");
New:
await LocalStorage.SetAsync("username", "Alice");
6. Update your remove operations
Old:
await LocalStorage.RemoveItemAsync("username");
New:
await LocalStorage.RemoveAsync("username");
7. Update your key existence checks
Old:
if (await LocalStorage.ContainKeyAsync("username"))
{
}
New:
if (await LocalStorage.ContainsKeyAsync("username"))
{
}
8. Update your session storage usage
Blazored required a separate package.
BrowserStorage does not.
You can inject:
[Inject]
private ISessionStorageService SessionStorage { get; set; } = default!;
And use the same API:
await SessionStorage.SetAsync("score", 42);
var score = await SessionStorage.GetAsync<int>("score");
9. Optional: Add key prefixing
If your app has multiple modules:
builder.Services.AddBrowserStorage(options =>
{
options.KeyPrefix = "myapp_";
});
10. Optional: Add custom JSON options
builder.Services.AddBrowserStorage(options =>
{
options.JsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
});
11. Test your migration
Verify:
- Reads/writes
- Missing key behavior
- Session storage
- Refresh persistence
- Change events
- Batch operations
Your app should behave identically — but with cleaner, safer code.
Code Comparison: Before and After
Before (Blazored.LocalStorage)
var value = await LocalStorage.GetItemAsync<string>("username");
await LocalStorage.SetItemAsync("username", "Alice");
await LocalStorage.RemoveItemAsync("username");
if (await LocalStorage.ContainKeyAsync("username"))
{
// ...
}
After (D20Tek.Blazor.BrowserStorage)
var result = await LocalStorage.GetAsync<string>("username");
if (result.IsSuccess)
{
var value = result.Value;
}
await LocalStorage.SetAsync("username", "Alice");
await LocalStorage.RemoveAsync("username");
if (await LocalStorage.ContainsKeyAsync("username"))
{
// ...
}
Common Migration Pitfalls
1. Forgetting to remove Blazored’s registration
If you leave AddBlazoredLocalStorage() in Program.cs, your app may compile but fail at runtime.
2. Not updating namespaces
This is the most common cause of “method not found” errors.
3. Assuming GetAsync throws exceptions
It doesn’t — check IsSuccess.
4. Forgetting to migrate session storage
Both services come from the same package now.
Conclusion
Migrating from Blazored.LocalStorage to D20Tek.Blazor.BrowserStorage is straightforward. Most method names map directly, and the few differences (like result‑based reads) improve reliability and reduce boilerplate.
With Blazored deprecated, this migration ensures your Blazor app stays modern, maintainable, and compatible with the latest .NET releases.