#if !BESTHTTP_DISABLE_SIGNALR #if BESTHTTP_SIGNALR_WITH_JSONDOTNET using Newtonsoft.Json.Linq; #endif using System; using System.Collections; using System.Collections.Generic; namespace BestHTTP.SignalR.Messages { /// /// Keep-alive message sent by the server. No data sent with it. /// public sealed class KeepAliveMessage : IServerMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.KeepAlive; } } void IServerMessage.Parse(object data) { } } /// /// A message that may contains multiple sub-messages and additional informations. /// public sealed class MultiMessage : IServerMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.Multiple; } } /// /// Id of the sent message /// public string MessageId { get; private set; } /// /// True if it's an initialization message, false otherwise. /// public bool IsInitialization { get; private set; } /// /// Group token may be sent, if the group changed that the client belongs to. /// public string GroupsToken { get; private set; } /// /// The server suggests that the client should do a reconnect turn. /// public bool ShouldReconnect { get; private set; } /// /// Additional poll delay sent by the server. /// public TimeSpan? PollDelay { get; private set; } /// /// List of server messages sent inside this message. /// public List Data { get; private set; } void IServerMessage.Parse(object data) { IDictionary dic = data as IDictionary; object value; this.MessageId = dic["C"].ToString(); if (dic.TryGetValue("S", out value)) IsInitialization = int.Parse(value.ToString()) == 1 ? true : false; else IsInitialization = false; if (dic.TryGetValue("G", out value)) GroupsToken = value.ToString(); if (dic.TryGetValue("T", out value)) ShouldReconnect = int.Parse(value.ToString()) == 1 ? true : false; else ShouldReconnect = false; if (dic.TryGetValue("L", out value)) PollDelay = TimeSpan.FromMilliseconds(double.Parse(value.ToString())); IEnumerable enumerable = dic["M"] as IEnumerable; if (enumerable != null) { Data = new List(); foreach (object subData in enumerable) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET IDictionary subObj = subData as IDictionary; #else IDictionary subObj = subData as IDictionary; #endif IServerMessage subMsg = null; if (subObj != null) { if (subObj.ContainsKey("H")) subMsg = new MethodCallMessage(); else if (subObj.ContainsKey("I")) subMsg = new ProgressMessage(); else subMsg = new DataMessage(); } else subMsg = new DataMessage(); subMsg.Parse(subData); Data.Add(subMsg); } } } } /// /// A simple non-hub data message. It holds only one Data property. /// public sealed class DataMessage : IServerMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.Data; } } public object Data { get; private set; } void IServerMessage.Parse(object data) { this.Data = data; } } /// /// A Hub message that orders the client to call a method. /// public sealed class MethodCallMessage : IServerMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.MethodCall; } } /// /// The name of the Hub that the method is called on. /// public string Hub { get; private set; } /// /// Name of the Method. /// public string Method { get; private set; } /// /// Arguments of the method call. /// public object[] Arguments { get; private set; } /// /// State changes of the hub. It's handled automatically by the Hub. /// #if BESTHTTP_SIGNALR_WITH_JSONDOTNET public IDictionary State { get; private set; } #else public IDictionary State { get; private set; } #endif void IServerMessage.Parse(object data) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET IDictionary dic = data as IDictionary; #else IDictionary dic = data as IDictionary; #endif Hub = dic["H"].ToString(); Method = dic["M"].ToString(); List args = new List(); foreach (object arg in dic["A"] as IEnumerable) args.Add(arg); Arguments = args.ToArray(); #if BESTHTTP_SIGNALR_WITH_JSONDOTNET JToken value; if (dic.TryGetValue("S", out value)) State = value as IDictionary; #else object value; if (dic.TryGetValue("S", out value)) State = value as IDictionary; #endif } } /// /// Message of a server side method invocation result. /// public sealed class ResultMessage : IServerMessage, IHubMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.Result; } } /// /// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub. /// public UInt64 InvocationId { get; private set; } /// /// The return value of the server side method call, or null if the method's return type is void. /// public object ReturnValue { get; private set; } /// /// State changes of the hub. It's handled automatically by the Hub. /// #if BESTHTTP_SIGNALR_WITH_JSONDOTNET public IDictionary State { get; private set; } #else public IDictionary State { get; private set; } #endif void IServerMessage.Parse(object data) { IDictionary dic = data as IDictionary; InvocationId = UInt64.Parse(dic["I"].ToString()); object value; if (dic.TryGetValue("R", out value)) ReturnValue = value; if (dic.TryGetValue("S", out value)) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET State = value as IDictionary; #else State = value as IDictionary; #endif } } } public sealed class FailureMessage : IServerMessage, IHubMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.Failure; } } /// /// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub. /// public UInt64 InvocationId { get; private set; } /// /// True if it's a hub error. /// public bool IsHubError { get; private set; } /// /// If the method call failed, it contains the error message to detail what happened. /// public string ErrorMessage { get; private set; } /// /// A dictionary that may contain additional error data (can only be present for hub errors). It can be null. /// #if BESTHTTP_SIGNALR_WITH_JSONDOTNET public IDictionary AdditionalData { get; private set; } #else public IDictionary AdditionalData { get; private set; } #endif /// /// Stack trace of the error. It present only if detailed error reporting is turned on on the server (https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubconfiguration.enabledetailederrors%28v=vs.118%29.aspx). /// public string StackTrace { get; private set; } /// /// State changes of the hub. It's handled automatically by the Hub. /// #if BESTHTTP_SIGNALR_WITH_JSONDOTNET public IDictionary State { get; private set; } #else public IDictionary State { get; private set; } #endif void IServerMessage.Parse(object data) { IDictionary dic = data as IDictionary; InvocationId = UInt64.Parse(dic["I"].ToString()); object value; if (dic.TryGetValue("E", out value)) ErrorMessage = value.ToString(); if (dic.TryGetValue("H", out value)) IsHubError = int.Parse(value.ToString()) == 1 ? true : false; if (dic.TryGetValue("D", out value)) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET AdditionalData = value as IDictionary; #else AdditionalData = value as IDictionary; #endif } if (dic.TryGetValue("T", out value)) StackTrace = value.ToString(); if (dic.TryGetValue("S", out value)) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET State = value as IDictionary; #else State = value as IDictionary; #endif } } } /// /// When a server method is a long running method the server can send the information about the progress of execution of the method to the client. /// public sealed class ProgressMessage : IServerMessage, IHubMessage { MessageTypes IServerMessage.Type { get { return MessageTypes.Progress; } } /// /// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub. /// public UInt64 InvocationId { get; private set; } /// /// Current progress of the long running method. /// public double Progress { get; private set; } void IServerMessage.Parse(object data) { #if BESTHTTP_SIGNALR_WITH_JSONDOTNET IDictionary dic = data as IDictionary; #else IDictionary dic = data as IDictionary; #endif #if BESTHTTP_SIGNALR_WITH_JSONDOTNET IDictionary P = dic["P"] as IDictionary; #else IDictionary P = dic["P"] as IDictionary; #endif InvocationId = UInt64.Parse(P["I"].ToString()); Progress = double.Parse(P["D"].ToString()); } } } #endif