我无法通过后面的代码向一个特定用户发送消息。 Clients.All
有效,Clients.AllExcept(userId)
有效,但不是Client.User(userId)
。
我的中心:
public class MessagingHub : Hub
{
public override Task OnConnected()
{
var signalRConnectionId = Context.ConnectionId;
// for testing purpose, I collect the userId from the VS Debug window
System.Diagnostics.Debug.WriteLine("OnConnected --> " + signalRConnectionId);
return base.OnConnected();
}
}
我的控制器从后面的代码发送消息:
public void PostMessageToUser(string ConnectionId)
{
var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>();
// doesn't works
mappingHub.Clients.User(ConnectionId).onMessageRecorded();
// doesn't works
mappingHub.Clients.Users(new List<string>() { ConnectionId }).onMessageRecorded();
// works
mappingHub.Clients.All.onMessageRecorded();
// works (?!)
mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded();
}
如何在JS上初始化我的集线器:
var con, hub;
function StartRealtimeMessaging()
{
con = $.hubConnection();
hub = con.createHubProxy('MessagingHub');
hub.on('onMessageRecorded', function () {
$(".MessageContainer").append("<div>I've received a message!!</div>");
});
con.start();
}
最后我如何向集线器发送(n空)消息:
function TestSendToUser(connectionId)
{
$.ajax({
url: '/Default/PostMessageToUser',
type: "POST",
data: { ConnectionId: connectionId},// contains the user I want to send the message to
});
}
因此,它与mappingHub.Clients.All.onMessageRecorded();
完美配合,但与mappingHub.Clients.User(ConnectionId).onMessageRecorded();
或mappingHub.Clients.Users(new List<string>() { ConnectionId}).onMessageRecorded();
配合使用。
但有趣的是,它适用于mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded();
:所有连接的用户都会收到除给定用户ID之外的消息,这意味着用户ID是好的,并且用户已被很好地识别。那么,为什么Clients.User(ConnectionId)
不起作用?
答案 0 :(得分:2)
我遇到了同样的问题。我无法使用.User(ConnectionId)工作。
我花了好几天时间试图让SignalR将长时间处理作业的进度仅报告给请求该作业的客户。也就是说,它不是大多数示例所描述的聊天应用程序。
我发现的任何“长处理进度报告”示例都只有集线器中的作业模拟。我有一个控制器做实际工作,需要从控制器发送消息,而不是集线器。
我使用了这个答案https://stackoverflow.com/a/21222303/3251300。作为您所述问题的解决方法,但已包含我用于长时间处理工作的所有代码片段,以防它们对偶然发现此答案的人有用。
该解决方法的优点在于它使用.Group()功能。通过将每个groupID设置为等于内部用户ID,可以使用.Group(userID)发送消息,而无需单独维护SignalR外部的userID / connectionID关系列表。
可能有一种方法可以在不使用.Group()功能的情况下维护SignalR中的关系,但我还没有找到它。
使用隐藏类型将userID传递给视图,然后将其提供给js。
<input type="hidden" value="@ViewBag.UserID" id="userID" />
然后在js hub脚本中使用以下命令在集线器连接启动时将userID发送到集线器。
$.connection.hub.start()
.done(function () {
var userID = document.getElementById('userID').value;
$.connection.myHub.server.announce(userID);
})
.fail(function () { alert("Hub failed to start.") });
然后,集线器有一条语句将userID和connectionID与groupID相关联,groupID与userID的字符串相同。
public class MyHub : Hub
{
public void Announce(string userID)
{
Groups.Add(Context.ConnectionId, userID);
}
}
要从控制器发送消息(在这种情况下,不是集线器,消息是在设置集线器上下文后,在控制器中运行的长处理请求上向客户端报告进度),请使用.Group()和内部用户ID。
var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
string fileMessage = "Some message";
hubContext.Clients.Group(userID).hubMessage(fileMessage);
然后使用js将其显示在视图中以将消息放入div
$.connection.myHub.client.hubMessage = function (message) {
$("#hubMessages").html(message);
}
'#hubMessages'在视图中引用此div。示例使用.append使得每次发送消息时div都会增长,.HTML将使用新消息替换div中的任何内容。
<div id="hubMessages"></div>
任何人都会回答这个问题,并试图继续使用MVC和SignalR,这是对Caleb的一次大喊,他为SignalR提供了很多一系列的介绍视频https://youtu.be/kr8uHeNjOKw任何找到这个答案的人都是新手SignalR我建议你花一个小时看这些。
答案 1 :(得分:2)
如果您要向某个特定的连接发送消息,并且想要使用 ConnectionId
,请确保使用 {{ 1}} ,而不是Clients.Client
像这样:
Clients.User
答案 2 :(得分:0)
我遇到同样的问题。
我从:
Clients.User(connectionId).SendAsync(CallbackDefinition.DirectMessage, directMessageResult);
收件人:
Clients.Client(connectionId).SendAsync(CallbackDefinition.DirectMessage, directMessageResult);
它有效:D
感谢:Matthieu Charbonnier