protected override void OnMessageReceived(JSONNode message) { // We have to handle progress updates first in order to ensure old clients that receive // progress updates enter the return value branch and then no-op when they can't find // the callback in the map (because the message["I"[ value will not be a valid callback ID) if (message["P"] != null) { var result = HubResult.FromJson(message); Action <HubResult> callback; lock (_callbacks) { if (!_callbacks.TryGetValue(result.ProgressUpdate.Id, out callback)) { Trace(TraceLevels.Messages, "Callback with id " + result.ProgressUpdate.Id + " not found!"); } } callback?.Invoke(result); } else if (message["I"] != null) { var result = HubResult.FromJson(message); Action <HubResult> callback; lock (_callbacks) { if (_callbacks.TryGetValue(result.Id, out callback)) { _callbacks.Remove(result.Id); } else { Trace(TraceLevels.Messages, "Callback with id " + result.Id + " not found!"); } } if (callback != null) { callback(result); } } else { var invocation = HubInvocation.FromJson(message); HubProxy hubProxy; if (_hubs.TryGetValue(invocation.Hub, out hubProxy)) { if (invocation.State != null) { foreach (var state in invocation.State) { hubProxy[state.Key] = state.Value; } } hubProxy.InvokeEvent(invocation.Method, invocation.Args); } base.OnMessageReceived(message); } }