parent
a79c7da4d2
commit
3fa10f92ad
|
|
@ -153,6 +153,29 @@ namespace Microsoft.AspNetCore.Internal
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool ReadForType(JsonTextReader reader, Type type)
|
||||
{
|
||||
// Explicity read values as dates from JSON with reader.
|
||||
// We do this because otherwise dates are read as strings
|
||||
// and the JsonSerializer will use a conversion method that won't
|
||||
// preserve UTC in DateTime.Kind for UTC ISO8601 dates
|
||||
if (type == typeof(DateTime) || type == typeof(DateTime?))
|
||||
{
|
||||
reader.ReadAsDateTime();
|
||||
}
|
||||
else if (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?))
|
||||
{
|
||||
reader.ReadAsDateTimeOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
// TokenType will be None if there is no more content
|
||||
return reader.TokenType != JsonToken.None;
|
||||
}
|
||||
|
||||
private class JsonArrayPool<T> : IArrayPool<T>
|
||||
{
|
||||
private readonly ArrayPool<T> _inner;
|
||||
|
|
|
|||
|
|
@ -168,12 +168,12 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
error = JsonUtils.ReadAsString(reader, ErrorPropertyName);
|
||||
break;
|
||||
case ResultPropertyName:
|
||||
JsonUtils.CheckRead(reader);
|
||||
|
||||
hasResult = true;
|
||||
|
||||
if (string.IsNullOrEmpty(invocationId))
|
||||
{
|
||||
JsonUtils.CheckRead(reader);
|
||||
|
||||
// If we don't have an invocation id then we need to store it as a JToken so we can parse it later
|
||||
resultToken = JToken.Load(reader);
|
||||
}
|
||||
|
|
@ -181,6 +181,12 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
{
|
||||
// If we have an invocation id already we can parse the end result
|
||||
var returnType = binder.GetReturnType(invocationId);
|
||||
|
||||
if (!JsonUtils.ReadForType(reader, returnType))
|
||||
{
|
||||
throw new JsonReaderException("Unexpected end when reading JSON");
|
||||
}
|
||||
|
||||
result = PayloadSerializer.Deserialize(reader, returnType);
|
||||
}
|
||||
break;
|
||||
|
|
@ -599,13 +605,25 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
return new InvocationMessage(invocationId, target, arguments);
|
||||
}
|
||||
|
||||
private bool ReadArgumentAsType(JsonTextReader reader, IReadOnlyList<Type> paramTypes, int paramIndex)
|
||||
{
|
||||
if (paramIndex < paramTypes.Count)
|
||||
{
|
||||
var paramType = paramTypes[paramIndex];
|
||||
|
||||
return JsonUtils.ReadForType(reader, paramType);
|
||||
}
|
||||
|
||||
return reader.Read();
|
||||
}
|
||||
|
||||
private object[] BindArguments(JsonTextReader reader, IReadOnlyList<Type> paramTypes)
|
||||
{
|
||||
object[] arguments = null;
|
||||
var paramIndex = 0;
|
||||
var argumentsCount = 0;
|
||||
|
||||
while (reader.Read())
|
||||
while (ReadArgumentAsType(reader, paramTypes, paramIndex))
|
||||
{
|
||||
if (reader.TokenType == JsonToken.EndArray)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -260,6 +260,37 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
|
|||
Assert.Equal(expectedMessage, bindingFailure.BindingFailure.SourceException.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{'type':1,'invocationId':'42','target':'foo','arguments':['2007-03-01T13:00:00Z']}")]
|
||||
[InlineData("{'type':1,'invocationId':'42','arguments':['2007-03-01T13:00:00Z'],'target':'foo'}")]
|
||||
public void DateTimeArgumentPreservesUtcKind(string input)
|
||||
{
|
||||
var binder = new TestBinder(new[] { typeof(DateTime) });
|
||||
var protocol = new JsonHubProtocol();
|
||||
var data = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(Frame(input)));
|
||||
protocol.TryParseMessage(ref data, binder, out var message);
|
||||
var invocationMessage = Assert.IsType<InvocationMessage>(message);
|
||||
|
||||
Assert.Single(invocationMessage.Arguments);
|
||||
var dt = Assert.IsType<DateTime>(invocationMessage.Arguments[0]);
|
||||
Assert.Equal(DateTimeKind.Utc, dt.Kind);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{'type':3,'invocationId':'42','target':'foo','arguments':[],'result':'2007-03-01T13:00:00Z'}")]
|
||||
[InlineData("{'type':3,'target':'foo','arguments':[],'result':'2007-03-01T13:00:00Z','invocationId':'42'}")]
|
||||
public void DateTimeReturnValuePreservesUtcKind(string input)
|
||||
{
|
||||
var binder = new TestBinder(typeof(DateTime));
|
||||
var protocol = new JsonHubProtocol();
|
||||
var data = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(Frame(input)));
|
||||
protocol.TryParseMessage(ref data, binder, out var message);
|
||||
var invocationMessage = Assert.IsType<CompletionMessage>(message);
|
||||
|
||||
var dt = Assert.IsType<DateTime>(invocationMessage.Result);
|
||||
Assert.Equal(DateTimeKind.Utc, dt.Kind);
|
||||
}
|
||||
|
||||
private static string Frame(string input)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(input);
|
||||
|
|
|
|||
Loading…
Reference in New Issue