我对 SignalR 也相当陌生(也是 Angular 的第一次用户),因此我在 ASP.NET MVC 4 (SignalR 2.2) 中重新创建(并简化)了该项目来解决问题。而且我认为还有不止一个......
1) SignalR 使用 JQuery。在 jQuery(以及几乎所有其他 JS 框架)中,最好在“文档就绪”事件之后执行代码。因此,我将 SignalR 设置包装在 jQuery 文档就绪处理程序中(请参阅下面的代码)。
另外我删除了hubConnetion
全局变量,因为全局变量是坏的+在包装在 jQuery 文档就绪处理程序之后,变量是该处理程序的本地变量,并且无论如何都无法在控制器代码中访问...
2) 恕我直言,主要问题是这个(部分SignalR 客户端 API http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#establishconnection):
通常,您在调用 start 方法之前注册事件处理程序
建立连接。如果您想注册一些活动
建立连接后的处理程序,您可以这样做,但是您
在调用之前必须注册至少一个事件处理程序
启动方法。原因之一是一个网络中可以有许多集线器
应用程序,但您不想触发 OnConnected 事件
如果您只打算使用其中一个集线器,则可以使用每个集线器。当。。。的时候
连接建立后,集线器上是否存在客户端方法
proxy 告诉 SignalR 触发 OnConnected 事件。如果你
在调用 start 方法之前不要注册任何事件处理程序,您
将能够调用 Hub 上的方法,但 Hub 的 OnConnected
方法不会被调用,也不会调用任何客户端方法
服务器.
您的事件处理程序是在控制器工厂方法中设置的,该方法在连接之后调用start()
方法。
尝试添加暂时的调用之前的处理程序start()
像这样:
$.connection.tasklistHub.client.getTask = function () { };
3)为了确保问题出在 SignalR 而不是 Angular,我打开了服务器端和客户端tracing http://www.asp.net/signalr/overview/testing-and-debugging/enabling-signalr-tracing。完成上述所有更改后,客户端已成功接收来自服务器的事件:
SignalR: Triggering client hub event 'getTask' on hub 'TasklistHub'
但 Angular 无法使用收到的数据更新 div。解决方案是使用$rootScope.$apply
中提到的函数这篇关于 SignalR 和 Angular 一起使用的文章 http://sravi-kiran.blogspot.cz/2013/05/HookingUpAspNetSignalRWithAngularJS.html。现在一切都按预期进行。请参阅下面的完整代码。
旁注:我知道这只是示例代码。在任何现实世界的项目中,我都会考虑将 SignalR 集线器包装在客户端上的某种服务中,例如上面提到的文章或使用这个图书馆 https://github.com/JustMaier/angular-signalr-hub(看起来非常优雅)
我还收回我之前关于客户端处理程序名称的答案,因为根据同一文档,客户端方法名称匹配不区分大小写......
索引.cshtml
<html lang="en" ng-app="SignalR">
<head>
<meta charset="utf-8" />
<title>SignalR & AngularJS</title>
<script src="~/Scripts/jquery-1.6.4.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<script src="~/Scripts/angular.js"></script>
<script type="text/javascript">
$(function() {
$.connection.hub.logging = true;
// temporary handler to force SignalR to subscribe to server events
$.connection.tasklistHub.client.getTask = function () { };
$.connection.hub.start().done(function () {
$('#connectionStatus').text('Connected');
console.log('Now connected, connection ID =' + $.connection.hub.id);
});
});
var SignalRControllers = angular.module('SignalRControllers', []);
var SignalRApp = angular.module('SignalR', ['SignalRControllers']);
</script>
<script src="~/Scripts/app/TodayController.js"></script>
</head>
<body>
<div id="body">
<div ng-view>
<div ng-controller="TodayController">
<div id="connectionStatus"></div>
<div>{{Task}}</div>
<input id="taskName" type="text"/>
<input type="button" name="Send Task" value="Send Task" data-ng-click="sendTask()" />
</div>
</div>
</div>
</body>
</html>
TodayController.js
SignalRControllers.controller('TodayController', [
'$scope', '$http', '$rootScope',
function ($scope, $http, $rootScope) {
$scope.sendTask = function() {
$.connection.tasklistHub.server.sendTask($("#taskName").val());
};
$scope.Task = "Empty";
$.connection.tasklistHub.client.getTask = function (task) {
console.log(task);
$rootScope.$apply(function () {
$scope.Task = task;
});
};
}
]
);