クライアントからサーバーにオブジェクトを投稿するために SignalR を使用しています。オブジェクトには、UTC DateTime と LOCAL DateTime を持つ日付プロパティが含まれています (これは別の問題です)。私が気付いたのは、日付が現地時間の場合、たとえば「2013-01-08T10:35:59.8484157+00:00」の場合は常に、「文字列を DateTime に変換できませんでした」というエラーが表示されることです。調べてみると、解析しようとしている文字列のタイム ゾーン オフセット情報から「+」文字が失われ、変換エラーが発生しているようです。このキャラクターがどのように失われたかを理解しようとしています。
SignalR 要求の本文に見られるように、+ 文字は %2B としてエンコードされているため、SignalR はオブジェクトを json に正しくシリアル化し、エンコードしています。
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 メソッドが呼び出され、アラートが消えます。ローカル日付のアラートに対して同じアクションを実行すると、失敗します ([Create new alert] ボタンをクリックすると、UTC または LOCAL 日付のアラートがランダムに生成されます)。ブラウザ コンソールに、変換の失敗に関するエラーが表示されます。しかし、そうでない場合は、以下のエラーが表示されます。
[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)
前もって感謝します