DemoHubSample.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. #if !BESTHTTP_DISABLE_SIGNALR
  2. using System;
  3. using UnityEngine;
  4. using BestHTTP.SignalR;
  5. using BestHTTP.SignalR.Hubs;
  6. using BestHTTP.SignalR.Messages;
  7. using BestHTTP.SignalR.JsonEncoders;
  8. using BestHTTP.Examples;
  9. class DemoHubSample : MonoBehaviour
  10. {
  11. readonly Uri URI = new Uri("https://besthttpsignalr.azurewebsites.net/signalr");
  12. /// <summary>
  13. /// The SignalR connection instance
  14. /// </summary>
  15. Connection signalRConnection;
  16. /// <summary>
  17. /// DemoHub client side implementation
  18. /// </summary>
  19. DemoHub demoHub;
  20. /// <summary>
  21. /// TypedDemoHub client side implementation
  22. /// </summary>
  23. TypedDemoHub typedDemoHub;
  24. /// <summary>
  25. /// VB .NET Hub
  26. /// </summary>
  27. Hub vbDemoHub;
  28. /// <summary>
  29. /// Result of the VB demo's ReadStateValue call
  30. /// </summary>
  31. string vbReadStateResult = string.Empty;
  32. Vector2 scrollPos;
  33. void Start()
  34. {
  35. // Create the hubs
  36. demoHub = new DemoHub();
  37. typedDemoHub = new TypedDemoHub();
  38. vbDemoHub = new Hub("vbdemo");
  39. // Create the SignalR connection, passing all the three hubs to it
  40. signalRConnection = new Connection(URI, demoHub, typedDemoHub, vbDemoHub);
  41. // Switch from the default encoder to the LitJson Encoder because it can handle the complex types too.
  42. signalRConnection.JsonEncoder = new LitJsonEncoder();
  43. // Call the demo functions when we successfully connect to the server
  44. signalRConnection.OnConnected += (connection) =>
  45. {
  46. var person = new { Name = "Foo", Age = 20, Address = new { Street = "One Microsoft Way", Zip = "98052" } };
  47. // Call the demo functions
  48. demoHub.AddToGroups();
  49. demoHub.GetValue();
  50. demoHub.TaskWithException();
  51. demoHub.GenericTaskWithException();
  52. demoHub.SynchronousException();
  53. demoHub.DynamicTask();
  54. demoHub.PassingDynamicComplex(person);
  55. demoHub.SimpleArray(new int[] { 5, 5, 6 });
  56. demoHub.ComplexType(person);
  57. demoHub.ComplexArray(new object[] { person, person, person });
  58. demoHub.ReportProgress("Long running job!");
  59. demoHub.Overload();
  60. // set some state
  61. demoHub.State["name"] = "Testing state!";
  62. demoHub.ReadStateValue();
  63. demoHub.PlainTask();
  64. demoHub.GenericTaskWithContinueWith();
  65. typedDemoHub.Echo("Typed echo callback");
  66. // vbDemo is not wrapped in a hub class, it would contain only one function
  67. vbDemoHub.Call("readStateValue", (hub, msg, result) => vbReadStateResult = string.Format("Read some state from VB.NET! => {0}", result.ReturnValue == null ? "undefined" : result.ReturnValue.ToString()));
  68. };
  69. // Start opening the signalR connection
  70. signalRConnection.Open();
  71. }
  72. void OnDestroy()
  73. {
  74. // Close the connection when we are closing this sample
  75. signalRConnection.Close();
  76. }
  77. void OnGUI()
  78. {
  79. GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
  80. {
  81. scrollPos = GUILayout.BeginScrollView(scrollPos, false, false);
  82. GUILayout.BeginVertical();
  83. demoHub.Draw();
  84. typedDemoHub.Draw();
  85. GUILayout.Label("Read State Value");
  86. GUILayout.BeginHorizontal();
  87. GUILayout.Space(20);
  88. GUILayout.Label(vbReadStateResult);
  89. GUILayout.EndHorizontal();
  90. GUILayout.Space(10);
  91. GUILayout.EndVertical();
  92. GUILayout.EndScrollView();
  93. });
  94. }
  95. }
  96. /// <summary>
  97. /// Wrapper class of the 'TypedDemoHub' hub
  98. /// </summary>
  99. class TypedDemoHub : Hub
  100. {
  101. string typedEchoResult = string.Empty;
  102. string typedEchoClientResult = string.Empty;
  103. public TypedDemoHub()
  104. :base("typeddemohub")
  105. {
  106. // Setup server-called functions
  107. base.On("Echo", Echo);
  108. }
  109. #region Server Called Functions
  110. /// <summary>
  111. /// Server-called, client side implementation of the Echo function
  112. /// </summary>
  113. private void Echo(Hub hub, MethodCallMessage methodCall)
  114. {
  115. typedEchoClientResult = string.Format("{0} #{1} triggered!", methodCall.Arguments[0], methodCall.Arguments[1]);
  116. }
  117. #endregion
  118. #region Client Called Function(s)
  119. /// <summary>
  120. /// Client-called, server side implementation of the Echo function.
  121. /// When the function successfully executed on the server the OnEcho_Done callback function will be called.
  122. /// </summary>
  123. public void Echo(string msg)
  124. {
  125. base.Call("echo", OnEcho_Done, msg);
  126. }
  127. /// <summary>
  128. /// When the function successfully executed on the server this callback function will be called.
  129. /// </summary>
  130. private void OnEcho_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  131. {
  132. typedEchoResult = "TypedDemoHub.Echo(string message) invoked!";
  133. }
  134. #endregion
  135. public void Draw()
  136. {
  137. GUILayout.Label("Typed callback");
  138. GUILayout.BeginHorizontal();
  139. GUILayout.Space(20);
  140. GUILayout.BeginVertical();
  141. GUILayout.Label(typedEchoResult);
  142. GUILayout.Label(typedEchoClientResult);
  143. GUILayout.EndVertical();
  144. GUILayout.EndHorizontal();
  145. GUILayout.Space(10);
  146. }
  147. }
  148. /// <summary>
  149. /// A wrapper class for the 'DemoHub' hub.
  150. /// </summary>
  151. class DemoHub : Hub
  152. {
  153. #region Private fields
  154. // These fields are here to store results of the function calls
  155. float longRunningJobProgress = 0f;
  156. string longRunningJobStatus = "Not Started!";
  157. string fromArbitraryCodeResult = string.Empty;
  158. string groupAddedResult = string.Empty;
  159. string dynamicTaskResult = string.Empty;
  160. string genericTaskResult = string.Empty;
  161. string taskWithExceptionResult = string.Empty;
  162. string genericTaskWithExceptionResult = string.Empty;
  163. string synchronousExceptionResult = string.Empty;
  164. string invokingHubMethodWithDynamicResult = string.Empty;
  165. string simpleArrayResult = string.Empty;
  166. string complexTypeResult = string.Empty;
  167. string complexArrayResult = string.Empty;
  168. string voidOverloadResult = string.Empty;
  169. string intOverloadResult = string.Empty;
  170. string readStateResult = string.Empty;
  171. string plainTaskResult = string.Empty;
  172. string genericTaskWithContinueWithResult = string.Empty;
  173. GUIMessageList invokeResults = new GUIMessageList();
  174. #endregion
  175. public DemoHub()
  176. : base("demo")
  177. {
  178. // Setup server-called functions
  179. base.On("invoke", Invoke);
  180. base.On("signal", Signal);
  181. base.On("groupAdded", GroupAdded);
  182. base.On("fromArbitraryCode", FromArbitraryCode);
  183. }
  184. #region Client Called Functions
  185. #region ReportProgress
  186. public void ReportProgress(string arg)
  187. {
  188. Call("reportProgress", OnLongRunningJob_Done, null, OnLongRunningJob_Progress, arg);
  189. }
  190. public void OnLongRunningJob_Progress(Hub hub, ClientMessage originialMessage, ProgressMessage progress)
  191. {
  192. longRunningJobProgress = (float)progress.Progress;
  193. longRunningJobStatus = progress.Progress.ToString() + "%";
  194. }
  195. public void OnLongRunningJob_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  196. {
  197. longRunningJobStatus = result.ReturnValue.ToString();
  198. MultipleCalls();
  199. }
  200. #endregion
  201. public void MultipleCalls()
  202. {
  203. base.Call("multipleCalls");
  204. }
  205. #region DynamicTask
  206. public void DynamicTask()
  207. {
  208. base.Call("dynamicTask", OnDynamicTask_Done, OnDynamicTask_Failed);
  209. }
  210. private void OnDynamicTask_Failed(Hub hub, ClientMessage originalMessage, FailureMessage result)
  211. {
  212. dynamicTaskResult = string.Format("The dynamic task failed :( {0}", result.ErrorMessage);
  213. }
  214. private void OnDynamicTask_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  215. {
  216. dynamicTaskResult = string.Format("The dynamic task! {0}", result.ReturnValue);
  217. }
  218. #endregion
  219. public void AddToGroups()
  220. {
  221. base.Call("addToGroups");
  222. }
  223. public void GetValue()
  224. {
  225. base.Call("getValue", (hub, msg, result) => genericTaskResult = string.Format("The value is {0} after 5 seconds", result.ReturnValue));
  226. }
  227. public void TaskWithException()
  228. {
  229. // This method call must fail, so only error handler added
  230. base.Call("taskWithException", null, (Hub hub, ClientMessage msg, FailureMessage error) => taskWithExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  231. }
  232. public void GenericTaskWithException()
  233. {
  234. // This method call must fail, so only error handler added
  235. base.Call("genericTaskWithException", null, (Hub hub, ClientMessage msg, FailureMessage error) => genericTaskWithExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  236. }
  237. public void SynchronousException()
  238. {
  239. // This method call must fail, so only error handler added
  240. base.Call("synchronousException", null, (Hub hub, ClientMessage msg, FailureMessage error) => synchronousExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  241. }
  242. public void PassingDynamicComplex(object person)
  243. {
  244. base.Call("passingDynamicComplex", (hub, msg, result) => invokingHubMethodWithDynamicResult = string.Format("The person's age is {0}", result.ReturnValue), person);
  245. }
  246. public void SimpleArray(int[] array)
  247. {
  248. base.Call("simpleArray", (hub, msg, result) => simpleArrayResult = "Simple array works!", array);
  249. }
  250. public void ComplexType(object person)
  251. {
  252. base.Call("complexType", (hub, msg, result) => complexTypeResult = string.Format("Complex Type -> {0}", (this as IHub).Connection.JsonEncoder.Encode(this.State["person"])), person);
  253. }
  254. public void ComplexArray(object[] complexArray)
  255. {
  256. // We need to cast the object array to object to keep it as an array
  257. // http://stackoverflow.com/questions/36350/how-to-pass-a-single-object-to-a-params-object
  258. base.Call("ComplexArray", (hub, msg, result) => complexArrayResult = "Complex Array Works!", (object)complexArray);
  259. }
  260. #region Overloads
  261. public void Overload()
  262. {
  263. base.Call("Overload", OnVoidOverload_Done);
  264. }
  265. private void OnVoidOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  266. {
  267. voidOverloadResult = "Void Overload called";
  268. Overload(101);
  269. }
  270. public void Overload(int number)
  271. {
  272. base.Call("Overload", OnIntOverload_Done, number);
  273. }
  274. private void OnIntOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  275. {
  276. intOverloadResult = string.Format("Overload with return value called => {0}", result.ReturnValue.ToString());
  277. }
  278. #endregion
  279. public void ReadStateValue()
  280. {
  281. base.Call("readStateValue", (hub, msg, result) => readStateResult = string.Format("Read some state! => {0}", result.ReturnValue));
  282. }
  283. public void PlainTask()
  284. {
  285. base.Call("plainTask", (hub, msg, result) => plainTaskResult = "Plain Task Result");
  286. }
  287. public void GenericTaskWithContinueWith()
  288. {
  289. base.Call("genericTaskWithContinueWith", (hub, msg, result) => genericTaskWithContinueWithResult = result.ReturnValue.ToString());
  290. }
  291. #endregion
  292. #region Server Called Functions
  293. private void FromArbitraryCode(Hub hub, MethodCallMessage methodCall)
  294. {
  295. fromArbitraryCodeResult = methodCall.Arguments[0] as string;
  296. }
  297. private void GroupAdded(Hub hub, MethodCallMessage methodCall)
  298. {
  299. if (!string.IsNullOrEmpty(groupAddedResult))
  300. groupAddedResult = "Group Already Added!";
  301. else
  302. groupAddedResult = "Group Added!";
  303. }
  304. private void Signal(Hub hub, MethodCallMessage methodCall)
  305. {
  306. dynamicTaskResult = string.Format("The dynamic task! {0}", methodCall.Arguments[0]);
  307. }
  308. private void Invoke(Hub hub, MethodCallMessage methodCall)
  309. {
  310. invokeResults.Add(string.Format("{0} client state index -> {1}", methodCall.Arguments[0], this.State["index"]));
  311. }
  312. #endregion
  313. #region Draw
  314. /// <summary>
  315. /// Display the result's of the function calls.
  316. /// </summary>
  317. public void Draw()
  318. {
  319. GUILayout.Label("Arbitrary Code");
  320. GUILayout.BeginHorizontal();
  321. GUILayout.Space(20);
  322. GUILayout.Label(string.Format("Sending {0} from arbitrary code without the hub itself!", fromArbitraryCodeResult));
  323. GUILayout.EndHorizontal();
  324. GUILayout.Space(10);
  325. GUILayout.Label("Group Added");
  326. GUILayout.BeginHorizontal();
  327. GUILayout.Space(20);
  328. GUILayout.Label(groupAddedResult);
  329. GUILayout.EndHorizontal();
  330. GUILayout.Space(10);
  331. GUILayout.Label("Dynamic Task");
  332. GUILayout.BeginHorizontal();
  333. GUILayout.Space(20);
  334. GUILayout.Label(dynamicTaskResult);
  335. GUILayout.EndHorizontal();
  336. GUILayout.Space(10);
  337. GUILayout.Label("Report Progress");
  338. GUILayout.BeginHorizontal();
  339. GUILayout.Space(20);
  340. GUILayout.BeginVertical();
  341. GUILayout.Label(longRunningJobStatus);
  342. GUILayout.HorizontalSlider(longRunningJobProgress, 0, 100);
  343. GUILayout.EndVertical();
  344. GUILayout.EndHorizontal();
  345. GUILayout.Space(10);
  346. GUILayout.Label("Generic Task");
  347. GUILayout.BeginHorizontal();
  348. GUILayout.Space(20);
  349. GUILayout.Label(genericTaskResult);
  350. GUILayout.EndHorizontal();
  351. GUILayout.Space(10);
  352. GUILayout.Label("Task With Exception");
  353. GUILayout.BeginHorizontal();
  354. GUILayout.Space(20);
  355. GUILayout.Label(taskWithExceptionResult);
  356. GUILayout.EndHorizontal();
  357. GUILayout.Space(10);
  358. GUILayout.Label("Generic Task With Exception");
  359. GUILayout.BeginHorizontal();
  360. GUILayout.Space(20);
  361. GUILayout.Label(genericTaskWithExceptionResult);
  362. GUILayout.EndHorizontal();
  363. GUILayout.Space(10);
  364. GUILayout.Label("Synchronous Exception");
  365. GUILayout.BeginHorizontal();
  366. GUILayout.Space(20);
  367. GUILayout.Label(synchronousExceptionResult);
  368. GUILayout.EndHorizontal();
  369. GUILayout.Space(10);
  370. GUILayout.Label("Invoking hub method with dynamic");
  371. GUILayout.BeginHorizontal();
  372. GUILayout.Space(20);
  373. GUILayout.Label(invokingHubMethodWithDynamicResult);
  374. GUILayout.EndHorizontal();
  375. GUILayout.Space(10);
  376. GUILayout.Label("Simple Array");
  377. GUILayout.BeginHorizontal();
  378. GUILayout.Space(20);
  379. GUILayout.Label(simpleArrayResult);
  380. GUILayout.EndHorizontal();
  381. GUILayout.Space(10);
  382. GUILayout.Label("Complex Type");
  383. GUILayout.BeginHorizontal();
  384. GUILayout.Space(20);
  385. GUILayout.Label(complexTypeResult);
  386. GUILayout.EndHorizontal();
  387. GUILayout.Space(10);
  388. GUILayout.Label("Complex Array");
  389. GUILayout.BeginHorizontal();
  390. GUILayout.Space(20);
  391. GUILayout.Label(complexArrayResult);
  392. GUILayout.EndHorizontal();
  393. GUILayout.Space(10);
  394. GUILayout.Label("Overloads");
  395. GUILayout.BeginHorizontal();
  396. GUILayout.Space(20);
  397. GUILayout.BeginVertical();
  398. GUILayout.Label(voidOverloadResult);
  399. GUILayout.Label(intOverloadResult);
  400. GUILayout.EndVertical();
  401. GUILayout.EndHorizontal();
  402. GUILayout.Space(10);
  403. GUILayout.Label("Read State Value");
  404. GUILayout.BeginHorizontal();
  405. GUILayout.Space(20);
  406. GUILayout.Label(readStateResult);
  407. GUILayout.EndHorizontal();
  408. GUILayout.Space(10);
  409. GUILayout.Label("Plain Task");
  410. GUILayout.BeginHorizontal();
  411. GUILayout.Space(20);
  412. GUILayout.Label(plainTaskResult);
  413. GUILayout.EndHorizontal();
  414. GUILayout.Space(10);
  415. GUILayout.Label("Generic Task With ContinueWith");
  416. GUILayout.BeginHorizontal();
  417. GUILayout.Space(20);
  418. GUILayout.Label(genericTaskWithContinueWithResult);
  419. GUILayout.EndHorizontal();
  420. GUILayout.Space(10);
  421. GUILayout.Label("Message Pump");
  422. GUILayout.BeginHorizontal();
  423. GUILayout.Space(20);
  424. invokeResults.Draw(Screen.width - 40, 270);
  425. GUILayout.EndHorizontal();
  426. GUILayout.Space(10);
  427. }
  428. #endregion
  429. }
  430. #endif