From de329aab43ee6772c42022682faaefda9fb2b01a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 4 Jan 2023 16:47:00 -0800 Subject: [PATCH 1/8] Adding EnsureJsonTrimmability switch --- ...Microsoft.AspNetCore.Http.Extensions.csproj | 18 ++++++++++++------ .../src/Properties/ILLink.Substitutions.xml | 8 ++++++++ .../src/Microsoft.AspNetCore.Mvc.Core.csproj | 7 ++++++- .../src/Properties/ILLink.Substitutions.xml | 8 ++++++++ src/Shared/TrimmingAppContextSwitches.cs | 11 +++++++++++ 5 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/Http/Http.Extensions/src/Properties/ILLink.Substitutions.xml create mode 100644 src/Mvc/Mvc.Core/src/Properties/ILLink.Substitutions.xml create mode 100644 src/Shared/TrimmingAppContextSwitches.cs diff --git a/src/Http/Http.Extensions/src/Microsoft.AspNetCore.Http.Extensions.csproj b/src/Http/Http.Extensions/src/Microsoft.AspNetCore.Http.Extensions.csproj index 6c7b5a47df8a..fe8c6d9d7ce5 100644 --- a/src/Http/Http.Extensions/src/Microsoft.AspNetCore.Http.Extensions.csproj +++ b/src/Http/Http.Extensions/src/Microsoft.AspNetCore.Http.Extensions.csproj @@ -12,16 +12,21 @@ - - - - + + + + - + - + + + + + + @@ -34,4 +39,5 @@ + diff --git a/src/Http/Http.Extensions/src/Properties/ILLink.Substitutions.xml b/src/Http/Http.Extensions/src/Properties/ILLink.Substitutions.xml new file mode 100644 index 000000000000..92c77d69a9e6 --- /dev/null +++ b/src/Http/Http.Extensions/src/Properties/ILLink.Substitutions.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.csproj b/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.csproj index 36a376a97f50..7ff7934ad916 100644 --- a/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.csproj +++ b/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.csproj @@ -33,6 +33,7 @@ Microsoft.AspNetCore.Mvc.RouteAttribute + @@ -59,7 +60,11 @@ Microsoft.AspNetCore.Mvc.RouteAttribute - + + + + + diff --git a/src/Mvc/Mvc.Core/src/Properties/ILLink.Substitutions.xml b/src/Mvc/Mvc.Core/src/Properties/ILLink.Substitutions.xml new file mode 100644 index 000000000000..9688f35dcd63 --- /dev/null +++ b/src/Mvc/Mvc.Core/src/Properties/ILLink.Substitutions.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/Shared/TrimmingAppContextSwitches.cs b/src/Shared/TrimmingAppContextSwitches.cs new file mode 100644 index 000000000000..641512945289 --- /dev/null +++ b/src/Shared/TrimmingAppContextSwitches.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Internal; + +internal sealed class TrimmingAppContextSwitches +{ + private const string EnsureJsonTrimmabilityKey = "Microsoft.AspNetCore.EnsureJsonTrimmability"; + + internal static bool EnsureJsonTrimmability { get; } = AppContext.TryGetSwitch(EnsureJsonTrimmabilityKey, out var enabled) && enabled; +} From 1c777f5d9994c1f2c7d2218a3e8492780fc717dc Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 10 Jan 2023 10:40:51 -0800 Subject: [PATCH 2/8] Set TypeResolver to null --- src/Http/Http.Extensions/src/JsonOptions.cs | 3 ++- src/Mvc/Mvc.Core/src/JsonOptions.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Http/Http.Extensions/src/JsonOptions.cs b/src/Http/Http.Extensions/src/JsonOptions.cs index ad718418c09e..de848ea80a96 100644 --- a/src/Http/Http.Extensions/src/JsonOptions.cs +++ b/src/Http/Http.Extensions/src/JsonOptions.cs @@ -4,6 +4,7 @@ using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization.Metadata; +using Microsoft.AspNetCore.Internal; #nullable enable @@ -26,7 +27,7 @@ public class JsonOptions // The JsonSerializerOptions.GetTypeInfo method is called directly and needs a defined resolver // setting the default resolver (reflection-based) but the user can overwrite it directly or calling // .AddContext() - TypeInfoResolver = CreateDefaultTypeResolver() + TypeInfoResolver = TrimmingAppContextSwitches.EnsureJsonTrimmability ? null : CreateDefaultTypeResolver() }; // Use a copy so the defaults are not modified. diff --git a/src/Mvc/Mvc.Core/src/JsonOptions.cs b/src/Mvc/Mvc.Core/src/JsonOptions.cs index 834c758bb9dc..44c2522924f2 100644 --- a/src/Mvc/Mvc.Core/src/JsonOptions.cs +++ b/src/Mvc/Mvc.Core/src/JsonOptions.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization.Metadata; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -42,7 +43,7 @@ public class JsonOptions // The JsonSerializerOptions.GetTypeInfo method is called directly and needs a defined resolver // setting the default resolver (reflection-based) but the user can overwrite it directly or calling // .AddContext() - TypeInfoResolver = CreateDefaultTypeResolver() + TypeInfoResolver = TrimmingAppContextSwitches.EnsureJsonTrimmability ? null : CreateDefaultTypeResolver() }; private static IJsonTypeInfoResolver CreateDefaultTypeResolver() From 2a997e58b804868a0402d70fe151adabbfe05f5a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 10 Jan 2023 14:33:07 -0800 Subject: [PATCH 3/8] Removing RUC/RDC attributes --- .../src/HttpRequestJsonExtensions.cs | 14 ++++++++------ .../src/HttpResponseJsonExtensions.cs | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Http/Http.Extensions/src/HttpRequestJsonExtensions.cs b/src/Http/Http.Extensions/src/HttpRequestJsonExtensions.cs index 09cc97339d0b..437283c330dd 100644 --- a/src/Http/Http.Extensions/src/HttpRequestJsonExtensions.cs +++ b/src/Http/Http.Extensions/src/HttpRequestJsonExtensions.cs @@ -32,13 +32,14 @@ public static class HttpRequestJsonExtensions /// The request to read from. /// A used to cancel the operation. /// The task object representing the asynchronous operation. - [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] - [RequiresDynamicCode(RequiresDynamicCodeMessage)] public static ValueTask ReadFromJsonAsync( this HttpRequest request, CancellationToken cancellationToken = default) { - return request.ReadFromJsonAsync(options: null, cancellationToken); + ArgumentNullException.ThrowIfNull(request); + + var options = ResolveSerializerOptions(request.HttpContext); + return request.ReadFromJsonAsync(jsonTypeInfo: (JsonTypeInfo)options.GetTypeInfo(typeof(TValue)), cancellationToken); } /// @@ -166,14 +167,15 @@ public static class HttpRequestJsonExtensions /// The type of object to read. /// A used to cancel the operation. /// The task object representing the asynchronous operation. - [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] - [RequiresDynamicCode(RequiresDynamicCodeMessage)] public static ValueTask ReadFromJsonAsync( this HttpRequest request, Type type, CancellationToken cancellationToken = default) { - return request.ReadFromJsonAsync(type, options: null, cancellationToken); + ArgumentNullException.ThrowIfNull(request); + + var options = ResolveSerializerOptions(request.HttpContext); + return request.ReadFromJsonAsync(jsonTypeInfo: options.GetTypeInfo(type), cancellationToken); } /// diff --git a/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs b/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs index 9d771adc2fb2..d2ec3b1e516e 100644 --- a/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs +++ b/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs @@ -30,14 +30,15 @@ public static partial class HttpResponseJsonExtensions /// The value to write as JSON. /// A used to cancel the operation. /// The task object representing the asynchronous operation. - [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] - [RequiresDynamicCode(RequiresDynamicCodeMessage)] public static Task WriteAsJsonAsync( this HttpResponse response, TValue value, CancellationToken cancellationToken = default) { - return response.WriteAsJsonAsync(value, options: null, contentType: null, cancellationToken); + ArgumentNullException.ThrowIfNull(response); + + var options = ResolveSerializerOptions(response.HttpContext); + return response.WriteAsJsonAsync(value, jsonTypeInfo: (JsonTypeInfo)options.GetTypeInfo(typeof(TValue)), contentType: null, cancellationToken); } /// @@ -203,15 +204,16 @@ private static async Task WriteAsJsonAsyncSlow( /// The type of object to write. /// A used to cancel the operation. /// The task object representing the asynchronous operation. - [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] - [RequiresDynamicCode(RequiresDynamicCodeMessage)] public static Task WriteAsJsonAsync( this HttpResponse response, object? value, Type type, CancellationToken cancellationToken = default) { - return response.WriteAsJsonAsync(value, type, options: null, contentType: null, cancellationToken); + ArgumentNullException.ThrowIfNull(response); + + var options = ResolveSerializerOptions(response.HttpContext); + return response.WriteAsJsonAsync(value, jsonTypeInfo: options.GetTypeInfo(type), contentType: null, cancellationToken); } /// From afd597e7fbfbe3440dda8884d355af88a8f33a1e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 13 Jan 2023 13:55:58 -0800 Subject: [PATCH 4/8] Removing ProblemDetails.Extension RUC/RDC --- .../src/ProblemDetails/ProblemDetails.cs | 3 - .../test/ProblemDetailsJsonConverterTest.cs | 66 +++++++++++++++++++ .../src/ProblemDetailsJsonContext.cs | 2 + .../DeveloperExceptionPageMiddlewareImpl.cs | 2 - ...tpValidationProblemDetailsJsonConverter.cs | 4 +- .../ProblemDetailsJsonConverter.cs | 33 ++++------ 6 files changed, 85 insertions(+), 25 deletions(-) diff --git a/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs b/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs index 582154c971a8..255b7860a15f 100644 --- a/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs +++ b/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Http; @@ -64,8 +63,6 @@ public class ProblemDetails [JsonExtensionData] public IDictionary Extensions { - [RequiresUnreferencedCode("JSON serialization and deserialization of ProblemDetails.Extensions might require types that cannot be statically analyzed.")] - [RequiresDynamicCode("JSON serialization and deserialization of ProblemDetails.Extensions might require types that cannot be statically analyzed.")] get => _extensions; } } diff --git a/src/Http/Http.Abstractions/test/ProblemDetailsJsonConverterTest.cs b/src/Http/Http.Abstractions/test/ProblemDetailsJsonConverterTest.cs index 81e4abee0635..666303b71df9 100644 --- a/src/Http/Http.Abstractions/test/ProblemDetailsJsonConverterTest.cs +++ b/src/Http/Http.Abstractions/test/ProblemDetailsJsonConverterTest.cs @@ -3,6 +3,7 @@ using System.Text; using System.Text.Json; +using System.Text.Json.Nodes; using Microsoft.AspNetCore.Http.Json; using Microsoft.AspNetCore.Mvc; @@ -92,6 +93,39 @@ public void Read_UsingJsonSerializerWorks() }); } + [Fact] + public void Read_WithUnknownTypeHandling_Works() + { + // Arrange + var type = "https://tools.ietf.org/html/rfc9110#section-15.5.5"; + var title = "Not found"; + var status = 404; + var detail = "Product not found"; + var instance = "http://example.com/products/14"; + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var json = $"{{\"type\":\"{type}\",\"title\":\"{title}\",\"status\":{status},\"detail\":\"{detail}\", \"instance\":\"{instance}\",\"traceId\":\"{traceId}\"}}"; + var serializerOptions = new JsonSerializerOptions(JsonSerializerOptions) { UnknownTypeHandling = System.Text.Json.Serialization.JsonUnknownTypeHandling.JsonNode }; + + // Act + var problemDetails = JsonSerializer.Deserialize(json, serializerOptions); + + // Assert + Assert.NotNull(problemDetails); + Assert.Equal(type, problemDetails!.Type); + Assert.Equal(title, problemDetails.Title); + Assert.Equal(status, problemDetails.Status); + Assert.Equal(instance, problemDetails.Instance); + Assert.Equal(detail, problemDetails.Detail); + Assert.Collection( + problemDetails.Extensions, + kvp => + { + Assert.Equal("traceId", kvp.Key); + Assert.IsAssignableFrom(kvp.Value!); + Assert.Equal(traceId, kvp.Value?.ToString()); + }); + } + [Fact] public void Read_WithSomeMissingValues_Works() { @@ -178,4 +212,36 @@ public void Write_WithSomeMissingContent_Works() var actual = Encoding.UTF8.GetString(stream.ToArray()); Assert.Equal(expected, actual); } + + [Fact] + public void Write_WithNullExtensionValue_Works() + { + // Arrange + var value = new ProblemDetails + { + Title = "Not found", + Type = "https://tools.ietf.org/html/rfc9110#section-15.5.5", + Status = 404, + Detail = "Product not found", + Instance = "http://example.com/products/14", + Extensions = + { + { "traceId", null }, + { "some-data", new[] { "value1", "value2" } } + } + }; + var expected = $"{{\"type\":\"{JsonEncodedText.Encode(value.Type)}\",\"title\":\"{value.Title}\",\"status\":{value.Status},\"detail\":\"{value.Detail}\",\"instance\":\"{JsonEncodedText.Encode(value.Instance)}\",\"traceId\":null,\"some-data\":[\"value1\",\"value2\"]}}"; + var converter = new ProblemDetailsJsonConverter(); + var stream = new MemoryStream(); + + // Act + using (var writer = new Utf8JsonWriter(stream)) + { + converter.Write(writer, value, JsonSerializerOptions); + } + + // Assert + var actual = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal(expected, actual); + } } diff --git a/src/Http/Http.Extensions/src/ProblemDetailsJsonContext.cs b/src/Http/Http.Extensions/src/ProblemDetailsJsonContext.cs index b247e359e483..287b7d93d954 100644 --- a/src/Http/Http.Extensions/src/ProblemDetailsJsonContext.cs +++ b/src/Http/Http.Extensions/src/ProblemDetailsJsonContext.cs @@ -9,6 +9,8 @@ namespace Microsoft.AspNetCore.Http; [JsonSerializable(typeof(ProblemDetails))] [JsonSerializable(typeof(HttpValidationProblemDetails))] +// ExtensionData +[JsonSerializable(typeof(IDictionary))] // Additional values are specified on JsonSerializerContext to support some values for extensions. // For example, the DeveloperExceptionMiddleware serializes its complex type to JsonElement, which problem details then needs to serialize. [JsonSerializable(typeof(JsonElement))] diff --git a/src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddlewareImpl.cs b/src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddlewareImpl.cs index 91e74ef529a6..bb34c6d64597 100644 --- a/src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddlewareImpl.cs +++ b/src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddlewareImpl.cs @@ -202,8 +202,6 @@ await _problemDetailsService.WriteAsync(new() } } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Values set on ProblemDetails.Extensions are supported by the default writer.")] - [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Values set on ProblemDetails.Extensions are supported by the default writer.")] private ProblemDetails CreateProblemDetails(ErrorContext errorContext, HttpContext httpContext) { var problemDetails = new ProblemDetails diff --git a/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs b/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs index d903bf99c34d..831ebc5fbd9d 100644 --- a/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs +++ b/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace Microsoft.AspNetCore.Http; @@ -23,6 +24,7 @@ public static HttpValidationProblemDetails ReadProblemDetails(ref Utf8JsonReader throw new JsonException("Unexpected end when reading JSON."); } + var objectTypeInfo = options.GetTypeInfo(typeof(object)); while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) { if (reader.ValueTextEquals(Errors.EncodedUtf8Bytes)) @@ -31,7 +33,7 @@ public static HttpValidationProblemDetails ReadProblemDetails(ref Utf8JsonReader } else { - ProblemDetailsJsonConverter.ReadValue(ref reader, problemDetails, options); + ProblemDetailsJsonConverter.ReadValue(ref reader, problemDetails, objectTypeInfo); } } diff --git a/src/Shared/ProblemDetails/ProblemDetailsJsonConverter.cs b/src/Shared/ProblemDetails/ProblemDetailsJsonConverter.cs index 13fa59608f2b..f72524daad9a 100644 --- a/src/Shared/ProblemDetails/ProblemDetailsJsonConverter.cs +++ b/src/Shared/ProblemDetails/ProblemDetailsJsonConverter.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; using Microsoft.AspNetCore.Mvc; namespace Microsoft.AspNetCore.Http; @@ -25,9 +26,10 @@ public override ProblemDetails Read(ref Utf8JsonReader reader, Type typeToConver throw new JsonException("Unexpected end when reading JSON."); } + var objectTypeInfo = options.GetTypeInfo(typeof(object)); while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) { - ReadValue(ref reader, problemDetails, options); + ReadValue(ref reader, problemDetails, objectTypeInfo); } if (reader.TokenType != JsonTokenType.EndObject) @@ -45,7 +47,7 @@ public override void Write(Utf8JsonWriter writer, ProblemDetails value, JsonSeri writer.WriteEndObject(); } - internal static void ReadValue(ref Utf8JsonReader reader, ProblemDetails value, JsonSerializerOptions options) + internal static void ReadValue(ref Utf8JsonReader reader, ProblemDetails value, JsonTypeInfo extensionDataTypeInfo) { if (TryReadStringProperty(ref reader, Type, out var propertyValue)) { @@ -79,14 +81,7 @@ internal static void ReadValue(ref Utf8JsonReader reader, ProblemDetails value, { var key = reader.GetString()!; reader.Read(); - ReadExtension(value, key, ref reader, options); - } - - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "ProblemDetails.Extensions is annotated to expose this warning to callers.")] - [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "ProblemDetails.Extensions is annotated to expose this warning to callers.")] - static void ReadExtension(ProblemDetails problemDetails, string key, ref Utf8JsonReader reader, JsonSerializerOptions options) - { - problemDetails.Extensions[key] = JsonSerializer.Deserialize(ref reader, typeof(object), options); + value.Extensions[key] = JsonSerializer.Deserialize(ref reader, extensionDataTypeInfo); } } @@ -130,17 +125,17 @@ internal static void WriteProblemDetails(Utf8JsonWriter writer, ProblemDetails v writer.WriteString(Instance, value.Instance); } - WriteExtensions(value, writer, options); - - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "ProblemDetails.Extensions is annotated to expose this warning to callers.")] - [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "ProblemDetails.Extensions is annotated to expose this warning to callers.")] - static void WriteExtensions(ProblemDetails problemDetails, Utf8JsonWriter writer, JsonSerializerOptions options) + foreach (var kvp in value.Extensions) { - foreach (var kvp in problemDetails.Extensions) + writer.WritePropertyName(kvp.Key); + + if (kvp.Value is null) + { + writer.WriteNullValue(); + } + else { - writer.WritePropertyName(kvp.Key); - // When AOT is enabled, Serialize will only work with values specified on the JsonContext. - JsonSerializer.Serialize(writer, kvp.Value, kvp.Value?.GetType() ?? typeof(object), options); + JsonSerializer.Serialize(writer, kvp.Value, options.GetTypeInfo(kvp.Value.GetType())); } } } From 5b432db62c4ed7ed37ae730e13f6010fd0212511 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 18 Jan 2023 14:42:54 -0800 Subject: [PATCH 5/8] Adding Test remote execution support --- eng/Dependencies.props | 1 + eng/Version.Details.xml | 4 ++++ eng/Versions.props | 1 + .../src/Microsoft.AspNetCore.Testing.csproj | 1 + .../RemoteExecutionSupportedAttribute.cs | 22 +++++++++++++++++++ 5 files changed, 29 insertions(+) create mode 100644 src/Testing/src/xunit/RemoteExecutionSupportedAttribute.cs diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 84b88d8fbb4d..663aca404a22 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -141,6 +141,7 @@ and are generated based on the last package release. + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7910f49e68be..6953742073d3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -319,5 +319,9 @@ https://github.com/dotnet/arcade 1b04d6de502c4108ada6ea8e5ccefdc2ddc3ee7b + + https://github.com/dotnet/arcade + 000000 + diff --git a/eng/Versions.props b/eng/Versions.props index 14ba44a615eb..351207a0f0b6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -137,6 +137,7 @@ 8.0.0-beta.23063.7 8.0.0-beta.23063.7 + 8.0.0-beta.23063.7 8.0.0-alpha.1.23062.2 diff --git a/src/Testing/src/Microsoft.AspNetCore.Testing.csproj b/src/Testing/src/Microsoft.AspNetCore.Testing.csproj index 12180a437d92..d48aac848c9d 100644 --- a/src/Testing/src/Microsoft.AspNetCore.Testing.csproj +++ b/src/Testing/src/Microsoft.AspNetCore.Testing.csproj @@ -40,6 +40,7 @@ --> + + { + // Arrange + var options = JsonOptions.DefaultSerializerOptions; + + // Assert + Assert.Null(options.TypeInfoResolver); + }, options); + } + + [ConditionalFact] + [RemoteExecutionSupported] + public void DefaultSerializerOptions_SetsTypeInfoResolverToDefault_WhenEnsureJsonTrimmabilityFalse() + { + var options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("Microsoft.AspNetCore.EnsureJsonTrimmability", false.ToString()); + + using var remoteHandle = RemoteExecutor.Invoke(static () => + { + // Arrange + var options = JsonOptions.DefaultSerializerOptions; + + // Assert + Assert.NotNull(options.TypeInfoResolver); + Assert.IsType(options.TypeInfoResolver); + }, options); + } +} diff --git a/src/Mvc/Mvc.Core/test/JsonOptionsTest.cs b/src/Mvc/Mvc.Core/test/JsonOptionsTest.cs new file mode 100644 index 000000000000..05209836bd45 --- /dev/null +++ b/src/Mvc/Mvc.Core/test/JsonOptionsTest.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.Json.Serialization.Metadata; +using Microsoft.AspNetCore.Testing; +using Microsoft.DotNet.RemoteExecutor; + +namespace Microsoft.AspNetCore.Mvc; + +public class JsonOptionsTest +{ + [ConditionalFact] + [RemoteExecutionSupported] + public void DefaultSerializerOptions_SetsTypeInfoResolverNull_WhenEnsureJsonTrimmabilityTrue() + { + var options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("Microsoft.AspNetCore.EnsureJsonTrimmability", true.ToString()); + + using var remoteHandle = RemoteExecutor.Invoke(static () => + { + // Arrange + var options = new JsonOptions().JsonSerializerOptions; + + // Assert + Assert.Null(options.TypeInfoResolver); + }, options); + } + + [ConditionalFact] + [RemoteExecutionSupported] + public void DefaultSerializerOptions_SetsTypeInfoResolverToDefault_WhenEnsureJsonTrimmabilityFalse() + { + var options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("Microsoft.AspNetCore.EnsureJsonTrimmability", false.ToString()); + + using var remoteHandle = RemoteExecutor.Invoke(static () => + { + // Arrange + var options = new JsonOptions().JsonSerializerOptions; + + // Assert + Assert.NotNull(options.TypeInfoResolver); + Assert.IsType(options.TypeInfoResolver); + }, options); + } +} From e3521da24002959655190abc8790c9c92e03afbd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 18 Jan 2023 14:47:33 -0800 Subject: [PATCH 7/8] Update ProblemDetails.cs --- .../Http.Abstractions/src/ProblemDetails/ProblemDetails.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs b/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs index 255b7860a15f..2d01289cdf19 100644 --- a/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs +++ b/src/Http/Http.Abstractions/src/ProblemDetails/ProblemDetails.cs @@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Mvc; [JsonConverter(typeof(ProblemDetailsJsonConverter))] public class ProblemDetails { - private readonly IDictionary _extensions = new Dictionary(StringComparer.Ordinal); - /// /// A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when /// dereferenced, it provide human-readable documentation for the problem type @@ -61,8 +59,5 @@ public class ProblemDetails /// In particular, complex types or collection types may not round-trip to the original type when using the built-in JSON or XML formatters. /// [JsonExtensionData] - public IDictionary Extensions - { - get => _extensions; - } + public IDictionary Extensions { get; } = new Dictionary(StringComparer.Ordinal); } From 4048eaedea4c3e52188137c61923ed39ca126cd0 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 19 Jan 2023 10:44:22 -0800 Subject: [PATCH 8/8] Update HttpValidationProblemDetailsJsonConverter.cs --- .../ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs b/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs index 831ebc5fbd9d..6686b2c0d8c1 100644 --- a/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs +++ b/src/Shared/ProblemDetails/HttpValidationProblemDetailsJsonConverter.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; -using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace Microsoft.AspNetCore.Http;