Skip to content

Commit

Permalink
Added ability to register local storage services as singleton (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrissainty committed Mar 28, 2022
1 parent 1bd48c0 commit 6876e49
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
arrTag=(${GITHUB_REF//\// })
VERSION="${arrTag[2]}"
echo Version: $VERSION
VERSION="${VERSION//v}"
VERSION="${VERSION:1}"
echo Clean Version: $VERSION
dotnet pack -v normal -c Release --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg src/Blazored.$PROJECT_NAME/Blazored.$PROJECT_NAME.csproj
dotnet pack -v normal -c Release --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg src/Blazored.$PROJECT_NAME.TestExtensions/Blazored.$PROJECT_NAME.TestExtensions.csproj
Expand Down
4 changes: 2 additions & 2 deletions Blazored.LocalStorage.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28531.58
# Visual Studio Version 17
VisualStudioVersion = 17.1.32228.430
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazored.LocalStorage", "src\Blazored.LocalStorage\Blazored.LocalStorage.csproj", "{EFA12DC3-35DE-449C-88F2-2BD7576CAF2C}"
EndProject
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ public static async Task Main(string[] args)
}
```

### Registering services as Singleton - Blazor WebAssembly **ONLY**
99% of developers will want to register Blazored LocalStorage using the method described above. However, in some very specific scenarios
developer may have a need to register services as Singleton as apposed to Scoped. This is possible by using the following method:

```csharp
builder.Services.AddBlazoredLocalStorageAsSingleton();
```

This method will not work with Blazor Server applications as Blazor's JS interop services are registered as Scoped and cannot be injected into Singletons.

## Usage (Blazor WebAssembly)
To use Blazored.LocalStorage in Blazor WebAssembly, inject the `ILocalStorageService` per the example below.

Expand Down
6 changes: 4 additions & 2 deletions samples/BlazorServer/App.razor
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
2 changes: 2 additions & 0 deletions samples/BlazorServer/BlazorServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
Expand Down
13 changes: 13 additions & 0 deletions samples/BlazorServer/NewtonSoftJsonSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Blazored.LocalStorage.Serialization;
using Newtonsoft.Json;

namespace BlazorServer;

public class NewtonSoftJsonSerializer : IJsonSerializer
{
public T Deserialize<T>(string text)
=> JsonConvert.DeserializeObject<T>(text);

public string Serialize<T>(T obj)
=> JsonConvert.SerializeObject(obj);
}
2 changes: 2 additions & 0 deletions samples/BlazorServer/Pages/Index.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@page "/"
@inject ILocalStorageService localStorage

<PageTitle>Blazored LocalStorage (Server)</PageTitle>

<h1>Blazored LocalStorage Sample</h1>

<hr class="mb-5" />
Expand Down
31 changes: 4 additions & 27 deletions samples/BlazorServer/Pages/_Host.cshtml
Original file line number Diff line number Diff line change
@@ -1,32 +1,9 @@
@page "/"
@namespace BlazorServer.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Blazored LocalStorage (Server)</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="BlazorServer.styles.css" rel="stylesheet" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<component type="typeof(App)" render-mode="ServerPrerendered" />

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

<script src="_framework/blazor.server.js"></script>
</body>
</html>
32 changes: 32 additions & 0 deletions samples/BlazorServer/Pages/_Layout.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@using Microsoft.AspNetCore.Components.Web
@namespace BlazorServer.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="BlazorServer.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

<script src="_framework/blazor.server.js"></script>
</body>
</html>
47 changes: 30 additions & 17 deletions samples/BlazorServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Blazored.LocalStorage;
using Blazored.LocalStorage.Serialization;
using BlazorServer;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace BlazorServer
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(config => config.DetailedErrors = true);
builder.Services.AddBlazoredLocalStorage();
builder.Services.Replace(ServiceDescriptor.Scoped<IJsonSerializer, NewtonSoftJsonSerializer>());

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();
68 changes: 0 additions & 68 deletions samples/BlazorServer/Startup.cs

This file was deleted.

4 changes: 2 additions & 2 deletions samples/BlazorWebAssembly/BlazorWebAssembly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(DotNet5Version)" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="$(DotNet5Version)" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(DotNet6Version)" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="$(DotNet6Version)" PrivateAssets="all" />
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion samples/BlazorWebAssembly/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static async Task Main(string[] args)
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

builder.Services.AddBlazoredLocalStorage();
builder.Services.AddBlazoredLocalStorageAsSingleton();

await builder.Build().RunAsync();
}
Expand Down
29 changes: 29 additions & 0 deletions src/Blazored.LocalStorage/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,34 @@ public static IServiceCollection AddBlazoredLocalStorage(this IServiceCollection
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
});
}

/// <summary>
/// Registers the Blazored LocalStorage services as singletons. This should only be used in Blazor WebAssembly applications.
/// Using this in Blazor Server applications will cause unexpected and potentially dangerous behaviour.
/// </summary>
/// <returns></returns>
public static IServiceCollection AddBlazoredLocalStorageAsSingleton(this IServiceCollection services)
=> AddBlazoredLocalStorageAsSingleton(services, null);

/// <summary>
/// Registers the Blazored LocalStorage services as singletons. This should only be used in Blazor WebAssembly applications.
/// Using this in Blazor Server applications will cause unexpected and potentially dangerous behaviour.
/// </summary>
/// <param name="services"></param>
/// <param name="configure"></param>
/// <returns></returns>
public static IServiceCollection AddBlazoredLocalStorageAsSingleton(this IServiceCollection services, Action<LocalStorageOptions> configure)
{
return services
.AddSingleton<IJsonSerializer, SystemTextJsonSerializer>()
.AddSingleton<IStorageProvider, BrowserStorageProvider>()
.AddSingleton<ILocalStorageService, LocalStorageService>()
.AddSingleton<ISyncLocalStorageService, LocalStorageService>()
.Configure<LocalStorageOptions>(configureOptions =>
{
configure?.Invoke(configureOptions);
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
});
}
}
}

0 comments on commit 6876e49

Please sign in to comment.