Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use local Newtonsoft settings when serializing/deserializing instead of assigning global settings #3402

Merged
merged 2 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/src/HttpMessageHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ internal static void SetHttpRequestMessageContent<T>(HttpRequestMessage requestM
#if NET451
requestMessage.Content = new ObjectContent<T>(entity, s_jsonFormatter);
#else
string str = JsonConvert.SerializeObject(entity);
string str = JsonConvert.SerializeObject(entity, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());
requestMessage.Content = new StringContent(str, Encoding.UTF8, ApplicationJson);
#endif
}
}
}
}
4 changes: 2 additions & 2 deletions common/src/service/ExceptionHandlingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ public static async Task<ErrorCode> GetExceptionCodeAsync(HttpResponseMessage re
int errorCodeValue = (int)ErrorCode.InvalidErrorCode;
try
{
IoTHubExceptionResult responseContent = JsonConvert.DeserializeObject<IoTHubExceptionResult>(responseContentStr);
IoTHubExceptionResult responseContent = JsonConvert.DeserializeObject<IoTHubExceptionResult>(responseContentStr, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());

try
{
var messageFields = new Dictionary<string, string>();
if (responseContent?.Message != null)
{
messageFields = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseContent.Message);
messageFields = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseContent.Message, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());
}

if (messageFields != null
Expand Down
7 changes: 2 additions & 5 deletions common/src/service/HttpClientHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ public HttpClientHelper(
_defaultErrorMapping = defaultErrorMapping;
_defaultOperationTimeout = timeout;

// Specify the JsonSerializerSettings. Check JsonSerializerSettingsInitializer for more details.
JsonConvert.DefaultSettings = JsonSerializerSettingsInitializer.GetJsonSerializerSettingsDelegate();

// We need two types of HttpClients, one with our default operation timeout, and one without. The one without will rely on
// a cancellation token.

Expand Down Expand Up @@ -312,7 +309,7 @@ private static async Task<T> ReadResponseMessageAsync<T>(HttpResponseMessage mes
}

string str = await message.Content.ReadHttpContentAsStringAsync(token).ConfigureAwait(false);
T entity = JsonConvert.DeserializeObject<T>(str);
T entity = JsonConvert.DeserializeObject<T>(str, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());

// Etag in the header is considered authoritative
var eTagHolder = entity as IETagHolder;
Expand Down Expand Up @@ -575,7 +572,7 @@ private Task PostAsyncHelper<T1>(
}
else
{
string str = JsonConvert.SerializeObject(entity);
string str = JsonConvert.SerializeObject(entity, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());
requestMsg.Content = new StringContent(str, System.Text.Encoding.UTF8, ApplicationJson);
}
}
Expand Down
36 changes: 36 additions & 0 deletions e2e/test/JsonSerializerSettingsInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using Newtonsoft.Json;

namespace Microsoft.Azure.Devices.E2ETests
{
/// <summary>
/// A class to initialize JsonSerializerSettings which can be applied to the project.
/// </summary>
internal static class JsonSerializerSettingsInitializer
{
/// <summary>
/// A static instance of JsonSerializerSettings which sets DateParseHandling to None.
/// </summary>
/// <remarks>
/// By default, serializing/deserializing with Newtonsoft.Json will try to parse date-formatted
/// strings to a date type, which drops trailing zeros in the microseconds date portion. By
/// specifying DateParseHandling with None, the original string will be read as-is. For more details
/// about the known issue, see https://github.com/JamesNK/Newtonsoft.Json/issues/1511.
/// </remarks>
private static readonly JsonSerializerSettings s_settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None
};

/// <summary>
/// Returns JsonSerializerSettings Func delegate
/// </summary>
internal static JsonSerializerSettings GetJsonSerializerSettings()
{
return s_settings;
}
}
}
2 changes: 1 addition & 1 deletion e2e/test/helpers/ImportExportHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static Stream BuildImportStream<T>(IReadOnlyList<T> items)

foreach (T item in items)
{
itemsFileSb.AppendLine(JsonConvert.SerializeObject(item));
itemsFileSb.AppendLine(JsonConvert.SerializeObject(item, JsonSerializerSettingsInitializer.GetJsonSerializerSettings()));
}

byte[] itemsFileInBytes = Encoding.Default.GetBytes(itemsFileSb.ToString());
Expand Down
56 changes: 28 additions & 28 deletions e2e/test/iothub/method/MethodE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,91 +29,91 @@ public class MethodE2ETests : E2EMsTestBase

private static readonly TimeSpan s_defaultMethodTimeoutMinutes = TimeSpan.FromMinutes(2);

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponse_Mqtt()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_Tcp_Only, SetDeviceReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponse_MqttWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_WebSocket_Only, SetDeviceReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceUnsubscribes_Mqtt()
{
await SendMethodAndUnsubscribeAsync(Client.TransportType.Mqtt_Tcp_Only, SubscribeAndUnsubscribeMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceUnsubscribes_MqttWs()
{
await SendMethodAndUnsubscribeAsync(Client.TransportType.Mqtt_WebSocket_Only, SubscribeAndUnsubscribeMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponseWithDefaultMethodHandler_Mqtt()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_Tcp_Only, SetDeviceReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponseWithDefaultMethodHandler_MqttWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_WebSocket_Only, SetDeviceReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponse_Amqp()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_Tcp_Only, SetDeviceReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponse_AmqpWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_WebSocket_Only, SetDeviceReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceUnsubscribes_Amqp()
{
await SendMethodAndUnsubscribeAsync(Client.TransportType.Amqp_Tcp_Only, SubscribeAndUnsubscribeMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceUnsubscribes_AmqpWs()
{
await SendMethodAndUnsubscribeAsync(Client.TransportType.Amqp_WebSocket_Only, SubscribeAndUnsubscribeMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponseWithDefaultMethodHandler_Amqp()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_Tcp_Only, SetDeviceReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_DeviceReceivesMethodAndResponseWithDefaultMethodHandler_AmqpWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_WebSocket_Only, SetDeviceReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceSendsMethodThroughProxyWithDefaultTimeout()
{
Expand All @@ -129,7 +129,7 @@ await SendMethodAndRespondAsync(
.ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceSendsMethodThroughProxyWithCustomTimeout()
{
Expand All @@ -146,7 +146,7 @@ await SendMethodAndRespondAsync(
.ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceInvokeDeviceMethodWithUnknownDeviceThrows()
{
Expand All @@ -172,63 +172,63 @@ public async Task Method_ServiceInvokeDeviceMethodWithUnknownDeviceThrows()
await serviceClient.CloseAsync().ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponse_Mqtt()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_Tcp_Only, SetModuleReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponse_MqttWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_WebSocket_Only, SetModuleReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponseWithDefaultMethodHandler_Mqtt()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_Tcp_Only, SetModuleReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponseWithDefaultMethodHandler_MqttWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Mqtt_WebSocket_Only, SetModuleReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponse_Amqp()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_Tcp_Only, SetModuleReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponse_AmqpWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_WebSocket_Only, SetModuleReceiveMethodAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponseWithDefaultMethodHandler_Amqp()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_Tcp_Only, SetModuleReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ModuleReceivesMethodAndResponseWithDefaultMethodHandler_AmqpWs()
{
await SendMethodAndRespondAsync(Client.TransportType.Amqp_WebSocket_Only, SetModuleReceiveMethodDefaultHandlerAsync).ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceInvokeDeviceMethodWithUnknownModuleThrows()
{
Expand Down Expand Up @@ -256,7 +256,7 @@ public async Task Method_ServiceInvokeDeviceMethodWithUnknownModuleThrows()
await serviceClient.CloseAsync().ConfigureAwait(false);
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceInvokeDeviceMethodWithNullPayload_DoesNotThrow()
{
Expand Down Expand Up @@ -302,15 +302,15 @@ await deviceClient
}
}

[TestMethodWithRetry(Max=3)]
[TestMethodWithRetry(Max = 3)]
[Timeout(TestTimeoutMilliseconds)]
public async Task Method_ServiceInvokeDeviceMethodWithDateTimePayload_DoesNotThrow()
{
// arrange

var date = new DateTimeOffset(638107582284599400, TimeSpan.FromHours(1));

string responseJson = JsonConvert.SerializeObject(new TestDateTime { Iso8601String = date.ToString("o", CultureInfo.InvariantCulture) });
string responseJson = JsonConvert.SerializeObject(new TestDateTime { Iso8601String = date.ToString("o", CultureInfo.InvariantCulture) }, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());
byte[] responseBytes = Encoding.UTF8.GetBytes(responseJson);

const string commandName = "GetDateTime";
Expand Down Expand Up @@ -340,7 +340,7 @@ await deviceClient

CloudToDeviceMethodResult result = await serviceClient.InvokeDeviceMethodAsync(testDevice.Id, c2dMethod).ConfigureAwait(false);
string actualResultJson = result.GetPayloadAsJson();
TestDateTime myDtoValue = JsonConvert.DeserializeObject<TestDateTime>(actualResultJson);
TestDateTime myDtoValue = JsonConvert.DeserializeObject<TestDateTime>(actualResultJson, JsonSerializerSettingsInitializer.GetJsonSerializerSettings());
string value = myDtoValue.Iso8601String;

Action act = () => DateTimeOffset.ParseExact(value, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
Expand Down
Loading