Skip to content

Commit

Permalink
Merge pull request #81 from jan-johansson-mr/add-options
Browse files Browse the repository at this point in the history
Added support for LocalStorage configuration, initially for JsonSerializerOptions
  • Loading branch information
chrissainty authored May 21, 2020
2 parents 270e279 + 4510373 commit d714c01
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 54 deletions.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,34 @@ public static async Task Main(string[] args)

await builder.Build().RunAsync();
}
```
```

### Configuration

The local storage provides options that can be modified by you at registration in your _Startup.cs_ file in Blazor Server.


```c#
public void ConfigureServices(IServiceCollection services)
{
services.AddBlazoredLocalStorage(config =>
config.JsonSerializerOptions.WriteIndented = true);
}
```
Or in your _Program.cs_ file in Blazor WebAssembly.

```c#
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");

builder.Services.AddBlazoredLocalStorage(config =>
config.JsonSerializerOptions.WriteIndented = true);

await builder.Build().RunAsync();
}
```

### Usage (Blazor WebAssembly)
To use Blazored.LocalStorage in Blazor WebAssembly, inject the `ILocalStorageService` per the example below.
Expand Down
2 changes: 1 addition & 1 deletion src/Blazored.LocalStorage/ILocalStorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface ILocalStorageService

Task RemoveItemAsync(string key);

Task SetItemAsync(string key, object data);
Task SetItemAsync<T>(string key, T data);

event EventHandler<ChangingEventArgs> Changing;
event EventHandler<ChangedEventArgs> Changed;
Expand Down
2 changes: 1 addition & 1 deletion src/Blazored.LocalStorage/ISyncLocalStorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface ISyncLocalStorageService

void RemoveItem(string key);

void SetItem(string key, object data);
void SetItem<T>(string key, T data);

event EventHandler<ChangingEventArgs> Changing;
event EventHandler<ChangedEventArgs> Changed;
Expand Down
27 changes: 13 additions & 14 deletions src/Blazored.LocalStorage/LocalStorageService.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
using Blazored.LocalStorage.JsonConverters;
using Microsoft.JSInterop;
using System;
using System;
using System.Text.Json;
using System.Threading.Tasks;
using Blazored.LocalStorage.StorageOptions;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;

