【问题标题】:SignalR hub proxy in Angular not workingAngular 中的 SignalR 集线器代理不起作用
【发布时间】:2016-04-23 18:03:59
【问题描述】:

我正在尝试将 SignalR 添加到我的 Angular MVC 应用程序中。我使用this 文章作为起点,它有一个集线器代理工厂,它用于......好吧......代理集线器调用。我已经完成了所有设置,但是我在服务器上的集线器无法与我的 Angular 代码进行通信。这是我的代码:

集线器代理工厂:

app.factory('hubProxy', ['$rootScope', 'signalRUrl', function ($rootScope, signalRUrl) {

    function hubFactory(hubName) {
        var connection = $.hubConnection(signalRUrl);
        var proxy = connection.createHubProxy(hubName);

        connection.start().done(function () { });

        return {
            on: function (eventName, callback) {
                proxy.on(eventName, function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            invoke: function (methodName, callback) {
                proxy.invoke(methodName)
                .done(function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            connection: connection
        };
    };

    return hubFactory;
}]);

角度控制器:

angular.module('testApp').controller('testController', ['$scope', 'hubProxy', function ($scope, hubProxy) {
    var pendingPaymentsHub = hubProxy('pendingPaymentsHub');

    pendingPaymentsHub.on('onUpdatePendingPayment', function (data) {
        console.log('hub callback!');
    });
}]);

枢纽:

[HubName("pendingPaymentsHub")]
public class PendingPaymentsHub : Hub
{
    private static IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<PendingPaymentsHub>();

    public static void UpdatePendingPayment(PendingPaymentViewModel pendingPayment)
    {
        hub.Clients.All.onUpdatePendingPayment(pendingPayment);
    }
}

我的集线器是从 API 控制器调用的,在这种情况下,是在更新完成之后。它是这样调用的:

PendingPaymentsHub.UpdatePendingPayment(pendingPayment);

当页面加载时,/signalr/negotiate/signalr/start 调用都成功运行(在浏览器开发工具中确认了 200 秒)。我还可以确认我的集线器中的UpdatePendingPayment 方法被调试命中。我只是在前端一无所获。为什么?

提前致谢。

更新: 需要明确的是,问题在于集线器代理工厂。当我在控制器中用以下内容替换工厂实现时,一切都按预期工作:

function initializeHub() {
    connection = $.hubConnection(signalRUrl);
    hub = connection.createHubProxy('pendingPaymentsHub');

    hub.on('onUpdatePendingPayment', function (data) {
        console.log('success');
    });

    connection.start();
};

【问题讨论】:

  • 我碰巧用过一次完全相同的代理工厂。我看不出有什么奇怪的。这可能只是控制器中的范围问题吗? var pendingPaymentsHubthis.pendingPaymentsHub
  • @rdoubleui 不幸的是,这不起作用。
  • 奇怪,希望其他人有一个想法。想知道原因!

标签: javascript angularjs signalr


【解决方案1】:

客户端的服务器端方法调用尝试大写,即使它在客户端以小写开头:

hub.Clients.All.OnUpdatePendingPayment(pendingPayment);

检查生成的代理看看做了什么方法映射,这是我发现大写问题的地方。

Misspelled method, incorrect method signature, or incorrect hub name 的点涵盖了这个,代理使用 camelCase:

[...] 此外,SignalR 使用驼峰式方法创建集线器代理,如 在 JavaScript 中是合适的,所以在 服务器将在客户端代理中称为 sendMessage。

【讨论】:

  • 根据使用的版本,这可能不再是问题了。
  • 感谢您的回复。它没有用。我正在使用 2.2.0。查看我的更新。
【解决方案2】:

我一直在使用完全相同的教程,我相信问题是您必须在为 hubProxy 对象定义 .on() 方法之后调用 connection.start()。不过,我不知道教程示例在这种情况下应该如何工作。

这是我的重做服务:

app.factory('hubProxy', ['$rootScope', 'serverUrl', function ($rootScope, serverUrl) {

    function backendFactory(hubName) {
        $.support.cors = true;
        var connection = $.hubConnection(serverUrl);
        var proxy = connection.createHubProxy(hubName);

        return {

            on: function (eventName, callback) {
                proxy.on(eventName, function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            invoke: function (methodName, callback) {
                proxy.invoke(methodName)
                .done(function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            start: function(){
                connection.start().done(function () { });
            }
        };
    };

    return backendFactory;
}]);

那么你只需要在调用 on() 方法后调用 start():

app.controller('hubDataController', ['$scope', 'hubProxy',
    function ($scope, hubProxy) {

    var proxy = hubProxy('remoteHub');        

    proxy.on('broadcast', function (data) {
        console.log(data);
    });
    proxy.start();
}

]);

【讨论】:

    最近更新 更多