Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to register local storage services as singleton #175

Merged
merged 1 commit into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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());
});
}
}
}