无法使用SignalR

时间:2017-07-21 21:20:12

标签: c# asp.net-mvc signalr

我无法通过后面的代码向一个特定用户发送消息。 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)不起作用?

3 个答案:

答案 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