Skip to content

Commit 5df4dbb

Browse files
authored
Merge pull request Blazored#18 from jan-johansson-mr/add-config
Added the same configuration option as is in LocalStorage
2 parents 9e9f4fc + 56fba9a commit 5df4dbb

8 files changed

Lines changed: 169 additions & 34 deletions

File tree

‎README.md‎

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ A library to provide access to session storage in Blazor applications
33

44
[![Build Status](https://dev.azure.com/blazored/SessionStorage/_apis/build/status/Blazored.SessionStorage?branchName=master)](https://dev.azure.com/blazored/SessionStorage/_build/latest?definitionId=1&branchName=master)
55

6-
![Nuget](https://img.shields.io/nuget/v/blazored.sessionstorage.svg)
6+
[![Nuget](https://img.shields.io/nuget/v/blazored.sessionstorage.svg)](https://www.nuget.org/packages/Blazored.SessionStorage/)
77

88
### Installing
99

1010
You can install from NuGet using the following command:
1111

1212
`Install-Package Blazored.SessionStorage`
1313

14-
Or via the Visual Studio package manger.
14+
Or via the Visual Studio package manager.
1515

1616
### Setup
1717

18-
You will need to register the session storage services with the service collection in your _startup.cs_ file.
18+
You will need to register the session storage services with the service collection in your _Startup.cs_ file in Blazor Server.
1919

2020
```c#
2121
public void ConfigureServices(IServiceCollection services)
@@ -24,6 +24,47 @@ public void ConfigureServices(IServiceCollection services)
2424
}
2525
```
2626

27+
Or in your _Program.cs_ file in Blazor WebAssembly.
28+
29+
```c#
30+
public static async Task Main(string[] args)
31+
{
32+
var builder = WebAssemblyHostBuilder.CreateDefault(args);
33+
builder.RootComponents.Add<App>("app");
34+
35+
builder.Services.AddBlazoredSessionStorage();
36+
37+
await builder.Build().RunAsync();
38+
}
39+
```
40+
41+
### Configuration
42+
43+
The session storage provides options that can be modified by you at registration in your _Startup.cs_ file in Blazor Server.
44+
45+
46+
```c#
47+
public void ConfigureServices(IServiceCollection services)
48+
{
49+
services.AddBlazoredSessionStorage(config =>
50+
config.JsonSerializerOptions.WriteIndented = true);
51+
}
52+
```
53+
Or in your _Program.cs_ file in Blazor WebAssembly.
54+
55+
```c#
56+
public static async Task Main(string[] args)
57+
{
58+
var builder = WebAssemblyHostBuilder.CreateDefault(args);
59+
builder.RootComponents.Add<App>("app");
60+
61+
builder.Services.AddBlazoredSessionStorage(config =>
62+
config.JsonSerializerOptions.WriteIndented = true);
63+
64+
await builder.Build().RunAsync();
65+
}
66+
```
67+
2768
### Usage (Blazor WebAssembly)
2869
To use Blazored.SessionStorage in Blazor WebAssembly, inject the `ISessionStorageService` per the example below.
2970

@@ -64,9 +105,9 @@ With Blazor WebAssembly you also have the option of a synchronous API, if your u
64105
```c#
65106
@inject Blazored.SessionStorage.ISessionStorageService sessionStorage
66107

67-
@functions {
108+
@code {
68109

69-
protected override async Task OnAfterRenderAsync()
110+
protected override async Task OnAfterRenderAsync(bool firstRender)
70111
{
71112
await sessionStorage.SetItemAsync("name", "John Smith");
72113
var name = await sessionStorage.GetItemAsync<string>("name");
@@ -84,12 +125,15 @@ The APIs available are:
84125
- ClearAsync()
85126
- LengthAsync()
86127
- KeyAsync()
87-
- synchronous via `ISyncSessionStorageService`:
128+
- ContainsKeyAsync()
129+
130+
- synchronous via `ISyncSessionStorageService` (Synchronous methods are **only** available in Blazor WebAssembly):
88131
- SetItem()
89132
- GetItem()
90133
- RemoveItem()
91134
- Clear()
92135
- Length()
93136
- Key()
137+
- ContainsKey()
94138

95139
**Note:** Blazored.SessionStorage methods will handle the serialisation and de-serialisation of the data for you.

‎src/Blazored.SessionStorage/Blazored.SessionStorage.csproj‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<RazorLangVersion>3.0</RazorLangVersion>
66
<RootNamespace>Blazored.SessionStorage</RootNamespace>
7-
<TypeScriptToolsVersion>3.2</TypeScriptToolsVersion>
87

98
<PackageId>Blazored.SessionStorage</PackageId>
109
<Version>1.0.11</Version>
@@ -18,10 +17,10 @@
1817
<PackageTags>Blazor SessionStorage Blazored Razor Components</PackageTags>
1918
<Company />
2019
</PropertyGroup>
21-
20+
2221
<ItemGroup>
23-
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.0.0" />
24-
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="3.0.0" />
22+
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.1.4" />
23+
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="3.1.4" />
2524
</ItemGroup>
2625

2726
</Project>

‎src/Blazored.SessionStorage/ISessionStorageService.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface ISessionStorageService
1515

1616
Task RemoveItemAsync(string key);
1717

18-
Task SetItemAsync(string key, object data);
18+
Task SetItemAsync<T>(string key, T data);
1919

2020
event EventHandler<ChangingEventArgs> Changing;
2121
event EventHandler<ChangedEventArgs> Changed;

‎src/Blazored.SessionStorage/ISyncSessionStorageService.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public interface ISyncSessionStorageService
1414

1515
void RemoveItem(string key);
1616

17-
void SetItem(string key, object data);
17+
void SetItem<T>(string key, T data);
1818

1919
event EventHandler<ChangingEventArgs> Changing;
2020
event EventHandler<ChangedEventArgs> Changed;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Text.Json;
3+
using System.Text.Json.Serialization;
4+
using System.Text.RegularExpressions;
5+
6+
namespace Blazored.SessionStorage.JsonConverters
7+
{
8+
/// <summary>
9+
/// The new Json.NET doesn't support Timespan at this time
10+
/// https://github.com/dotnet/corefx/issues/38641
11+
/// </summary>
12+
public class TimespanJsonConverter : JsonConverter<TimeSpan>
13+
{
14+
/// <summary>
15+
/// Format: Days.Hours:Minutes:Seconds:Milliseconds
16+
/// </summary>
17+
public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
18+
19+
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
20+
{
21+
var s = reader.GetString();
22+
if (string.IsNullOrWhiteSpace(s))
23+
{
24+
return TimeSpan.Zero;
25+
}
26+
else
27+
{
28+
TimeSpan parsedTimeSpan;
29+
if (!TimeSpan.TryParseExact(s, TimeSpanFormatString, null, out parsedTimeSpan))
30+
{
31+
throw new FormatException($"Input timespan is not in an expected format : expected {Regex.Unescape(TimeSpanFormatString)}. Please retrieve this key as a string and parse manually.");
32+
}
33+
else
34+
{
35+
return parsedTimeSpan;
36+
}
37+
}
38+
}
39+
40+
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
41+
{
42+
var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
43+
writer.WriteStringValue(timespanFormatted);
44+
}
45+
}
46+
}
Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using System;
2+
using Blazored.SessionStorage.JsonConverters;
3+
using Blazored.SessionStorage.StorageOptions;
4+
using Microsoft.Extensions.DependencyInjection;
25

36
namespace Blazored.SessionStorage
47
{
@@ -8,7 +11,23 @@ public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollecti
811
{
912
return services
1013
.AddScoped<ISessionStorageService, SessionStorageService>()
11-
.AddScoped<ISyncSessionStorageService, SessionStorageService>();
14+
.AddScoped<ISyncSessionStorageService, SessionStorageService>()
15+
.Configure<SessionStorageOptions>(configureOptions =>
16+
{
17+
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
18+
});
1219
}
20+
21+
public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollection services, Action<SessionStorageOptions> configure)
22+
{
23+
return services
24+
.AddScoped<ISessionStorageService, SessionStorageService>()
25+
.AddScoped<ISyncSessionStorageService, SessionStorageService>()
26+
.Configure<SessionStorageOptions>(configureOptions =>
27+
{
28+
configure?.Invoke(configureOptions);
29+
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
30+
});
31+
}
1332
}
1433
}

‎src/Blazored.SessionStorage/SessionStorageService.cs‎

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Microsoft.JSInterop;
1+
using Blazored.SessionStorage.StorageOptions;
2+
using Microsoft.Extensions.Options;
3+
using Microsoft.JSInterop;
24
using System;
35
using System.Text.Json;
46
using System.Threading.Tasks;
@@ -9,24 +11,31 @@ public class SessionStorageService : ISessionStorageService, ISyncSessionStorage
911
{
1012
private readonly IJSRuntime _jSRuntime;
1113
private readonly IJSInProcessRuntime _jSInProcessRuntime;
14+
private readonly JsonSerializerOptions _jsonOptions;
1215

13-
public SessionStorageService(IJSRuntime jSRuntime)
16+
public event EventHandler<ChangingEventArgs> Changing;
17+
public event EventHandler<ChangedEventArgs> Changed;
18+
19+
public SessionStorageService(IJSRuntime jSRuntime, IOptions<SessionStorageOptions> options)
1420
{
15-
_jSRuntime = jSRuntime;
16-
_jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
21+
_jSRuntime = jSRuntime;
22+
_jsonOptions = options.Value.JsonSerializerOptions;
23+
_jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
1724
}
1825

19-
public async Task SetItemAsync(string key, object data)
26+
public async Task SetItemAsync<T>(string key, T data)
2027
{
2128
if (string.IsNullOrEmpty(key))
2229
throw new ArgumentNullException(nameof(key));
2330

2431
var e = await RaiseOnChangingAsync(key, data);
2532

2633
if (e.Cancel)
27-
return;
28-
29-
await _jSRuntime.InvokeAsync<object>("sessionStorage.setItem", key, JsonSerializer.Serialize(data));
34+
return;
35+
36+
var serialisedData = JsonSerializer.Serialize(data, _jsonOptions);
37+
38+
await _jSRuntime.InvokeVoidAsync("sessionStorage.setItem", key, serialisedData);
3039

3140
RaiseOnChanged(key, e.OldValue, data);
3241
}
@@ -39,9 +48,9 @@ public async Task<T> GetItemAsync<T>(string key)
3948
var serialisedData = await _jSRuntime.InvokeAsync<string>("sessionStorage.getItem", key);
4049

4150
if (serialisedData == null)
42-
return default(T);
43-
44-
return JsonSerializer.Deserialize<T>(serialisedData);
51+
return default;
52+
53+
return JsonSerializer.Deserialize<T>(serialisedData, _jsonOptions);
4554
}
4655

4756
public async Task RemoveItemAsync(string key)
@@ -58,7 +67,7 @@ public async Task RemoveItemAsync(string key)
5867

5968
public async Task<string> KeyAsync(int index) => await _jSRuntime.InvokeAsync<string>("sessionStorage.key", index);
6069

61-
public void SetItem(string key, object data)
70+
public void SetItem<T>(string key, T data)
6271
{
6372
if (string.IsNullOrEmpty(key))
6473
throw new ArgumentNullException(nameof(key));
@@ -71,7 +80,9 @@ public void SetItem(string key, object data)
7180
if (e.Cancel)
7281
return;
7382

74-
_jSInProcessRuntime.Invoke<object>("sessionStorage.setItem", key, JsonSerializer.Serialize(data));
83+
var serialisedData = JsonSerializer.Serialize(data, _jsonOptions);
84+
85+
_jSInProcessRuntime.InvokeVoid("sessionStorage.setItem", key, serialisedData);
7586

7687
RaiseOnChanged(key, e.OldValue, data);
7788
}
@@ -87,9 +98,9 @@ public T GetItem<T>(string key)
8798
var serialisedData = _jSInProcessRuntime.Invoke<string>("sessionStorage.getItem", key);
8899

89100
if (serialisedData == null)
90-
return default(T);
91-
92-
return JsonSerializer.Deserialize<T>(serialisedData);
101+
return default;
102+
103+
return JsonSerializer.Deserialize<T>(serialisedData, _jsonOptions);
93104
}
94105

95106
public void RemoveItem(string key)
@@ -100,15 +111,15 @@ public void RemoveItem(string key)
100111
if (_jSInProcessRuntime == null)
101112
throw new InvalidOperationException("IJSInProcessRuntime not available");
102113

103-
_jSInProcessRuntime.Invoke<object>("sessionStorage.removeItem", key);
114+
_jSInProcessRuntime.InvokeVoid("sessionStorage.removeItem", key);
104115
}
105116

106117
public void Clear()
107118
{
108119
if (_jSInProcessRuntime == null)
109120
throw new InvalidOperationException("IJSInProcessRuntime not available");
110121

111-
_jSInProcessRuntime.Invoke<object>("sessionStorage.clear");
122+
_jSInProcessRuntime.InvokeVoid("sessionStorage.clear");
112123
}
113124

114125
public int Length()
@@ -127,7 +138,6 @@ public string Key(int index)
127138
return _jSInProcessRuntime.Invoke<string>("sessionStorage.key", index);
128139
}
129140

130-
public event EventHandler<ChangingEventArgs> Changing;
131141
private async Task<ChangingEventArgs> RaiseOnChangingAsync(string key, object data)
132142
{
133143
var e = new ChangingEventArgs
@@ -156,7 +166,6 @@ private ChangingEventArgs RaiseOnChangingSync(string key, object data)
156166
return e;
157167
}
158168

159-
public event EventHandler<ChangedEventArgs> Changed;
160169
private void RaiseOnChanged(string key, object oldValue, object data)
161170
{
162171
var e = new ChangedEventArgs
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Text.Json;
2+
3+
namespace Blazored.SessionStorage.StorageOptions
4+
{
5+
public class SessionStorageOptions
6+
{
7+
public JsonSerializerOptions JsonSerializerOptions { get; } = new JsonSerializerOptions
8+
{
9+
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
10+
IgnoreNullValues = true,
11+
IgnoreReadOnlyProperties = true,
12+
PropertyNameCaseInsensitive = true,
13+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
14+
ReadCommentHandling = JsonCommentHandling.Skip,
15+
WriteIndented = false
16+
};
17+
}
18+
}

0 commit comments

Comments
 (0)