public async Task <IHttpActionResult> ReconnectAndInvoke(string connectionId, string hubName, string methodName, [FromBody] HubNamesAndArguments hubNamesAndArguments)
        {
            Session session;
            bool    sessionRetrieved;

            sessionManagementLock.EnterReadLock();
            try
            {
                sessionRetrieved = sessions.TryGetValue(connectionId, out session);
            }
            finally
            {
                sessionManagementLock.ExitReadLock();
            }
            var hubMethodInvocation = new HubMethodInvocation
            {
                Arguments = hubNamesAndArguments.Arguments,
                Hub       = hubName,
                Method    = methodName
            };

            if (!sessionRetrieved)
            {
                try
                {
                    session = await PerformConnect(hubNamesAndArguments.HubNames, connectionId);
                }
                catch (ArgumentOutOfRangeException)
                {
                    return(NotFound());
                }
                return(Ok(new
                {
                    ConnectionId = session.ConnectionId,
                    ReturnValue = await ExecuteHubMethodInvocation(session, Request, hubMethodInvocation)
                }));
            }
            if (!session.Hubs.Keys.OrderBy(n => n).SequenceEqual(hubNamesAndArguments.HubNames.OrderBy(n => n), StringComparer.OrdinalIgnoreCase))
            {
                return(Conflict());
            }
            return(Ok(new
            {
                Events = GetEvents(session),
                ReturnValue = await ExecuteHubMethodInvocation(session, Request, hubMethodInvocation)
            }));
        }
        static async Task <object> ExecuteHubMethodInvocation(Session session, HttpRequestMessage requestMessage, HubMethodInvocation invocation)
        {
            object       invocationResult = null;
            ReflectedHub reflectedHub;

            if (!Hubs.TryGetValue(invocation.Hub, out reflectedHub))
            {
                invocationResult = new { Error = "Hub not found" }
            }
            ;
            else
            {
                IReadOnlyDictionary <int, Tuple <Type, Type[], FastMethodInfo> > overloads;
                if (!reflectedHub.MethodNames.TryGetValue(invocation.Method, out overloads))
                {
                    invocationResult = new { Error = "Hub method not found" }
                }
                ;
                else
                {
                    Tuple <Type, Type[], FastMethodInfo> overload;
                    if (!overloads.TryGetValue(invocation.Arguments?.Count ?? 0, out overload))
                    {
                        invocationResult = new { Error = "Hub method not found" }
                    }
                    ;
                    else
                    {
                        var argumentsList = new List <object>();
                        var p             = -1;
                        if (invocation.Arguments != null)
                        {
                            foreach (var child in invocation.Arguments.Children())
                            {
                                argumentsList.Add(child.ToObject(overload.Item2[++p]));
                            }
                        }
                        try
                        {
                            using (var hub = Hub.GetHub(requestMessage, invocation.Hub, session))
                                invocationResult = overload.Item3.Invoke(hub, argumentsList.ToArray());
                            if (invocationResult != null)
                            {
                                var task = invocationResult as Task;
                                if (task != null)
                                {
                                    await task.ContinueWith(t =>
                                    {
                                        if (t.IsFaulted)
                                        {
                                            invocationResult = new { Error = string.Format("{0}: {1}", t.Exception.GetType().Name, t.Exception.Message) }
                                        }
                                        ;
                                        else
                                        {
                                            var type = t.GetType();
                                            if (type.IsGenericType)
                                            {
                                                invocationResult = taskValueGetters.GetOrAdd(type, CreateTaskValueGetter).Invoke(t);
                                            }
                                        }
                                    });
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            invocationResult = new { Error = string.Format("{0}: {1}", ex.GetType().Name, ex.Message) };
                        }
                    }
                }
            }
            return(invocationResult);
        }