Ben*_*ack 4 c# signalr angularjs
我正在使用AngularJS创建一个SignalR服务,该服务连接到我指定的集线器并公开.on和.invoke方法,以便我的控制器可以监听来自服务器的事件并调用服务器上的方法.
这是我服务的相关部分:
return {
on: function (eventName, callback) {
hub.on(eventName, function (result) {
$root.$apply(function () {
if (callback) {
callback(result);
}
});
});
},
ready: function (callback) {
return isLoaded.then(function () {
callback();
});
},
invoke: function (methodName, args, callback) {
return hub.invoke.apply(hub, $.merge([methodName], $.makeArray(args))).done(function (result) {
$root.$apply(function () {
if (callback) {
callback(result);
}
});
});
},
connection: connection
};
Run Code Online (Sandbox Code Playgroud)
我的集线器连接完美,但是当我尝试调用我的调用时,没有任何反应.这就是我所说的:
var chatHub = hub('chatHub');
chatHub.on('userConnected', function (user) {
console.log(user);
});
chatHub.ready(function () {
chatHub.invoke('Connect', [ // also tried 'connect' here
{ Name: $root.auth.profile.name, Picture: $root.auth.profile.picture },
{ RoomKey: $routeParams.roomKey, RoomID: $routeParams.roomId }
]);
});
Run Code Online (Sandbox Code Playgroud)
因此,如果您查看.ready()从我的服务返回的函数,它会使用一个承诺,当它被解析时将执行传递给它的回调.这很好用(承诺isLoaded在我的connection.start().done()中得到解决,当它被实例化时在我的服务中被调用,因此它只会在成功连接后执行回调)
它得到我的.invoke方法(我已经用console.log确认了这一点),但从不调用集线器上的方法,如下所示:
public class ChatHub : Hub {
public async void Connect(User user, Room room) {
// ommitted
}
}
Run Code Online (Sandbox Code Playgroud)
我传递给它的对象具有以下结构:
public class Room {
public int RoomKey { get; set; }
public string RoomID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<User> Users { get; set; }
public List<Message> Messages { get; set; }
}
public class User {
public string Name { get; set; }
public string Picture { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
所以我不认为这是我的论点的问题,因为他们不需要任何东西,因此它不会抱怨我只传递了一些参数(我唯一需要的参数).
为了清楚起见,在我chatHub.invoke('Connect', ...)使用的情况下,它是基于我在我的~/signalr/hubs文件中找到的代码在服务器上(我不需要这个,因为我不使用生成的代理,我只是包括它同时所以我可以检查他们的底层代码)
proxies['chatHub'] = this.createHubProxy('chatHub');
proxies['chatHub'].client = { };
proxies['chatHub'].server = {
connect: function (user, room) {
return proxies['chatHub'].invoke.apply(proxies['chatHub'], $.merge(["Connect"], $.makeArray(arguments)));
}
};
Run Code Online (Sandbox Code Playgroud)
好吧,终于明白了.我遇到了两个不同的问题.
问题一:
chatHub.ready(function () {
chatHub.invoke('Connect', [ // also tried 'connect' here
{ Name: $root.auth.profile.name, Picture: $root.auth.profile.picture },
{ RoomKey: $routeParams.roomKey, RoomID: $routeParams.roomId }
]);
});
Run Code Online (Sandbox Code Playgroud)
这段代码传递了一个数据数组.invoke(),然后:
return hub.invoke.apply(hub, $.merge([methodName], $.makeArray(args)))
Run Code Online (Sandbox Code Playgroud)
正在制作该阵列的数组.所以只需将其更改为:
return hub.invoke.apply(hub, $.merge([methodName], args))
Run Code Online (Sandbox Code Playgroud)
它是固定的.
然后我想,我应该添加一些错误记录到这,看看它是否实际上是错误的,我只是没有做任何事情(没有.fail(),因此从来没有看到它)所以我把它改为:
return hub.invoke.apply(hub, $.merge([methodName], args))
.done(function (result) {
$root.$apply(function () {
if (callback) {
callback(result);
}
});
})
.fail(function (error) {
$log.error('Error invoking ' + methodName + ' on server: ' + error);
});
Run Code Online (Sandbox Code Playgroud)
这给了我这个惊人的错误信息和问题二:
Error invoking connect on server: Error: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我在服务器上的方法是一个async void,我切换它async Task,瞧,它工作.它现在成功地击中了我的断点.