SignalR 不在服务器上调用方法

SignalR not invoking method on server

我正在使用 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
        };

我的集线器连接完美,但是当我尝试调用我的调用时,没有任何反应。我在这里称呼它:

    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 }
        ]);
    });

因此,如果您查看从我的服务返回的 .ready() 函数,它使用承诺,当它被解析时将执行我传递给它的回调。这很好用(承诺 isLoaded 在我的 connection.start().done() 中解决,它在实例化时在我的服务内部调用,因此它只会在成功连接后执行回调)

它进入了我的 .invoke 方法(我已经用 console.log 确认了这一点),但从未调用集线器上的方法,如下所示:

public class ChatHub : Hub {
    public async void Connect(User user, Room room) {
        // ommitted
    }
}

我传递给它的对象有这样的结构:

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; }
}

所以我认为这不是我的论点的问题,因为它们不需要任何内容​​,所以它不会抱怨我只传递了一些论点(我唯一需要的论点)。

为了清楚起见,在我的 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)));
        }
    };

好吧,终于想通了。我遇到了两个不同的问题。

问题一:

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 }
    ]);
});

此代码将数据数组传递给 .invoke(),然后:

        return hub.invoke.apply(hub, $.merge([methodName], $.makeArray(args)))

正在制作那个数组的数组。所以只需将其更改为:

        return hub.invoke.apply(hub, $.merge([methodName], args))

并且已修复。

然后我想,我可能应该添加一些错误日志记录来查看它是否真的有错误,而我只是没有对它做任何事情(没有 .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);
            });

这给了我这个 惊人的 错误消息和 第二个问题 :

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.

这是有道理的,因为我在服务器上的方法是 async void,我将其切换为 async Task,瞧,它成功了。它现在成功地达到了我的断点。