namespace Blazored.LocalStorage
{
public class LocalStorageService : ILocalStorageService, ISyncLocalStorageService
{
private readonly IJSRuntime _jSRuntime;
private readonly IJSInProcessRuntime _jSInProcessRuntime;
private readonly JsonSerializerOptions _jsonOptions;

private JsonSerializerOptions _jsonOptions;

public LocalStorageService(IJSRuntime jSRuntime)
public LocalStorageService(IJSRuntime jSRuntime, IOptions<LocalStorageOptions> options)
{
_jSRuntime = jSRuntime;
_jsonOptions = options.Value.JsonSerializerOptions;
_jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
_jsonOptions = new JsonSerializerOptions();
_jsonOptions.Converters.Add(new TimespanJsonConverter());
}

public async Task SetItemAsync(string key, object data)
public async Task SetItemAsync<T>(string key, T data)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
Expand Down Expand Up @@ -52,7 +51,7 @@ public async Task<T> GetItemAsync<T>(string key)
var serialisedData = await _jSRuntime.InvokeAsync<string>("localStorage.getItem", key);

if (string.IsNullOrWhiteSpace(serialisedData))
return default(T);
return default;

if (serialisedData.StartsWith("{") && serialisedData.EndsWith("}")
|| serialisedData.StartsWith("\"") && serialisedData.EndsWith("\"")
Expand Down Expand Up @@ -82,7 +81,7 @@ public async Task RemoveItemAsync(string key)

public async Task<bool> ContainKeyAsync(string key) => await _jSRuntime.InvokeAsync<bool>("localStorage.hasOwnProperty", key);

public void SetItem(string key, object data)
public void SetItem<T>(string key, T data)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
Expand Down Expand Up @@ -118,7 +117,7 @@ public T GetItem<T>(string key)
var serialisedData = _jSInProcessRuntime.Invoke<string>("localStorage.getItem", key);

if (string.IsNullOrWhiteSpace(serialisedData))
return default(T);
return default;

if (serialisedData.StartsWith("{") && serialisedData.EndsWith("}")
|| serialisedData.StartsWith("\"") && serialisedData.EndsWith("\"")
Expand Down Expand Up @@ -198,7 +197,7 @@ private async Task<T> GetItemInternalAsync<T>(string key)
var serialisedData = await _jSRuntime.InvokeAsync<string>("localStorage.getItem", key);

if (string.IsNullOrWhiteSpace(serialisedData))
return default(T);
return default;

if (serialisedData.StartsWith("{") && serialisedData.EndsWith("}")
|| serialisedData.StartsWith("\"") && serialisedData.EndsWith("\""))
Expand Down Expand Up @@ -236,7 +235,7 @@ public T GetItemInternal<T>(string key)
var serialisedData = _jSInProcessRuntime.Invoke<string>("localStorage.getItem", key);

if (string.IsNullOrWhiteSpace(serialisedData))
return default(T);
return default;

if (serialisedData.StartsWith("{") && serialisedData.EndsWith("}")
|| serialisedData.StartsWith("\"") && serialisedData.EndsWith("\""))
Expand Down
23 changes: 21 additions & 2 deletions src/Blazored.LocalStorage/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Blazored.LocalStorage.JsonConverters;
using Blazored.LocalStorage.StorageOptions;
using Microsoft.Extensions.DependencyInjection;

namespace Blazored.LocalStorage
{
Expand All @@ -8,7 +11,23 @@ public static IServiceCollection AddBlazoredLocalStorage(this IServiceCollection
{
return services
.AddScoped<ILocalStorageService, LocalStorageService>()
.AddScoped<ISyncLocalStorageService, LocalStorageService>();
.AddScoped<ISyncLocalStorageService, LocalStorageService>()
.Configure<LocalStorageOptions>(configureOptions =>
{
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
});
}

public static IServiceCollection AddBlazoredLocalStorage(this IServiceCollection services, Action<LocalStorageOptions> configure)
{
return services
.AddScoped<ILocalStorageService, LocalStorageService>()
.AddScoped<ISyncLocalStorageService, LocalStorageService>()
.Configure<LocalStorageOptions>(configureOptions =>
{
configure?.Invoke(configureOptions);
configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
});
}
}
}
18 changes: 18 additions & 0 deletions src/Blazored.LocalStorage/StorageOptions/LocalStorageOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json;

namespace Blazored.LocalStorage.StorageOptions
{
public class LocalStorageOptions
{
public JsonSerializerOptions JsonSerializerOptions { get; } = new JsonSerializerOptions
{
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
IgnoreNullValues = true,
IgnoreReadOnlyProperties = true,
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
ReadCommentHandling = JsonCommentHandling.Skip,
WriteIndented = false
};
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
using System.Text.Json;
using Blazored.LocalStorage.JsonConverters;
using Blazored.LocalStorage.StorageOptions;
using Blazored.LocalStorage.Tests.Mocks;
using Blazored.LocalStorage.Tests.TestAssets;
using FluentAssertions;
using Microsoft.Extensions.Options;
using Moq;
using System.Text.Json;
using System.Threading.Tasks;
using Xunit;

namespace Blazored.LocalStorage.Tests.LocalStorageServiceTests
{
public class GetItem
{
private JsonSerializerOptions _jsonOptions;
private Mock<JSRuntimeWrapper> _mockJSRuntime;
private LocalStorageService _sut;
private readonly JsonSerializerOptions _jsonOptions;
private readonly Mock<JSRuntimeWrapper> _mockJSRuntime;
private readonly Mock<IOptions<LocalStorageOptions>> _mockOptions;
private readonly LocalStorageService _sut;

private static string _key = "testKey";
private static readonly string _key = "testKey";

public GetItem()
{
_mockJSRuntime = new Mock<JSRuntimeWrapper>();
_mockOptions = new Mock<IOptions<LocalStorageOptions>>();
_jsonOptions = new JsonSerializerOptions();
_jsonOptions.Converters.Add(new TimespanJsonConverter());
_sut = new LocalStorageService(_mockJSRuntime.Object);
_mockOptions.Setup(u => u.Value).Returns(new LocalStorageOptions());
_sut = new LocalStorageService(_mockJSRuntime.Object, _mockOptions.Object);
}

[Theory]
Expand All @@ -37,7 +41,7 @@ public void Should_DeserialiseToCorrectType<T>(T value)
serialisedData = value.ToString();
else
serialisedData = JsonSerializer.Serialize(value, _jsonOptions);

_mockJSRuntime.Setup(x => x.Invoke<string>("localStorage.getItem", new[] { _key }))
.Returns(() => serialisedData);

Expand Down Expand Up @@ -72,7 +76,7 @@ public void Should_DeserialiseValueToDecimal()
// Arrange
decimal value = 6.00m;
var serialisedData = JsonSerializer.Serialize(value, _jsonOptions);

_mockJSRuntime.Setup(x => x.Invoke<string>("localStorage.getItem", new[] { _key }))
.Returns(() => serialisedData);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
using System.Text.Json;
using System.Threading.Tasks;
using Blazored.LocalStorage.JsonConverters;
using Blazored.LocalStorage.StorageOptions;
using Blazored.LocalStorage.Tests.Mocks;
using Blazored.LocalStorage.Tests.TestAssets;
using FluentAssertions;
using Microsoft.Extensions.Options;
using Moq;
using System.Text.Json;
using System.Threading.Tasks;
using Xunit;

namespace Blazored.LocalStorage.Tests.LocalStorageServiceTests
{
public class GetItemAsync
{
private JsonSerializerOptions _jsonOptions;
private Mock<JSRuntimeWrapperAsync> _mockJSRuntime;
private LocalStorageService _sut;
private readonly JsonSerializerOptions _jsonOptions;
private readonly Mock<JSRuntimeWrapperAsync> _mockJSRuntime;
private readonly Mock<IOptions<LocalStorageOptions>> _mockOptions;
private readonly LocalStorageService _sut;

private static string _key = "testKey";
private static readonly string _key = "testKey";

public GetItemAsync()
{
_mockJSRuntime = new Mock<JSRuntimeWrapperAsync>();
_mockOptions = new Mock<IOptions<LocalStorageOptions>>();
_jsonOptions = new JsonSerializerOptions();
_jsonOptions.Converters.Add(new TimespanJsonConverter());
_sut = new LocalStorageService(_mockJSRuntime.Object);
_mockOptions.Setup(u => u.Value).Returns(new LocalStorageOptions());
_sut = new LocalStorageService(_mockJSRuntime.Object, _mockOptions.Object);
}

[Theory]
Expand All @@ -37,7 +42,7 @@ public async Task Should_DeserialiseToCorrectType<T>(T value)
serialisedData = value.ToString();
else
serialisedData = JsonSerializer.Serialize(value, _jsonOptions);

_mockJSRuntime.Setup(x => x.InvokeAsync<string>("localStorage.getItem", new[] { _key }))
.Returns(() => new ValueTask<string>(serialisedData));

Expand Down Expand Up @@ -72,7 +77,7 @@ public async Task Should_DeserialiseValueToDecimal()
// Arrange
decimal value = 6.00m;
var serialisedData = JsonSerializer.Serialize(value, _jsonOptions);

_mockJSRuntime.Setup(x => x.InvokeAsync<string>("localStorage.getItem", new[] { _key }))
.Returns(() => new ValueTask<string>(serialisedData));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
using Blazored.LocalStorage.JsonConverters;
using System.Text.Json;
using Blazored.LocalStorage.JsonConverters;
using Blazored.LocalStorage.StorageOptions;
using Blazored.LocalStorage.Tests.Mocks;
using FluentAssertions;
using Microsoft.Extensions.Options;
using Moq;
using System.Text.Json;
using Xunit;

namespace Blazored.LocalStorage.Tests.LocalStorageServiceTests
{
public class SetItem
{
private JsonSerializerOptions _jsonOptions;
private Mock<JSRuntimeWrapper> _mockJSRuntime;
private LocalStorageService _sut;
private readonly JsonSerializerOptions _jsonOptions;
private readonly Mock<JSRuntimeWrapper> _mockJSRuntime;
private readonly Mock<IOptions<LocalStorageOptions>> _mockOptions;
private readonly LocalStorageService _sut;

private static string _key = "testKey";
private static readonly string _key = "testKey";

public SetItem()
{
_mockJSRuntime = new Mock<JSRuntimeWrapper>();
_mockOptions = new Mock<IOptions<LocalStorageOptions>>();
_jsonOptions = new JsonSerializerOptions();
_jsonOptions.Converters.Add(new TimespanJsonConverter());
_sut = new LocalStorageService(_mockJSRuntime.Object);
_mockOptions.Setup(u => u.Value).Returns(new LocalStorageOptions());
_sut = new LocalStorageService(_mockJSRuntime.Object, _mockOptions.Object);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
using Blazored.LocalStorage.JsonConverters;
using System.Text.Json;
using System.Threading.Tasks;
using Blazored.LocalStorage.JsonConverters;
using Blazored.LocalStorage.StorageOptions;
using Blazored.LocalStorage.Tests.Mocks;
using FluentAssertions;
using Microsoft.Extensions.Options;
using Moq;
using System.Text.Json;
using System.Threading.Tasks;
using Xunit;

namespace Blazored.LocalStorage.Tests.LocalStorageServiceTests
{
public class SetItemAsync
{
private JsonSerializerOptions _jsonOptions;
private Mock<JSRuntimeWrapperAsync> _mockJSRuntime;
private LocalStorageService _sut;
private readonly JsonSerializerOptions _jsonOptions;
private readonly Mock<JSRuntimeWrapperAsync> _mockJSRuntime;
private readonly Mock<IOptions<LocalStorageOptions>> _mockOptions;
private readonly LocalStorageService _sut;

private static string _key = "testKey";
private static readonly string _key = "testKey";

public SetItemAsync()
{
_mockJSRuntime = new Mock<JSRuntimeWrapperAsync>();
_mockOptions = new Mock<IOptions<LocalStorageOptions>>();
_jsonOptions = new JsonSerializerOptions();
_jsonOptions.Converters.Add(new TimespanJsonConverter());
_sut = new LocalStorageService(_mockJSRuntime.Object);
_mockOptions.Setup(u => u.Value).Returns(new LocalStorageOptions());
_sut = new LocalStorageService(_mockJSRuntime.Object, _mockOptions.Object);
}

[Fact]
Expand Down

0 comments on commit d714c01

Please sign in to comment.