From d8da35a8c2b371608b6677f36dd277269538b7ff Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Tue, 20 Apr 2021 18:13:35 -0700 Subject: [PATCH 1/4] Add Put/Get methods to HttpClientJsonExtensions that take type metadata --- .../ref/System.Net.Http.Json.cs | 6 +- .../src/ILLink/ILLink.Suppressions.xml | 2 +- .../src/System.Net.Http.Json.csproj | 10 +- .../Json/HttpClientJsonExtensions.Post.cs | 23 ++++ .../Http/Json/HttpClientJsonExtensions.Put.cs | 23 ++++ .../src/System/Net/Http/Json/JsonContent.cs | 25 ++-- .../Net/Http/Json/JsonContent.netcoreapp.cs | 2 +- .../System/Net/Http/Json/JsonContentOfT.cs | 107 ++++++++++++++++++ .../Http/Json/JsonContentOfT.netcoreapp.cs | 26 +++++ .../HttpClientJsonExtensionsTests.cs | 76 +++++++++++-- 10 files changed, 271 insertions(+), 29 deletions(-) create mode 100644 src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs create mode 100644 src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs diff --git a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs index 0010ea20d123af..a1604f71b72c58 100644 --- a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs +++ b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs @@ -21,12 +21,16 @@ public static partial class HttpClientJsonExtensions public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, string? requestUri, TValue value, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri? requestUri, TValue value, System.Threading.CancellationToken cancellationToken) { throw null; } } public static partial class HttpContentJsonExtensions @@ -36,7 +40,7 @@ public static partial class HttpContentJsonExtensions public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } - public sealed partial class JsonContent : System.Net.Http.HttpContent + public partial class JsonContent : System.Net.Http.HttpContent { internal JsonContent() { } public System.Type ObjectType { get { throw null; } } diff --git a/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml index 540a559a8ee756..1eeb610b79c306 100644 --- a/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml @@ -5,7 +5,7 @@ ILLink IL2072 member - M:System.Net.Http.Json.JsonContent.<SerializeToStreamAsyncCore>d__18.MoveNext + M:System.Net.Http.Json.JsonContent.<SerializeToStreamAsyncCore>d__17.MoveNext ILLink diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index e9accb07aa992f..f9234b0031a302 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);net5.0;netstandard2.0;net461 true @@ -10,13 +10,14 @@ + + - + @@ -30,8 +31,7 @@ - + diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Post.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Post.cs index 86d91add941cb0..324fa61f76c7e1 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Post.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Post.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.Serialization.Metadata; using System.Threading; using System.Threading.Tasks; @@ -36,5 +37,27 @@ public static Task PostAsJsonAsync(this HttpClient public static Task PostAsJsonAsync(this HttpClient client, Uri? requestUri, TValue value, CancellationToken cancellationToken) => client.PostAsJsonAsync(requestUri, value, options: null, cancellationToken); + + public static Task PostAsJsonAsync(this HttpClient client, string? requestUri, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken = default) + { + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + JsonContent content = new(value, jsonTypeInfo); + return client.PostAsync(requestUri, content, cancellationToken); + } + + public static Task PostAsJsonAsync(this HttpClient client, Uri? requestUri, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken = default) + { + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + JsonContent content = new(value, jsonTypeInfo); + return client.PostAsync(requestUri, content, cancellationToken); + } } } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Put.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Put.cs index 0550254318a233..e04d6ec027f221 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Put.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Put.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.Serialization.Metadata; using System.Threading; using System.Threading.Tasks; @@ -36,5 +37,27 @@ public static Task PutAsJsonAsync(this HttpClient c public static Task PutAsJsonAsync(this HttpClient client, Uri? requestUri, TValue value, CancellationToken cancellationToken) => client.PutAsJsonAsync(requestUri, value, options: null, cancellationToken); + + public static Task PutAsJsonAsync(this HttpClient client, string? requestUri, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken = default) + { + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + JsonContent content = new(value, jsonTypeInfo); + return client.PutAsync(requestUri, content, cancellationToken); + } + + public static Task PutAsJsonAsync(this HttpClient client, Uri? requestUri, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken = default) + { + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + JsonContent content = new(value, jsonTypeInfo); + return client.PutAsync(requestUri, content, cancellationToken); + } } } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index cdd1472cd4e42d..10975e7e6d23f8 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -11,21 +11,19 @@ namespace System.Net.Http.Json { - public sealed partial class JsonContent : HttpContent + public partial class JsonContent : HttpContent { - internal const string JsonMediaType = "application/json"; - internal const string JsonType = "application"; - internal const string JsonSubtype = "json"; - private static MediaTypeHeaderValue DefaultMediaType - => new MediaTypeHeaderValue(JsonMediaType) { CharSet = "utf-8" }; + private JsonSerializerOptions _jsonSerializerOptions = null!; - internal static readonly JsonSerializerOptions s_defaultSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + private static MediaTypeHeaderValue DefaultMediaType => new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" }; + + internal static JsonSerializerOptions s_defaultSerializerOptions { get; } = new JsonSerializerOptions(JsonSerializerDefaults.Web); - private readonly JsonSerializerOptions? _jsonSerializerOptions; public Type ObjectType { get; } + public object? Value { get; } - private JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType, JsonSerializerOptions? options) + internal JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType) { if (inputType == null) { @@ -40,14 +38,17 @@ private JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? me Value = inputValue; ObjectType = inputType; Headers.ContentType = mediaType ?? DefaultMediaType; - _jsonSerializerOptions = options ?? s_defaultSerializerOptions; } public static JsonContent Create(T inputValue, MediaTypeHeaderValue? mediaType = null, JsonSerializerOptions? options = null) => Create(inputValue, typeof(T), mediaType, options); public static JsonContent Create(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType = null, JsonSerializerOptions? options = null) - => new JsonContent(inputValue, inputType, mediaType, options); + { + JsonContent content = new JsonContent(inputValue, inputType, mediaType); + content._jsonSerializerOptions = options ?? s_defaultSerializerOptions; + return content; + } protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) => SerializeToStreamAsyncCore(stream, async: true, CancellationToken.None); @@ -60,6 +61,8 @@ protected override bool TryComputeLength(out long length) private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) { + Debug.Assert(_jsonSerializerOptions != null); + Encoding? targetEncoding = GetEncoding(Headers.ContentType?.CharSet); // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs index 7520cd74ec5aeb..ee93ae1e21bd2a 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs @@ -7,7 +7,7 @@ namespace System.Net.Http.Json { - public sealed partial class JsonContent + public partial class JsonContent { protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken) => SerializeToStreamAsyncCore(stream, async: false, cancellationToken).GetAwaiter().GetResult(); diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs new file mode 100644 index 00000000000000..ec9b289073d67d --- /dev/null +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if !NETCOREAPP +using System.Diagnostics; +#endif +using System.IO; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http.Json +{ + internal sealed partial class JsonContent : JsonContent + { + private readonly JsonTypeInfo _typeInfo; + + private readonly TValue _typedValue; + + public JsonContent(TValue inputValue, JsonTypeInfo jsonTypeInfo) + : base (inputValue, typeof(TValue), mediaType: null) + { + _typeInfo = jsonTypeInfo ?? throw new ArgumentNullException(nameof(jsonTypeInfo)); + _typedValue = inputValue; + } + + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) + => SerializeToStreamAsyncCore(stream, async: true, CancellationToken.None); + + /// + /// Based on . + /// The difference is that this implementation calls overloads of that take type metadata directly. + /// This is done to avoid rooting unused, built-in s and reflection-based + /// warm-up logic (to reduce app size and be ILLinker-friendly), post ILLinker trimming. + /// + private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) + { + Encoding? targetEncoding = GetEncoding(Headers.ContentType?.CharSet); + + // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. + if (targetEncoding != null && targetEncoding != Encoding.UTF8) + { +#if NETCOREAPP + Stream transcodingStream = Encoding.CreateTranscodingStream(targetStream, targetEncoding, Encoding.UTF8, leaveOpen: true); + try + { + if (async) + { + await JsonSerializer.SerializeAsync(transcodingStream, _typedValue, _typeInfo, cancellationToken).ConfigureAwait(false); + } + else + { + // Have to use Utf8JsonWriter because JsonSerializer doesn't support sync serialization into stream directly. + // ToDo: Remove Utf8JsonWriter usage after https://github.com/dotnet/runtime/issues/1574 + using var writer = new Utf8JsonWriter(transcodingStream); + JsonSerializer.Serialize(writer, _typedValue, _typeInfo); + } + } + finally + { + // Dispose/DisposeAsync will flush any partial write buffers. In practice our partial write + // buffers should be empty as we expect JsonSerializer to emit only well-formed UTF-8 data. + if (async) + { + await transcodingStream.DisposeAsync().ConfigureAwait(false); + } + else + { + transcodingStream.Dispose(); + } + } +#else + Debug.Assert(async); + + using (TranscodingWriteStream transcodingStream = new TranscodingWriteStream(targetStream, targetEncoding)) + { + await JsonSerializer.SerializeAsync(transcodingStream, _typedValue, _typeInfo, cancellationToken).ConfigureAwait(false); + // The transcoding streams use Encoders and Decoders that have internal buffers. We need to flush these + // when there is no more data to be written. Stream.FlushAsync isn't suitable since it's + // acceptable to Flush a Stream (multiple times) prior to completion. + await transcodingStream.FinalWriteAsync(cancellationToken).ConfigureAwait(false); + } +#endif + } + else + { + if (async) + { + await JsonSerializer.SerializeAsync(targetStream, _typedValue, _typeInfo, cancellationToken).ConfigureAwait(false); + } + else + { +#if NETCOREAPP + // Have to use Utf8JsonWriter because JsonSerializer doesn't support sync serialization into stream directly. + // ToDo: Remove Utf8JsonWriter usage after https://github.com/dotnet/runtime/issues/1574 + using var writer = new Utf8JsonWriter(targetStream); + JsonSerializer.Serialize(writer, _typedValue, _typeInfo); +#else + Debug.Fail("Synchronous serialization is only supported since .NET 5.0"); +#endif + } + } + } + } +} diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs new file mode 100644 index 00000000000000..cc8ed25cca1997 --- /dev/null +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http.Json +{ + internal sealed partial class JsonContent + { + /// + /// This method is overriden to avoid accidentally rooting post ILLinker trimming. + /// See for more info. + /// + protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken) + => SerializeToStreamAsyncCore(stream, async: false, cancellationToken).GetAwaiter().GetResult(); + + /// + /// This method is overriden to avoid accidentally rooting post ILLinker trimming. + /// See for more info. + /// + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken) + => SerializeToStreamAsyncCore(stream, async: true, cancellationToken); + } +} diff --git a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs index 680e42e2aaa331..580806a40aac31 100644 --- a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs +++ b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs @@ -74,7 +74,7 @@ await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( await Assert.ThrowsAsync(() => client.GetFromJsonAsync(uri, typeof(Person))); await Assert.ThrowsAsync(() => client.GetFromJsonAsync(uri)); await Assert.ThrowsAsync(() => client.GetFromJsonAsync(uri, typeof(Person), JsonContext.Default)); - await Assert.ThrowsAsync(() => client.GetFromJsonAsync(uri, JsonContext.Default.Person)); + await Assert.ThrowsAsync(() => client.GetFromJsonAsync(uri, JsonContext.Default.Person)); } }, server => server.HandleRequestAsync(statusCode: HttpStatusCode.InternalServerError)); @@ -101,6 +101,18 @@ await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( using HttpResponseMessage response4 = await client.PostAsJsonAsync(uri, person, CancellationToken.None); Assert.True(response4.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response5 = await client.PostAsJsonAsync(uri.ToString(), person, JsonContext.Default.Person); + Assert.True(response5.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response6 = await client.PostAsJsonAsync(uri, person, JsonContext.Default.Person); + Assert.True(response6.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response7 = await client.PostAsJsonAsync(uri.ToString(), person, JsonContext.Default.Person, CancellationToken.None); + Assert.True(response7.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response8 = await client.PostAsJsonAsync(uri, person, JsonContext.Default.Person, CancellationToken.None); + Assert.True(response8.StatusCode == HttpStatusCode.OK); } }, async server => { @@ -133,6 +145,18 @@ await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( using HttpResponseMessage response4 = await client.PutAsJsonAsync(uri, person, CancellationToken.None); Assert.True(response4.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response5 = await client.PutAsJsonAsync(uri.ToString(), person, JsonContext.Default.Person); + Assert.True(response5.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response6 = await client.PutAsJsonAsync(uri, person, JsonContext.Default.Person); + Assert.True(response6.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response7 = await client.PutAsJsonAsync(uri.ToString(), person, JsonContext.Default.Person, CancellationToken.None); + Assert.True(response7.StatusCode == HttpStatusCode.OK); + + using HttpResponseMessage response8 = await client.PutAsJsonAsync(uri, person, JsonContext.Default.Person, CancellationToken.None); + Assert.True(response8.StatusCode == HttpStatusCode.OK); } }, async server => { @@ -153,20 +177,52 @@ await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( [Fact] public void TestHttpClientIsNullAsync() { + const string uriString = "http://example.com"; + const string clientParamName = "client"; + + HttpClient client = null; + Uri uri = new Uri(uriString); + + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uriString, typeof(Person))); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uri, typeof(Person))); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uriString)); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uri)); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uriString, typeof(Person), JsonContext.Default)); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uri, typeof(Person), JsonContext.Default)); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uriString, JsonContext.Default.Person)); + AssertExtensions.Throws(clientParamName, () => client.GetFromJsonAsync(uri, JsonContext.Default.Person)); + + AssertExtensions.Throws(clientParamName, () => client.PostAsJsonAsync(uriString, null)); + AssertExtensions.Throws(clientParamName, () => client.PostAsJsonAsync(uri, null)); + AssertExtensions.Throws(clientParamName, () => client.PostAsJsonAsync(uriString, null, JsonContext.Default.Person)); + AssertExtensions.Throws(clientParamName, () => client.PostAsJsonAsync(uri, null, JsonContext.Default.Person)); + + AssertExtensions.Throws(clientParamName, () => client.PutAsJsonAsync(uriString, null)); + AssertExtensions.Throws(clientParamName, () => client.PutAsJsonAsync(uri, null)); + AssertExtensions.Throws(clientParamName, () => client.PutAsJsonAsync(uriString, null, JsonContext.Default.Person)); + AssertExtensions.Throws(clientParamName, () => client.PutAsJsonAsync(uri, null, JsonContext.Default.Person)); + } + + [Fact] + public void TestTypeMetadataIsNull() + { + const string uriString = "http://example.com"; + const string jsonTypeInfoParamName = "client"; + const string contextParamName = "client"; + HttpClient client = null; - string uriString = "http://example.com"; Uri uri = new Uri(uriString); - AssertExtensions.Throws("client", () => client.GetFromJsonAsync(uriString, typeof(Person))); - AssertExtensions.Throws("client", () => client.GetFromJsonAsync(uri, typeof(Person))); - AssertExtensions.Throws("client", () => client.GetFromJsonAsync(uriString)); - AssertExtensions.Throws("client", () => client.GetFromJsonAsync(uri)); + AssertExtensions.Throws(contextParamName, () => client.GetFromJsonAsync(uriString, typeof(Person), JsonContext.Default)); + AssertExtensions.Throws(contextParamName, () => client.GetFromJsonAsync(uri, typeof(Person), JsonContext.Default)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.GetFromJsonAsync(uriString, JsonContext.Default.Person)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.GetFromJsonAsync(uri, JsonContext.Default.Person)); - AssertExtensions.Throws("client", () => client.PostAsJsonAsync(uriString, null)); - AssertExtensions.Throws("client", () => client.PostAsJsonAsync(uri, null)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.PostAsJsonAsync(uriString, null, JsonContext.Default.Person)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.PostAsJsonAsync(uri, null, JsonContext.Default.Person)); - AssertExtensions.Throws("client", () => client.PutAsJsonAsync(uriString, null)); - AssertExtensions.Throws("client", () => client.PutAsJsonAsync(uri, null)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.PutAsJsonAsync(uriString, null, JsonContext.Default.Person)); + AssertExtensions.Throws(jsonTypeInfoParamName, () => client.PutAsJsonAsync(uri, null, JsonContext.Default.Person)); } private void ValidateRequest(HttpRequestData requestData) From d854174de2dfdba12bfcf7263b808edb0eb19d3e Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Wed, 21 Apr 2021 13:54:57 -0700 Subject: [PATCH 2/4] Make JsonContentOfT derive directly from HttpContent --- .../ref/System.Net.Http.Json.cs | 2 +- .../src/System.Net.Http.Json.csproj | 3 +- .../src/System/Net/Http/Json/Helper.cs | 43 ++++++++++++++ .../Http/Json/HttpContentJsonExtensions.cs | 8 +-- .../src/System/Net/Http/Json/JsonContent.cs | 56 ++++--------------- .../Net/Http/Json/JsonContent.netcoreapp.cs | 2 +- .../System/Net/Http/Json/JsonContentOfT.cs | 12 +++- .../Http/Json/JsonContentOfT.netcoreapp.cs | 8 --- 8 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs diff --git a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs index a1604f71b72c58..4cd8fcd0569ac1 100644 --- a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs +++ b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.cs @@ -40,7 +40,7 @@ public static partial class HttpContentJsonExtensions public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } - public partial class JsonContent : System.Net.Http.HttpContent + public sealed partial class JsonContent : System.Net.Http.HttpContent { internal JsonContent() { } public System.Type ObjectType { get { throw null; } } diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index f9234b0031a302..d81a90fcf4dcb0 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -1,10 +1,11 @@ - + $(NetCoreAppCurrent);net5.0;netstandard2.0;net461 true enable + diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs new file mode 100644 index 00000000000000..a2315e5afb1d22 --- /dev/null +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs @@ -0,0 +1,43 @@ +// 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; +using System.Net.Http.Headers; +using System.Text; + +namespace System.Net.Http.Json +{ + internal static class Helper + { + internal static MediaTypeHeaderValue GetDefaultMediaType() => new("application/json") { CharSet = "utf-8" }; + + internal static Encoding? GetEncoding(string? charset) + { + Encoding? encoding = null; + + if (charset != null) + { + try + { + // Remove at most a single set of quotes. + if (charset.Length > 2 && charset[0] == '\"' && charset[charset.Length - 1] == '\"') + { + encoding = Encoding.GetEncoding(charset.Substring(1, charset.Length - 2)); + } + else + { + encoding = Encoding.GetEncoding(charset); + } + } + catch (ArgumentException e) + { + throw new InvalidOperationException(SR.CharSetInvalid, e); + } + + Debug.Assert(encoding != null); + } + + return encoding; + } + } +} diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs index ec0c7562776599..dc0a1b63c4b746 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs @@ -20,7 +20,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = JsonContent.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, type, sourceEncoding, options, cancellationToken); } @@ -32,7 +32,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = JsonContent.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, sourceEncoding, options, cancellationToken); } @@ -60,7 +60,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = JsonContent.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, type, sourceEncoding, context, cancellationToken); } @@ -72,7 +72,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = JsonContent.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, sourceEncoding, jsonTypeInfo, cancellationToken); } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index 10975e7e6d23f8..f4f5184249cf32 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NETCOREAPP using System.Diagnostics; +#endif using System.IO; using System.Net.Http.Headers; using System.Text; @@ -11,19 +13,15 @@ namespace System.Net.Http.Json { - public partial class JsonContent : HttpContent + public sealed partial class JsonContent : HttpContent { - private JsonSerializerOptions _jsonSerializerOptions = null!; - - private static MediaTypeHeaderValue DefaultMediaType => new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" }; - - internal static JsonSerializerOptions s_defaultSerializerOptions { get; } = new JsonSerializerOptions(JsonSerializerDefaults.Web); + internal static readonly JsonSerializerOptions s_defaultSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + private readonly JsonSerializerOptions? _jsonSerializerOptions; public Type ObjectType { get; } - public object? Value { get; } - internal JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType) + private JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType, JsonSerializerOptions? options) { if (inputType == null) { @@ -37,18 +35,15 @@ internal JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? m Value = inputValue; ObjectType = inputType; - Headers.ContentType = mediaType ?? DefaultMediaType; + Headers.ContentType = mediaType ?? Helper.GetDefaultMediaType(); + _jsonSerializerOptions = options ?? s_defaultSerializerOptions; } public static JsonContent Create(T inputValue, MediaTypeHeaderValue? mediaType = null, JsonSerializerOptions? options = null) => Create(inputValue, typeof(T), mediaType, options); public static JsonContent Create(object? inputValue, Type inputType, MediaTypeHeaderValue? mediaType = null, JsonSerializerOptions? options = null) - { - JsonContent content = new JsonContent(inputValue, inputType, mediaType); - content._jsonSerializerOptions = options ?? s_defaultSerializerOptions; - return content; - } + => new JsonContent(inputValue, inputType, mediaType, options); protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) => SerializeToStreamAsyncCore(stream, async: true, CancellationToken.None); @@ -61,9 +56,7 @@ protected override bool TryComputeLength(out long length) private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) { - Debug.Assert(_jsonSerializerOptions != null); - - Encoding? targetEncoding = GetEncoding(Headers.ContentType?.CharSet); + Encoding? targetEncoding = Helper.GetEncoding(Headers.ContentType?.CharSet); // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. if (targetEncoding != null && targetEncoding != Encoding.UTF8) @@ -129,34 +122,5 @@ private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, C } } } - - internal static Encoding? GetEncoding(string? charset) - { - Encoding? encoding = null; - - if (charset != null) - { - try - { - // Remove at most a single set of quotes. - if (charset.Length > 2 && charset[0] == '\"' && charset[charset.Length - 1] == '\"') - { - encoding = Encoding.GetEncoding(charset.Substring(1, charset.Length - 2)); - } - else - { - encoding = Encoding.GetEncoding(charset); - } - } - catch (ArgumentException e) - { - throw new InvalidOperationException(SR.CharSetInvalid, e); - } - - Debug.Assert(encoding != null); - } - - return encoding; - } } } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs index ee93ae1e21bd2a..7520cd74ec5aeb 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.netcoreapp.cs @@ -7,7 +7,7 @@ namespace System.Net.Http.Json { - public partial class JsonContent + public sealed partial class JsonContent { protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken) => SerializeToStreamAsyncCore(stream, async: false, cancellationToken).GetAwaiter().GetResult(); diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs index ec9b289073d67d..cf81df93798ab2 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs @@ -13,22 +13,28 @@ namespace System.Net.Http.Json { - internal sealed partial class JsonContent : JsonContent + internal sealed partial class JsonContent : HttpContent { private readonly JsonTypeInfo _typeInfo; private readonly TValue _typedValue; public JsonContent(TValue inputValue, JsonTypeInfo jsonTypeInfo) - : base (inputValue, typeof(TValue), mediaType: null) { _typeInfo = jsonTypeInfo ?? throw new ArgumentNullException(nameof(jsonTypeInfo)); _typedValue = inputValue; + Headers.ContentType = Helper.GetDefaultMediaType(); } protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) => SerializeToStreamAsyncCore(stream, async: true, CancellationToken.None); + protected override bool TryComputeLength(out long length) + { + length = 0; + return false; + } + /// /// Based on . /// The difference is that this implementation calls overloads of that take type metadata directly. @@ -37,7 +43,7 @@ protected override Task SerializeToStreamAsync(Stream stream, TransportContext? /// private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) { - Encoding? targetEncoding = GetEncoding(Headers.ContentType?.CharSet); + Encoding? targetEncoding = Helper.GetEncoding(Headers.ContentType?.CharSet); // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. if (targetEncoding != null && targetEncoding != Encoding.UTF8) diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs index cc8ed25cca1997..bd6bb97da22304 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.netcoreapp.cs @@ -9,17 +9,9 @@ namespace System.Net.Http.Json { internal sealed partial class JsonContent { - /// - /// This method is overriden to avoid accidentally rooting post ILLinker trimming. - /// See for more info. - /// protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken) => SerializeToStreamAsyncCore(stream, async: false, cancellationToken).GetAwaiter().GetResult(); - /// - /// This method is overriden to avoid accidentally rooting post ILLinker trimming. - /// See for more info. - /// protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken) => SerializeToStreamAsyncCore(stream, async: true, cancellationToken); } From 630d4ae12102f63cd1ce41b8a4d89d62c572df32 Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Wed, 21 Apr 2021 15:06:43 -0700 Subject: [PATCH 3/4] Fix linker error --- .../System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml index 1eeb610b79c306..accf0f2438a6b0 100644 --- a/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Net.Http.Json/src/ILLink/ILLink.Suppressions.xml @@ -5,7 +5,7 @@ ILLink IL2072 member - M:System.Net.Http.Json.JsonContent.<SerializeToStreamAsyncCore>d__17.MoveNext + M:System.Net.Http.Json.JsonContent.<SerializeToStreamAsyncCore>d__13.MoveNext ILLink From 34b168f2d26c45fd052085051491c2b6fee5ae2f Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Wed, 21 Apr 2021 15:25:27 -0700 Subject: [PATCH 4/4] Rename Helper to JsonHelpers --- .../System.Net.Http.Json/src/System.Net.Http.Json.csproj | 4 ++-- .../src/System/Net/Http/Json/HttpContentJsonExtensions.cs | 8 ++++---- .../src/System/Net/Http/Json/JsonContent.cs | 4 ++-- .../src/System/Net/Http/Json/JsonContentOfT.cs | 4 ++-- .../System/Net/Http/Json/{Helper.cs => JsonHelpers.cs} | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) rename src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/{Helper.cs => JsonHelpers.cs} (97%) diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index d81a90fcf4dcb0..a0b6916073f665 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -1,11 +1,11 @@ - + $(NetCoreAppCurrent);net5.0;netstandard2.0;net461 true enable - + diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs index dc0a1b63c4b746..503b4eedf22994 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs @@ -20,7 +20,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = JsonHelpers.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, type, sourceEncoding, options, cancellationToken); } @@ -32,7 +32,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = JsonHelpers.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, sourceEncoding, options, cancellationToken); } @@ -60,7 +60,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = JsonHelpers.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, type, sourceEncoding, context, cancellationToken); } @@ -72,7 +72,7 @@ public static partial class HttpContentJsonExtensions throw new ArgumentNullException(nameof(content)); } - Encoding? sourceEncoding = Helper.GetEncoding(content.Headers.ContentType?.CharSet); + Encoding? sourceEncoding = JsonHelpers.GetEncoding(content.Headers.ContentType?.CharSet); return ReadFromJsonAsyncCore(content, sourceEncoding, jsonTypeInfo, cancellationToken); } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index f4f5184249cf32..fdbae1b51cae33 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -35,7 +35,7 @@ private JsonContent(object? inputValue, Type inputType, MediaTypeHeaderValue? me Value = inputValue; ObjectType = inputType; - Headers.ContentType = mediaType ?? Helper.GetDefaultMediaType(); + Headers.ContentType = mediaType ?? JsonHelpers.GetDefaultMediaType(); _jsonSerializerOptions = options ?? s_defaultSerializerOptions; } @@ -56,7 +56,7 @@ protected override bool TryComputeLength(out long length) private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) { - Encoding? targetEncoding = Helper.GetEncoding(Headers.ContentType?.CharSet); + Encoding? targetEncoding = JsonHelpers.GetEncoding(Headers.ContentType?.CharSet); // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. if (targetEncoding != null && targetEncoding != Encoding.UTF8) diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs index cf81df93798ab2..5f786f8607af16 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContentOfT.cs @@ -23,7 +23,7 @@ public JsonContent(TValue inputValue, JsonTypeInfo jsonTypeInfo) { _typeInfo = jsonTypeInfo ?? throw new ArgumentNullException(nameof(jsonTypeInfo)); _typedValue = inputValue; - Headers.ContentType = Helper.GetDefaultMediaType(); + Headers.ContentType = JsonHelpers.GetDefaultMediaType(); } protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) @@ -43,7 +43,7 @@ protected override bool TryComputeLength(out long length) /// private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, CancellationToken cancellationToken) { - Encoding? targetEncoding = Helper.GetEncoding(Headers.ContentType?.CharSet); + Encoding? targetEncoding = JsonHelpers.GetEncoding(Headers.ContentType?.CharSet); // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. if (targetEncoding != null && targetEncoding != Encoding.UTF8) diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs similarity index 97% rename from src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs rename to src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs index a2315e5afb1d22..145340b0079ffc 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/Helper.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs @@ -7,7 +7,7 @@ namespace System.Net.Http.Json { - internal static class Helper + internal static class JsonHelpers { internal static MediaTypeHeaderValue GetDefaultMediaType() => new("application/json") { CharSet = "utf-8" };