GetTwinAsync()引发序列化强制转换异常-> DatetimeOffset

时间:2018-06-21 07:49:44

标签: azure azure-iot-hub

您好,当我们尝试从IOT集线器获取设备孪生时,会出现此投射错误

@Edge(value="children") public class NodeChild extends CommonBo { ... }

我们使用设备SDK, Microsoft.Azure.Devices.Common.Exceptions.IotHubException: Unable to cast object of type 'System.DateTimeOffset' to type 'System.DateTime'. ---> System.InvalidCastException: Unable to cast object of type 'System.DateTimeOffset' to type 'System.DateTime'. at Microsoft.Azure.Devices.Shared.TwinJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Microsoft.Azure.Devices.HttpClientHelper.<ReadResponseMessageAsync>d__17`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.Devices.HttpClientHelper.<>c__DisplayClass10_0`1.<<GetAsync>b__9>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.Devices.HttpClientHelper.<ExecuteAsync>d__35.MoveNext() --- End of inner exception stack trace --- at Microsoft.Azure.Devices.HttpClientHelper.<ExecuteAsync>d__35.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.Devices.HttpClientHelper.<GetAsync>d__10`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 到目前为止,我还无法从本地复制此文件,但是它是在我们的一种测试环境中发生的。

3 个答案:

答案 0 :(得分:1)

使用registryManager中的Rest API获取双胞胎设备:

        #region get the device twin

        var finfo = registryManager.GetType().GetField("httpClientHelper", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(registryManager);
        HttpClient client = finfo.GetType().GetField("httpClientObj", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(finfo) as HttpClient;
        var provider = finfo.GetType().GetField("authenticationHeaderProvider", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(finfo);
        dynamic sastoken = provider.GetType().InvokeMember("GetAuthorizationHeader", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, provider, null);
        if (client.DefaultRequestHeaders.Authorization == null)
            client.DefaultRequestHeaders.Add("Authorization", sastoken);

        var jsontext = client.GetStringAsync("https://{yourNamespace}.azure-devices.net/twins/{yourDeviceId}?api-version=2018-04-01").Result;

        // log this jsontext

        var twin = JsonConvert.DeserializeObject<Twin>(jsontext);

        #endregion

在您的“不良”环境中使用上述代码段查看设备的json格式文本。

答案 1 :(得分:1)

我们花了一些时间才弄清楚,但请检查默认json序列化程序是否已将DateParseHandling配置为DateTimeOffset。

      JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            DateParseHandling = DateParseHandling.DateTimeOffset
        };

在这种情况下,您将不得不覆盖DeviceTwin的序列化程序,因为其他代码必须取决于此设置。

答案 2 :(得分:0)

尽管DateTimeOffset结构提供了比DateTime结构更大的时区感知能力,但DateTime参数在方法调用中更常用。因此,将DateTimeOffset值转换为DateTime值,反之亦然的能力尤其重要。更多信息here

我认为您需要检查不同环境中的时区设置以及双胞胎设备的属性值。