I am trying to create a JQuery UI widget that receives realtime updates from a server using SignalR (2.2.0). Invoking a method on the server works just fine, however invoking a client callback from the server does not trigger on the client.
I have enabled logging on the client as is suggested here: SignalR Troubleshooting and I can see in the console that the connection is setup just fine but the client method is never invoked. There is no error message of any kind. I have also defined the client method on the hub proxy before starting the connection like so:
_bindClientCallbacks: function () {
theHub.client.broadCastToClient = function (message) {
twr.log(message);
};
}
and afterwards I start the hub connection like so:
_startSignalRClient: function () {
$.connection.hub.logging = true;
$.connection.hub.start()
.done(function () {
twr.log("Connected to SignalR hub, id=" + $.connection.hub.id);
})
.fail(function () {
});
}
These methods are called in the '_create()' function in the JQuery widget like so:
_create: function () {
theHub = $.connection.DataImportHub;
this._bindClientCallbacks();
this._startSignalRClient();
}
This works fine and I can get a valid connection with an id. I can also call a server method from the client. But when I try to invoke the broadCastToClient method on the client from the server like so:
public void BroadCastToClient(string userId, string message)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<DataImportHub>();
foreach (var connectionId in _connections.GetConnections(userId))
{
hubContext.Clients.Client(connectionId).broadCastToClient(message);
}
}
Nothing happens on the client.. even though the server does find a valid connection that corresponds to the connection id I got on the client.
What am I missing here?
Just found out the solution by reading this post. Apparently having a custom SignalR dependency resolver setup in the Owin startup class breaks javascript callbacks. Moving the dependency resolver setup code to Application_Start in Global.asax does the trick. Why this happens really is beyond me...
Bad DI setup in Startup.cs
app.Map("/signalr", map =>
{
var hubConfiguration = new HubConfiguration
{
Resolver = new NinjectSignalRDependencyResolver(new StandardKernel())
};
map.RunSignalR(hubConfiguration);
});
Good DI setup in Global.asax
protected void Application_Start()
{
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(new StandardKernel());
}
Related
I have a C# server running my hub class, which contains only 1 method in there, which is as follows,
public class HothHub : Hub
{
public async Task AddSingleUserGroup(string name)
{
await Groups.AddToGroupAsync(Context.ConnectionId, name);
}
}
I also have a JavaScript client, which connects to the hub via the following code,
var connection;
async function signalRStart() {
connection = new signalR.HubConnectionBuilder()
.withUrl("https://somesignalrurl.com/hothhub", { withCredentials: false })
.withAutomaticReconnect()
.configureLogging(signalR.LogLevel.Information)
.build();
connection.on("hothHubToHothUpdate", () => {
console.log("Called by the server!");
});
connection.onreconnecting(error => {
console.log("Connection lost due to error " + error + ". Reconnecting.");
});
// Start the connection.
await start();
}
async function start() {
try {
await connection.start();
connection.invoke("addSingleUserGroup", "someUniqueUserName");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
Now when the client initiates the connections and run start() on itself, this part seems to run fine. A connection to the signalR hub is made successfully. The problem I'm having is when connection.invoke("addSingleUserGroup", "someUniqueUserName"); is run although the error does not happen all the time. On first run, the method at the server end is hit successfully however, it looks like subsequent calls to it fail and this is the error returned in the client,
Uncaught (in promise) Error: Failed to invoke 'addSingleUserGroup' due to an error on the server. HubException: Method does not exist.
at _callbacks.<computed> (signalr.js:1252:36)
at HubConnection._processIncomingData (signalr.js:1364:33)
at HubConnection.connection.onreceive (signalr.js:985:52)
at webSocket.onmessage (signalr.js:2236:30)
I've read a few articles on here but most seemed to be related to the client calling the wrong method name having used a capital letter at the start of the method name when invoking it and some having mentioned issues with the method expecting 1 type parameter and receiving another type although in my instance here its hard to think how the server would not treat the incoming parameter as a string, which is what is being passed in. Has anyone got any ideas on what could be wrong here or what I could try?
Thanks!
Unfortunately I dont have an actual answer for this but after deploying the solution to my Azure App Service, the release version does not produce the error. It seems the error only persisted when in debug mode but like I said I'am not sure why.
I am already googled about this but not found any solution.
My hub's methods are like this
public string Test(string hello)
{
return hello;
}
public override System.Threading.Tasks.Task OnConnected()
{
return base.OnConnected();
}
and my client side is
var objHub = $.connection.myHub;
$.connection.hub.start().done(function () {
objHub.server.test('test');
}).fail(function () {
/.....
})
OnConnected is calling perfectly but objHub.server.test is not calling.
Even I have checked in console for server side methods mapping to hub object and here is all server methods are registered with hub object
Why my server side methods are not calling?
Update
Now what I am seeing
Server is requesting to
http://localhost:83/signalr/connect?transport=longPolling&clientProtocol=1.5&connectionToken=MUM0NzA5MDI3QTEyRjM5RDM4QjEzNDhGRTFEMjJGNzI3QTcyQTRDM0ZDOTE3MTRCRUYwQkVCOUI3OEQ3Q0MxREY1NzNEQkUzQjAxM0QzMzlCRDIzQUY0OUJDNThENDVCMDUzQ0RENEMwQTUzNkNFMzEyNDY2QTkyMjExRkE4REVDMUZGRUE2RTdFNTNDRkM2NDg5NjEzMUIyMzQzNDI4Njk3RjRBNTdEMDlEQ0U1MUJGQ0I4RjE4Njg3NjU5NTBFRURGQTZCNzBGMzUwRjA0MzdFOERENkQ1NTFEQ0JCNEJDN0U3NDUyNA%3D%3D&connectionData=%5B%5D
And getting this error
Method not found: System.Threading.Tasks.Task 1<Microsoft.Owin.IFormCollection> Microsoft.Owin.OwinRequest.ReadFormAsync()
Thanks
Yes I updated my Microsoft.AspNet.SignalR2.2.2 when I revert to Microsoft.AspNet.SignalR2.2.0 then it working........
I'm using MVC 4. I have a js code that needs to communicate with the server with the help of Websockets. I'm using Fleck at the server. I'm creating the socket server in Application_Start event. But when I try the connection from browser console, I get errors like Connection refused.
Here is my global.asax code.
protected void Application_Start()
{
IPAddress ip = null;
if (GetResolvedConnecionIPAddress(out ip)) // Get host ip
{
string Domain = "wss" + System.Uri.SchemeDelimiter + ip + ":" + "8092";
FleckLog.Level = Fleck.LogLevel.Debug;
try
{
if (GetResolvedConnecionIPAddress(out ip))
{
var server = new WebSocketServer(Domain);
server.Start(socket =>
{
LogWriter.Logger.Info("WS: Inside socket server");
socket.OnOpen = () =>
{
LogWriter.Logger.Info("WS: OnOpen socket");
};
socket.OnClose = () =>
{
LogWriter.Logger.Info("WS: OnClose socket");
};
socket.OnMessage = message =>
{
LogWriter.Logger.Info("WS: OnMsg socket");
};
});
}
}
catch (Exception e)
{
throw;
}
}
}
It looks like as soon as the Application_Start method ends, that WebSocketServer is going to get out of scope and eventually garbage collected.
You could, set that object as member in the Global class, and dispose it on the Application_End event for example.
UPDATE:
You are also using the wss schema but not providing any certificate configuration. Please note that IIS and Fleck are two different things, that runs in different ports, and not because you create Fleck into the ASP.NET app means that Fleck is going to infer the SSL/TLS configuration or any configuration at all. Try to set the schema to ws instead and open the page without HTTPS and see if it works.
I have already integrated pusher using Ratchet. Broadcasting to all users works fine.
Now I'm trying to find a way how to send a message to specific user when I got it's connection.
method which is executed on subscribe :
public function onSubscribe(ConnectionInterface $conn, $topic) {
$conn->send(json_encode("Hello"));
}
JS on client side:
var conn = new ab.Session('ws://127.0.0.1:8080',
function() {
conn.subscribe('chat', function(topic, data) {
console.log(data); // here I'd like to get that "Hello" message
});
},
function() {
console.warn('WebSocket connection closed');
},
{'skipSubprotocolCheck': true}
);
I'm not getting any message, I guess I haven't formatted it properly (json_encode("Hello")). Any help ?
You need to store the connections somehow and then call them directly.
For instance:
$conns[$conn->resourceId] = $conn;
And then later:
$conns[$resourceId]->write("new data");
As for why you're not receiving the message on subscribe, try the write() method instead of the send() method.
Also, check the console to see if you're receiving the data but not unpacking it properly.
this project work right on SignalR v1.1.4, client is phantomjs with cors:
webpage = require "webpage"
websocket = webpage.create()
serverUrl = "http://www.domain.com"
websocket.injectJs './jquery-2.1.0.min.js'
websocket.injectJs './jquery.signalR-1.1.4.min.js'
websocket.includeJs serverUrl + '/signalr/hubs', ->
websocket.evaluate (serverUrl)->
$.support.cors = false
$.connection.hub.url = serverUrl + '/signalr'
taskHub = $.connection.taskHub
$.connection.hub.start().done ->
taskHub.server.registerAgent "xxx"
#……
taskHub.client.castTesk = (task) ->
#……
, serverUrl
until upgrade SignalR to v2.0.2.
i remove RouteTable.Routes.MapHubs(new HubConfiguration() { EnableCrossDomain = true }) on Application_Start() and add Startup.cs:
[assembly: OwinStartup(typeof(SpiderMan.Startup))]
namespace ProjectNamespace {
public partial class Startup {
public void Configuration(IAppBuilder app) {
app.Map("/signalr", map => {
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration {
EnableJSONP = true
};
map.RunSignalR(hubConfiguration);
});
}
}
}
then $.connection.hub.start() work right always, but taskHub.client.castTesk() could not be triggered, without any error message.
update:
v1.2.1 is work fail also like v2.0.2.
And, Microsoft.AspNet.SignalR Package with any version on server could not affect this issus. client work right with jquery.signalR-1.1.4.min.js, fail with jquery.signalR-1.2.1.min.js always, for any server signalR version.
You should define your castTesk method before you start your connection. This issue is discussed in the "Connection started before subscriptions are added" section of the SignalR Troubleshooting Guide.
#……
taskHub.client.castTesk = (task) ->
#……
$.connection.hub.start().done ->
taskHub.server.registerAgent "xxx"
#……
The problem is that if you call $.connection.hub.start() before you define taskHub.client.castTesk, SignalR will not subscribe the client to the TaskHub.
You will still be able to invoke server-side methods belonging to the TaskHub such as RegisterAgent, but the server will be unable to invoke client methods such as castTesk.
I would also suggest removing the $.support.cors = false line. This will cause SignalR to always use JSONP instead of CORS even if the browser supports CORS.