2017-07-21 6 views
2

Ich kann nicht funktioniert die Nachricht an einen bestimmten Benutzer aus dem Code hinter zu senden. Clients.All funktioniert, Clients.AllExcept(userId) funktioniert, aber nicht Client.User(userId).Kann nicht senden Nachricht an bestimmte Benutzer mit SignalR

Meine Nabe:

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

Meine Controller hinter Nachricht von Code zu senden:

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(); 

} 

Wie meine Nabe auf der JS initialisiert wird:

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

Und schließlich, wie ich eine (n leer) Nachricht an den Hub senden:

function TestSendToUser(connectionId) 
{ 
    $.ajax({ 
     url: '/Default/PostMessageToUser', 
     type: "POST", 
     data: { ConnectionId: connectionId},// contains the user I want to send the message to 
    }); 
} 

So funktioniert es perfekt mit mappingHub.Clients.All.onMessageRecorded(); aber nicht mit mappingHub.Clients.User(ConnectionId).onMessageRecorded(); oder mappingHub.Clients.Users(new List<string>() { ConnectionId}).onMessageRecorded();.

Aber interessanter, es funktioniert mit mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded();: Alle Benutzer verbunden, um die Nachricht mit Ausnahme der angegebenen Benutzer-ID erhalten, was bedeutet, dass die Benutzer-ID ist gut, und der Benutzer ist gut identifiziert. Warum funktioniert Clients.User(ConnectionId) nicht?

Antwort

1

Wenn Sie eine Nachricht an eine bestimmte Verbindung senden und wenn Sie die ConnectionId verwenden möchten, stellen Sie sicher, dass Sie verwenden Clients.Client und nicht Clients.User

So:

public void PostMessageToUser(string connectionId) 
{ 
    var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>(); 

    // Like this 
    mappingHub.Clients.Client(connectionId).onMessageRecorded(); 

    // or this 
    mappingHub.Clients.Clients(new List<string>() { connectionId }).onMessageRecorded(); 
} 
2

Ich hatte das gleiche Problem. Ich konnte nicht. Benutzer (ConnectionId) zu arbeiten.

Ich habe gerade Tage damit verbracht, SignalR dazu zu bringen, den Fortschritt eines langen Verarbeitungsjobs an den Client zu melden, der den Job angefordert hat. Das heißt, es ist keine Chat-App, die die meisten Beispiele beschreiben.

Alle 'langen Verarbeitungsfortschrittsberichte', die ich gefunden habe, haben nur eine Sim der Aufgabe im Hub. Ich habe einen Controller, der echte Arbeit leistet und Nachrichten vom Controller senden muss, nicht vom Hub.

Ich habe diese Antwort verwendet https://stackoverflow.com/a/21222303/3251300. als Workaround für Ihr angegebenes Problem, aber haben alle Code-Schnipsel, die ich für den langen Verarbeitungsauftrag verwende, falls sie für jeden nützlich sind, der auf diese Antwort stolpert.

Die Problemumgehung weist eine Eleganz auf, da sie die Funktion .Group() verwendet. Indem Sie jede Gruppen-ID gleich der internen Benutzer-ID setzen, können Nachrichten mit .Group (Benutzer-ID) gesendet werden, ohne dass eine Liste der userID/connectionID-Beziehungen außerhalb von SignalR separat gepflegt werden muss.

Es kann einen Weg geben, die Beziehungen in SignalR ohne die .Group() Funktion zu pflegen, aber ich habe es noch nicht gefunden.

Übergeben Sie die Benutzer-ID an die Ansicht mit einem versteckten Typ, der es dann für die js zur Verfügung stellt.

<input type="hidden" value="@ViewBag.UserID" id="userID" /> 

Dann in dem js-Hub-Skript den folgenden, um den Benutzer-ID an den Hub zu senden verwenden, wenn die Nabe-Verbindung startet.

$.connection.hub.start() 
    .done(function() { 
    var userID = document.getElementById('userID').value; 
    $.connection.myHub.server.announce(userID); 
    }) 
    .fail(function() { alert("Hub failed to start.") }); 

Die Nabe hat dann eine Anweisung, die die Benutzer-ID und connectionId zum groupID zuordnet, die dann die gleiche Zeichenfolge als userID ist.

public class MyHub : Hub 
    { 
     public void Announce(string userID) 
     { 
      Groups.Add(Context.ConnectionId, userID); 
     } 
    } 

auf Nachrichten von dem Controller senden (auch hier nicht die Nabe in diesem Fall, wird die Nachricht auf einer langen Verarbeitungsanforderung an den Client Fortschritte berichtet in dem Controller ausgeführt wird), nachdem die Nabenkontexteinstellung verwenden .Group() und die interne Benutzer-ID. die Nachricht platzieren in einem div

$.connection.myHub.client.hubMessage = function (message) { 
    $("#hubMessages").html(message); 
} 

'#hubMessages' bezieht sich auf diese div in der Ansicht

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); 
string fileMessage = "Some message"; 
hubContext.Clients.Group(userID).hubMessage(fileMessage); 

Dies wird dann in der Ansicht mit dem js angezeigt. Beispiele verwenden .append, wodurch das div bei jedem Senden einer Nachricht wächst, .HTML ersetzt alles, was im div ist, durch die neue Nachricht.

<div id="hubMessages"></div> 

Wer auf diese Antwort kommt und versucht, auf MVC und SignalR, einem großen shout out zu Caleb gehend zu erhalten, die für SignalR https://youtu.be/kr8uHeNjOKw Wer eine große Reihe von Intro vids hat, die diese Antwort findet, ist neu SignalR Ich empfehle Ihnen, eine Stunde damit zu verbringen, diese anzusehen.

+0

+1 für die Antwort, aber, .. .. Erstellen von Gruppen von nur einem Benutzer ist ein Workaround, und keine echte Lösung. Ich kann nicht glauben, dass der 'Clients.User (srUserId)' nicht funktioniert ... –

+0

Nun, endlich habe ich die Antwort gefunden. Siehe meine Antwort. (hoffe es hilft dir auch;)) –

+0

Du hast recht, ich hätte 'Workaround' verwenden sollen - ich habe geantwortet. Und brillante Arbeit, um die richtige Antwort zu finden. Die Problemumgehung .Group() hat eine elegante Eigenschaft, da SignalR die internen Beziehungen userID/ConnectionID verwaltet, was bedeutet, dass BenutzerID direkt in den Nachrichtenanforderungen verwendet werden kann, ohne dass die Beziehungen separat gepflegt werden müssen. Als Testumgehung dafür hatte ich ConnectionID der Benutzerdb-Tabelle hinzugefügt. Das wollte ich im Live-db nicht machen. –

Verwandte Themen