I've currently built a simple Signalr Hub which I'm pushing messages to from a Unity5 project. Given that SignalR2 client doesn't work with Unity5 I'm using websocketsharp in order to intercept the websocket frames. The messages are being pushed to the Hub successfully, but when I attempt to call a method on the client, I do not get the payload string, only the message identifier {"I": 0}
Looking through the SignalR documentation, it looks like this gets sent last, but I have no idea how I can get a hold it it. I'm sure its something simple, but for the life of me I can't figure it out.
UPDATE
Upon request, I've added the code for the project below...
SignalRClient.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Newtonsoft.Json;
using WebSocketSharp;
namespace Assets.Scripts
{
class SignalRClient
{
private WebSocket _ws;
private string _connectionToken;
private Dictionary<string, UnTypedActionContainer> _actionMap;
private readonly string _socketUrl = "http://localhost/";
private readonly string _socket = "ws://localhost/";
public SignalRClient()
{
_actionMap = new Dictionary<string, UnTypedActionContainer>();
var webRequest = (HttpWebRequest)WebRequest.Create(_socketUrl + "/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22myHub%22%7D%5D&clientProtocol=1.3");
var response = (HttpWebResponse)webRequest.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
var payload = sr.ReadToEnd();
UnityEngine.Debug.Log(payload);
_connectionToken = Uri.EscapeDataString(JsonConvert.DeserializeObject<NegotiateResponse>(payload).ConnectionToken);
//UnityEngine.Debug.Log(_connectionToken);
}
}
public void Open()
{
_ws = _ws == null
? new WebSocket(_socket + "signalr/connect?transport=webSockets&connectionToken=" + _connectionToken)
: new WebSocket(_socket + "signalr/reconnect?transport=webSockets&connectionToken=" + _connectionToken);
AttachAndConnect();
}
public void Close()
{
_ws.Close();
}
public void SendMessage(string name, string message)
{
//{"H":"chathub","M":"Send","A":["tester","hello"],"I":0}
var payload = new RollerBallWrapper()
{
H = "myhub",
M = "Send",
A = new[] { name, message },
I = 12
};
var wsPacket = JsonConvert.SerializeObject(payload);
_ws.Send(wsPacket);
}
private void AttachAndConnect()
{
_ws.OnClose += _ws_OnClose;
_ws.OnError += _ws_OnError;
_ws.OnMessage += _ws_OnMessage;
_ws.OnOpen += _ws_OnOpen;
_ws.Connect();
}
void _ws_OnOpen(object sender, EventArgs e)
{
UnityEngine.Debug.Log("Opened Connection");
}
//
// This seems to be retriving the last frame containing the Identifier
void _ws_OnMessage(object sender, MessageEventArgs e)
{
//UnityEngine.Debug.Log(e.Data); // Returns {"I":"0"} ????
}
void _ws_OnError(object sender, WebSocketSharp.ErrorEventArgs e)
{
UnityEngine.Debug.Log(e.Message);
}
void _ws_OnClose(object sender, CloseEventArgs e)
{
UnityEngine.Debug.Log(e.Reason + " Code: " + e.Code + " WasClean: " + e.WasClean);
}
public void On<T>(string method, Action<T> callback) where T : class
{
_actionMap.Add(method, new UnTypedActionContainer
{
Action = new Action<object>(x =>
{
callback(x as T);
}),
ActionType = typeof(T)
});
}
}
internal class UnTypedActionContainer
{
public Action<object> Action { get; set; }
public Type ActionType { get; set; }
}
class MessageWrapper
{
public string C { get; set; }
public RollerBallWrapper[] M { get; set; }
}
class RollerBallWrapper
{
public string H { get; set; }
public string M { get; set; }
public string[] A { get; set; }
public int I { get; set; }
}
}
MyHub.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
public class MyHub : Hub
{
public void Send(string name, string message)
{
var myConn = Context.ConnectionId;
Clients.All.broadcastMessage("John", "Hello");
}
}
The problem is the websocket connection. I had the following:
Which was missing 2 critical querystring parameters:
connectionData
andtid
in addition to theconnectionToken
andtransport
. I wrongly assumed that these weren't needed.I hope this helps anyone who didn't read the documentation like me :)