Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text.Json;
using Cuemon.AspNetCore.Diagnostics;
using Cuemon.Extensions.AspNetCore.Text.Json.Converters;
using Cuemon.Extensions.DependencyInjection;
using Cuemon.Extensions.Text.Json.Formatters;
using Cuemon.Net.Http;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -37,7 +38,7 @@ public static IServiceCollection AddJsonFormatterOptions(this IServiceCollection
{
Validator.ThrowIfNull(services);
Validator.ThrowIfInvalidConfigurator(setup, out var options);
services.Configure(setup ?? (o =>
services.TryConfigure(setup ?? (o =>
{
o.Settings = options.Settings;
o.SensitivityDetails = options.SensitivityDetails;
Expand Down
64 changes: 64 additions & 0 deletions src/Cuemon.Extensions.AspNetCore.Text.Json/MinimalJsonOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Text.Json;
using Cuemon.Collections.Generic;
using Cuemon.Extensions.AspNetCore.Text.Json.Converters;
using Cuemon.Extensions.Text.Json.Formatters;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.Extensions.Options;

namespace Cuemon.Extensions.AspNetCore.Text.Json
{
/// <summary>
/// A <see cref="ConfigureOptions{TOptions}"/> implementation which will pass <see cref="JsonFormatterOptions"/> to <see cref="JsonOptions"/>.
/// </summary>
public class MinimalJsonOptions : ConfigureOptions<JsonOptions>
{
/// <summary>
/// Initializes a new instance of the <see cref="MinimalJsonOptions" /> class.
/// </summary>
/// <param name="formatterOptions">
/// The formatter options.
/// </param>
public MinimalJsonOptions(IOptions<JsonFormatterOptions> formatterOptions) : base(mo =>
{
var options = formatterOptions.Value;

var settings = new JsonSerializerOptions(options.Settings);
settings.Converters.AddHttpExceptionDescriptorConverter(o => o.SensitivityDetails = options.SensitivityDetails);

Decorator.Enclose(mo.SerializerOptions.Converters).AddRange(settings.Converters);
mo.SerializerOptions.AllowOutOfOrderMetadataProperties = settings.AllowOutOfOrderMetadataProperties;
mo.SerializerOptions.AllowTrailingCommas = settings.AllowTrailingCommas;
mo.SerializerOptions.DefaultBufferSize = settings.DefaultBufferSize;
mo.SerializerOptions.Encoder = settings.Encoder;
mo.SerializerOptions.DictionaryKeyPolicy = settings.DictionaryKeyPolicy;
mo.SerializerOptions.DefaultIgnoreCondition = settings.DefaultIgnoreCondition;
mo.SerializerOptions.NumberHandling = settings.NumberHandling;
mo.SerializerOptions.PreferredObjectCreationHandling = settings.PreferredObjectCreationHandling;
mo.SerializerOptions.UnknownTypeHandling = settings.UnknownTypeHandling;
mo.SerializerOptions.UnmappedMemberHandling = settings.UnmappedMemberHandling;
mo.SerializerOptions.IgnoreReadOnlyProperties = settings.IgnoreReadOnlyProperties;
mo.SerializerOptions.IgnoreReadOnlyFields = settings.IgnoreReadOnlyFields;
mo.SerializerOptions.IncludeFields = settings.IncludeFields;
mo.SerializerOptions.MaxDepth = settings.MaxDepth;
mo.SerializerOptions.PropertyNamingPolicy = settings.PropertyNamingPolicy;
mo.SerializerOptions.PropertyNameCaseInsensitive = settings.PropertyNameCaseInsensitive;
mo.SerializerOptions.ReadCommentHandling = settings.ReadCommentHandling;
mo.SerializerOptions.WriteIndented = settings.WriteIndented;
mo.SerializerOptions.IndentCharacter = settings.IndentCharacter;
mo.SerializerOptions.IndentSize = settings.IndentSize;
mo.SerializerOptions.ReferenceHandler = settings.ReferenceHandler;
mo.SerializerOptions.NewLine = settings.NewLine;
mo.SerializerOptions.RespectNullableAnnotations = settings.RespectNullableAnnotations;
mo.SerializerOptions.RespectRequiredConstructorParameters = settings.RespectRequiredConstructorParameters;
#if NET10_0_OR_GREATER
mo.SerializerOptions.AllowDuplicateProperties = settings.AllowDuplicateProperties;
#endif
if (settings.TypeInfoResolver is not null)
{
mo.SerializerOptions.TypeInfoResolver = settings.TypeInfoResolver;
}
})
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using Cuemon.Extensions.AspNetCore.Text.Json.Formatters;
using Cuemon.Extensions.Text.Json.Formatters;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace Cuemon.Extensions.AspNetCore.Text.Json
{
/// <summary>
/// Extension methods for the <see cref="IServiceCollection"/> interface.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds a <see cref="JsonFormatterOptions"/> service to the specified <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add services to.</param>
/// <param name="setup">The <see cref="JsonFormatterOptions"/> which may be configured.</param>
/// <returns>An <see cref="IServiceCollection"/> that can be used to further configure other services.</returns>
/// <remarks>
/// This method registers a <see cref="MinimalJsonOptions"/> configuration as a singleton <see cref="IConfigureOptions{TOptions}"/> for <see cref="JsonOptions"/>
/// and delegates to <see cref="Cuemon.Extensions.AspNetCore.Text.Json.Formatters.ServiceCollectionExtensions.AddJsonExceptionResponseFormatter"/> to configure the JSON exception response formatter.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> cannot be null.
/// </exception>
public static IServiceCollection AddMinimalJsonOptions(this IServiceCollection services, Action<JsonFormatterOptions> setup = null)
{
Validator.ThrowIfNull(services);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<JsonOptions>, MinimalJsonOptions>());
return services.AddJsonExceptionResponseFormatter(setup);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Net.Http;
using Cuemon.AspNetCore.Diagnostics;
using Cuemon.Extensions.AspNetCore.Xml.Converters;
using Cuemon.Extensions.DependencyInjection;
using Cuemon.Net.Http;
using Cuemon.Xml.Serialization.Formatters;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -36,7 +37,7 @@ public static IServiceCollection AddXmlFormatterOptions(this IServiceCollection
{
Validator.ThrowIfNull(services);
Validator.ThrowIfInvalidConfigurator(setup, out var options);
services.Configure(setup ?? (o =>
services.TryConfigure(setup ?? (o =>
{
o.Settings = options.Settings;
o.SensitivityDetails = options.SensitivityDetails;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static IServiceCollection Add<TOptions>(this IServiceCollection services,
Validator.ThrowIfNull(services);
Validator.ThrowIfNull(setup);
services.AddServices(service, implementation, lifetime, false);
services.Configure(setup);
services.TryConfigure(setup);
return services;
}

Expand Down Expand Up @@ -398,7 +398,7 @@ public static IServiceCollection TryAdd<TOptions>(this IServiceCollection servic
Validator.ThrowIfNull(services);
Validator.ThrowIfNull(setup);
services.AddServices(service, implementation, lifetime, true);
services.Configure(setup);
services.TryConfigure(setup);
return services;
}

Expand Down Expand Up @@ -475,7 +475,7 @@ public static IServiceCollection TryAdd<TOptions>(this IServiceCollection servic
Validator.ThrowIfNull(implementationFactory);
Validator.ThrowIfNull(setup);
services.AddServices(service, implementationFactory, lifetime, true);
services.Configure(setup);
services.TryConfigure(setup);
return services;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Linq;
using Cuemon.Extensions.Text.Json.Formatters;
using Codebelt.Extensions.Xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;

namespace Cuemon.Extensions.AspNetCore.Text.Json.Formatters
{
public class ServiceCollectionExtensionsTest : Test
{
public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output)
{
}

[Fact]
public void AddJsonFormatterOptions_ShouldOnlyRegisterOnce_WhenCalledMultipleTimes()
{
var sut = new ServiceCollection();

sut.AddJsonFormatterOptions();
sut.AddJsonFormatterOptions();
sut.AddJsonFormatterOptions();

var configureOptionsCount = sut.Count(sd =>
sd.ServiceType == typeof(IConfigureOptions<JsonFormatterOptions>));

TestOutput.WriteLine($"IConfigureOptions<JsonFormatterOptions> registrations: {configureOptionsCount}");

Assert.Equal(1, configureOptionsCount);
}
}
}
Loading
Loading