Permalink
Browse files

Fixes #60.

Don't only downcast to SignalRCommand, deserialize json as a fallback.
  • Loading branch information...
1 parent b953b23 commit 2e8588155ddffe0454ea121567888e2f19c36b1e @davidfowl davidfowl committed Nov 16, 2011
@@ -51,7 +51,6 @@
</Compile>
<Compile Include="ConfigPeerUrlSource.cs" />
<Compile Include="HttpHelper.cs" />
- <Compile Include="IJsonSerializer.cs" />
<Compile Include="IPeerUrlSource.cs" />
<Compile Include="JavaScriptSerializerAdapter.cs" />
<Compile Include="PeerToPeerHelper.cs" />
@@ -15,7 +15,7 @@ public void ExtractsClientIdFromRequest()
var request = new Mock<HttpRequestBase>();
request.Setup(m => m["clientId"]).Returns("1");
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
@@ -29,7 +29,7 @@ public void IsAliveReturnsTrueIfClientIsConnected()
var response = new Mock<HttpResponseBase>();
response.Setup(m => m.IsClientConnected).Returns(true);
context.Setup(m => m.Response).Returns(response.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
@@ -43,7 +43,7 @@ public void DisconnectRaisedDisconnectEvent()
var response = new Mock<HttpResponseBase>();
response.Setup(m => m.IsClientConnected).Returns(false);
context.Setup(m => m.Response).Returns(response.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
@@ -65,7 +65,7 @@ public void ConnectRequestAddsConnectionToHeartBeat()
request.Setup(m => m.Path).Returns("/foo/connect");
request.Setup(m => m["clientId"]).Returns("1");
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
var connection = new Mock<IConnection>();
@@ -82,7 +82,7 @@ public void ConnectRequestRaisesConnectEvent()
request.Setup(m => m.Path).Returns("/foo/connect");
request.Setup(m => m["clientId"]).Returns("1");
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
var connection = new Mock<IConnection>();
@@ -107,7 +107,7 @@ public void ConnectRequestCallsReceiveOnConnectionThenSend()
request.Setup(m => m["clientId"]).Returns("1");
context.Setup(m => m.Response).Returns(response.Object);
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new Mock<LongPollingTransport>(context.Object, json.Object, heartBeat.Object) { CallBase = true };
var connection = new Mock<IConnection>();
@@ -135,7 +135,7 @@ public void RequestWithMessageIdCallsReceiveOnConnectionThenSend()
request.Setup(m => m["messageId"]).Returns("20");
context.Setup(m => m.Response).Returns(response.Object);
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new Mock<LongPollingTransport>(context.Object, json.Object, heartBeat.Object) { CallBase = true };
var connection = new Mock<IConnection>();
@@ -163,7 +163,7 @@ public void ProcessRequestReturnsNullIfRequestWithMalformedMessageId()
request.Setup(m => m["messageId"]).Returns("fff");
context.Setup(m => m.Response).Returns(response.Object);
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
var connection = new Mock<IConnection>();
@@ -184,7 +184,7 @@ public void SendSetsContentTypeAndWritesSerializedResponse()
request.Setup(m => m["clientId"]).Returns("1");
context.Setup(m => m.Response).Returns(response.Object);
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
json.Setup(m => m.Stringify(obj)).Returns("A=1");
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
@@ -205,7 +205,7 @@ public void SendRequestRaisesOnReceived()
form["data"] = "some data";
request.Setup(m => m.Form).Returns(form);
context.Setup(m => m.Request).Returns(request.Object);
- var json = new Mock<IJsonStringifier>();
+ var json = new Mock<IJsonSerializer>();
var heartBeat = new Mock<ITransportHeartBeat>();
var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object);
var connection = new Mock<IConnection>();
View
@@ -10,18 +10,21 @@ public class Connection : IConnection
{
private readonly Signaler _signaler;
private readonly IMessageStore _store;
+ private readonly IJsonSerializer _jsonSerializer;
private readonly string _baseSignal;
private readonly string _clientId;
private readonly HashSet<string> _signals;
private readonly HashSet<string> _groups;
private readonly object _lockObj = new object();
public Connection(IMessageStore store,
+ IJsonSerializer jsonSerializer,
Signaler signaler,
string baseSignal,
string clientId,
IEnumerable<string> signals)
: this(store,
+ jsonSerializer,
signaler,
baseSignal,
clientId,
@@ -31,13 +34,15 @@ public class Connection : IConnection
}
public Connection(IMessageStore store,
+ IJsonSerializer jsonSerializer,
Signaler signaler,
string baseSignal,
string clientId,
IEnumerable<string> signals,
IEnumerable<string> groups)
{
_store = store;
+ _jsonSerializer = jsonSerializer;
_signaler = signaler;
_baseSignal = baseSignal;
_clientId = clientId;
@@ -103,6 +108,7 @@ public Task<PersistentResponse> ReceiveAsync(long messageId)
public static IConnection GetConnection(string connectionType)
{
return new Connection(DependencyResolver.Resolve<IMessageStore>(),
+ DependencyResolver.Resolve<IJsonSerializer>(),
Signaler.Instance,
connectionType,
null,
@@ -193,12 +199,12 @@ private void ProcessCommands(IEnumerable<Message> messages)
{
foreach (var message in messages)
{
- var command = message.Value as SignalCommand;
+ var command = GetCommand(message);
if (command == null)
{
continue;
}
-
+
switch (command.Type)
{
case CommandType.AddToGroup:
@@ -211,6 +217,26 @@ private void ProcessCommands(IEnumerable<Message> messages)
}
}
+ private SignalCommand GetCommand(Message message)
+ {
+ var command = message.Value as SignalCommand;
+
+ // Optimization for in memory message store
+ if (command != null)
+ {
+ return command;
+ }
+
+ // Otherwise deserialize the message value
+ string value = message.Value as string;
+ if (value == null)
+ {
+ return null;
+ }
+
+ return _jsonSerializer.Parse<SignalCommand>(value);
+ }
+
private Task SendMessage(string message, object value)
{
return _store.Save(message, value)
@@ -30,6 +30,7 @@ public class HubDispatcher : PersistentConnection
private readonly string _url;
private readonly IHubLocator _hubLocator;
private readonly IHubTypeResolver _hubTypeResolver;
+ private readonly IJsonSerializer _jsonSerializer;
private HttpCookieCollection _cookies;
private IPrincipal _user;
@@ -41,7 +42,7 @@ public HubDispatcher(string url)
DependencyResolver.Resolve<IClientIdFactory>(),
DependencyResolver.Resolve<IActionResolver>(),
DependencyResolver.Resolve<IJavaScriptProxyGenerator>(),
- DependencyResolver.Resolve<IJsonStringifier>(),
+ DependencyResolver.Resolve<IJsonSerializer>(),
DependencyResolver.Resolve<IHubLocator>(),
DependencyResolver.Resolve<IHubTypeResolver>(),
url)
@@ -54,14 +55,15 @@ public HubDispatcher(string url)
IClientIdFactory clientIdFactory,
IActionResolver actionResolver,
IJavaScriptProxyGenerator proxyGenerator,
- IJsonStringifier jsonStringifier,
+ IJsonSerializer jsonSerializer,
IHubLocator hubLocator,
IHubTypeResolver hubTypeResolver,
string url)
- : base(signaler, clientIdFactory, store, jsonStringifier)
+ : base(signaler, clientIdFactory, store, jsonSerializer)
{
_hubFactory = hubFactory;
_store = store;
+ _jsonSerializer = jsonSerializer;
_signaler = signaler;
_actionResolver = actionResolver;
_proxyGenerator = proxyGenerator;
@@ -241,7 +243,7 @@ protected override IConnection CreateConnection(string clientId, IEnumerable<str
IEnumerable<string> hubSignals = clientHubInfo.SelectMany(info => GetSignals(info, clientId));
- return new Connection(_store, _signaler, null, clientId, hubSignals, groups);
+ return new Connection(_store, _jsonSerializer, _signaler, null, clientId, hubSignals, groups);
}
private IEnumerable<string> GetSignals(ClientHubInfo hubInfo, string clientId)
@@ -1,9 +1,11 @@
using System;
-namespace SignalR.ScaleOut
+namespace SignalR
{
- public interface IJsonSerializer : IJsonStringifier
+ public interface IJsonSerializer
{
+ string Stringify(object value);
+
object Parse(string json);
object Parse(string json, Type targetType);
@@ -1,8 +0,0 @@
-
-namespace SignalR
-{
- public interface IJsonStringifier
- {
- string Stringify(object obj);
- }
-}
@@ -88,12 +88,12 @@ internal DefaultDependencyResolver()
Register(typeof(IMessageStore), () => store.Value);
- var serialzier = new JavaScriptSerializerAdapter(new JavaScriptSerializer
+ var serializer = new JavaScriptSerializerAdapter(new JavaScriptSerializer
{
MaxJsonLength = 30 * 1024 * 1024
});
- Register(typeof(IJsonStringifier), () => serialzier);
+ Register(typeof(IJsonSerializer), () => serializer);
Register(typeof(IActionResolver), () => new DefaultActionResolver());
Register(typeof(IHubActivator), () => new DefaultHubActivator());
@@ -1,10 +1,11 @@
-using System.Web.Script.Serialization;
+using System;
+using System.Web.Script.Serialization;
namespace SignalR
{
- public class JavaScriptSerializerAdapter : IJsonStringifier
+ public class JavaScriptSerializerAdapter : IJsonSerializer
{
- private JavaScriptSerializer _serializer;
+ private readonly JavaScriptSerializer _serializer;
public JavaScriptSerializerAdapter(JavaScriptSerializer serializer)
{
@@ -15,5 +16,20 @@ public string Stringify(object obj)
{
return _serializer.Serialize(obj);
}
+
+ public object Parse(string json)
+ {
+ return _serializer.DeserializeObject(json);
+ }
+
+ public object Parse(string json, Type targetType)
+ {
+ return _serializer.Deserialize(json, targetType);
+ }
+
+ public T Parse<T>(string json)
+ {
+ return _serializer.Deserialize<T>(json);
+ }
}
}
@@ -15,7 +15,7 @@ public abstract class PersistentConnection : HttpTaskAsyncHandler, IGroupManager
private readonly Signaler _signaler;
private readonly IMessageStore _store;
- private readonly IJsonStringifier _jsonStringifier;
+ private readonly IJsonSerializer _jsonSerializer;
private readonly IClientIdFactory _clientIdFactory;
protected ITransport _transport;
@@ -24,19 +24,19 @@ protected PersistentConnection()
: this(Signaler.Instance,
DependencyResolver.Resolve<IClientIdFactory>(),
DependencyResolver.Resolve<IMessageStore>(),
- DependencyResolver.Resolve<IJsonStringifier>())
+ DependencyResolver.Resolve<IJsonSerializer>())
{
}
protected PersistentConnection(Signaler signaler,
IClientIdFactory clientIdFactory,
IMessageStore store,
- IJsonStringifier jsonStringifier)
+ IJsonSerializer jsonSerializer)
{
_signaler = signaler;
_clientIdFactory = clientIdFactory;
_store = store;
- _jsonStringifier = jsonStringifier;
+ _jsonSerializer = jsonSerializer;
}
// Static events intended for use when measuring performance
@@ -75,7 +75,7 @@ public override Task ProcessRequestAsync(HttpContext context)
if (IsNegotiationRequest(context.Request))
{
context.Response.ContentType = Json.MimeType;
- context.Response.Write(_jsonStringifier.Stringify(new
+ context.Response.Write(_jsonSerializer.Stringify(new
{
Url = VirtualPathUtility.ToAbsolute(context.Request.AppRelativeCurrentExecutionFilePath.Replace("/negotiate", "")),
ClientId = _clientIdFactory.CreateClientId(contextBase)
@@ -147,7 +147,7 @@ protected virtual IConnection CreateConnection(string clientId, IEnumerable<stri
clientId + "." + SignalrCommand
};
- return new Connection(_store, _signaler, DefaultSignal, clientId, signals, groups);
+ return new Connection(_store, _jsonSerializer, _signaler, DefaultSignal, clientId, signals, groups);
}
protected virtual void OnConnected(HttpContextBase context, string clientId) { }
@@ -253,7 +253,7 @@ private bool IsNegotiationRequest(HttpRequest httpRequest)
private ITransport GetTransport(HttpContextBase context)
{
return TransportManager.GetTransport(context) ??
- new LongPollingTransport(context, _jsonStringifier);
+ new LongPollingTransport(context, _jsonSerializer);
}
private static void OnSending()
@@ -15,8 +15,8 @@ public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(HubModule));
- TransportManager.Register("longPolling", context => new LongPollingTransport(context, DependencyResolver.Resolve<IJsonStringifier>()));
- TransportManager.Register("forever", context => new ForeverTransport(context, DependencyResolver.Resolve<IJsonStringifier>()));
+ TransportManager.Register("longPolling", context => new LongPollingTransport(context, DependencyResolver.Resolve<IJsonSerializer>()));
+ TransportManager.Register("forever", context => new ForeverTransport(context, DependencyResolver.Resolve<IJsonSerializer>()));
}
}
}
View
@@ -65,6 +65,7 @@
<Compile Include="Hubs\IHub.cs" />
<Compile Include="Hubs\IHubTypeResolver.cs" />
<Compile Include="IClientIdFactory.cs" />
+ <Compile Include="IJsonSerializer.cs" />
<Compile Include="Infrastructure\ReflectionHelper.cs" />
<Compile Include="IPersistentConnectionFactory.cs" />
<Compile Include="IGroupManager.cs" />
@@ -82,7 +83,6 @@
<Compile Include="Hubs\IHubFactory.cs" />
<Compile Include="Hubs\IHubLocator.cs" />
<Compile Include="Hubs\SignalAgent.cs" />
- <Compile Include="IJsonStringifier.cs" />
<Compile Include="Infrastructure\DependencyResolver.cs" />
<Compile Include="Infrastructure\NullJavaScriptMinifier.cs" />
<Compile Include="Infrastructure\IDependencyResolver.cs" />
Oops, something went wrong.

0 comments on commit 2e85881

Please sign in to comment.