我正在使用 SignalR 将一个对象从客户端发布到服务器,该对象包含一个日期属性,该属性有时具有 UTC DateTime,有时具有 LOCAL DateTime(这本身就是一个单独的问题)。我注意到的是,只要日期是当地时间,例如“2013-01-08T10:35:59.8484157+00:00”,我就会收到“无法将字符串转换为 DateTime”错误。经检查,试图解析的字符串似乎从导致转换错误的时区偏移信息中丢失了“+”字符。我试图了解这个角色是如何丢失的。
SignalR 正确地将对象序列化为 json,并对其进行编码,因为 + 字符被编码为 %2B,这可以在 SignalR 请求的正文中看到
data=%7B%22H%22%3A%22alertshub%22%2C%22M%22%3A%22AcknowledgeAlert%22%2C%22A%22%3A%5B%7B%22Id%22%3A%22e2d65f79-6a03-4094-a00f-99fcd9b46a7a%22%2C%22StartDateTimeUtc%22%3A%222013-01-08T10%3A26%3A44.0849463%2B00%3A00%22%2C%22EndDateTimeUtc%22%3Anull%2C%22AcknowledgedDateTimeUtc%22%3Anull%2C%22Description%22%3A%22Test+Alert+17%22%7D%5D%2C%22I%22%3A0%7D
通过 UrlDecode 函数运行它会返回正确的值
data={
"H":"alertshub",
"M":"AcknowledgeAlert",
"A":[{
"Id":"e2d65f79-6a03-4094-a00f-99fcd9b46a7a",
"StartDateTimeUtc":"2013-01-08T10:26:44.0849463+00:00",
"EndDateTimeUtc":null,
"AcknowledgedDateTimeUtc":null,
"Description":"Test Alert 17"
}],
"I":0
}
但是在查看 SignalR 请求上下文时,正文列出了“+”,现在是一个空格。这会导致日期转换错误。似乎在 SignalR/JSON.NET/.NET(不确定是哪一个)的某处对发布的数据进行双重解码并将 + 转换为空格。
我创建了一个简单的 MVC 应用程序来演示这个问题,它在 GitHub 上http://github.com/davidthompson/SignalRPlusEncodingTest
示例应用程序运行后,单击带有 UTC 日期的任何警报旁边的确认按钮,这将调用集线器上的 SignalR 方法,并且警报将消失。如果您对具有本地日期的警报执行相同的操作,它将失败(单击“创建新警报”按钮,它将随机生成具有 UTC 或本地日期的警报)。浏览器控制台将显示有关转换失败的错误。但如果不是这样,收到的错误如下:
[10:36:04 GMT+0000 (GMT Standard Time)] SignalR: Could not convert string to DateTime: 2013-01-08T10:35:53.1401147 00:00. Path 'StartDateTimeUtc', line 1, position 144.
at Newtonsoft.Json.JsonReader.ReadAsDateTimeInternal()
at Newtonsoft.Json.Linq.JTokenReader.ReadAsDateTime()
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Microsoft.AspNet.SignalR.JTokenValue.ConvertTo(Type type)
at Microsoft.AspNet.SignalR.Hubs.DefaultParameterResolver.ResolveParameter(ParameterDescriptor descriptor, IJsonValue value)
at System.Linq.Enumerable.<ZipIterator>d__7a`3.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Microsoft.AspNet.SignalR.Hubs.DefaultParameterResolver.ResolveMethodParameters(MethodDescriptor method, IJsonValue[] values)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.InvokeHubPipeline(IHub hub, IJsonValue[] parameterValues, MethodDescriptor methodDescriptor, HubRequest hubRequest, StateChangeTracker tracker)
jquery....min.js (line 10)
提前致谢