2015-05-20 20 views
8

Ich habe heute mit SignalR experimentiert und es ist wirklich nett. Grundsätzlich wollte ich Folgendes erreichen:SignalR - Nachricht senden OnConnected

Sobald ein Gerät verbindet, sollte es eine Nachricht an die erste senden. Wenn mehr Geräte als 1 verbunden sind, möchte ich zwei Nachrichten senden. Einer für alle außer der letzte verbundene Client. Und eine Nachricht an nur der letzte verbundene Client.

Der Code, den ich verwendet habe funktioniert perfekt, wenn ich es in einem benutzerdefinierten API-Controller und im Grunde die Aktion aufrufen, aber das ist nicht was ich will.

Ich möchte die Nachrichten senden, sobald ein Gerät innerhalb von OnConnected ohne Benutzerinteraktion verbindet, aber wenn ich meinen Code innerhalb der OnConnected überschreiben, funktioniert es nicht mehr. Es wird nicht mehr an die spezifischen Clients gesendet (zuerst verbunden und zuletzt verbunden).

Ich hoffe, dass mir jemand dabei helfen kann, weil ich mir seit ein paar Stunden den Kopf schlage.

public override System.Threading.Tasks.Task OnConnected() 
    { 
     UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1); 

     int amountOfConnections = UserHandler.ConnectedIds.Count; 
     var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault(); 
     var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList(); 

     if (amountOfConnections == 1) 
     { 
      Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one"); 
     } 
     else 
     { 
      Clients.Clients(allExceptLast).hello("Send to everyone except last"); 
      Clients.Client(lastConnection.Key).hello("Send to only the last one"); 
     } 

     return base.OnConnected(); 
    } 

Antwort

4

Danke für die Hilfe (upvoted euch). Tatsächlich fand das Problem .. es war in meinem Client. Ich habe zuerst die Hallo-Funktion abonniert und danach die HubConnection gestartet. Sobald ich diese Bestellung geändert habe, hat alles gut funktioniert.

Es arbeitete mit dem folgenden Client-Code:

private async Task ConnectToSignalR() 
    { 
     var hubConnection = new HubConnection("url"); 
     hubConnection.Headers["x-zumo-application"] = "clientapikey"; 

     IHubProxy proxy = hubConnection.CreateHubProxy("ChatHub"); 

     proxy.On<string>("hello", async (msg) => 
     { 
      Console.WriteLine(msg); 
     }); 

     await hubConnection.Start(); 
    } 
1

gut ... Sie sind wieder eine neue Aufgabe ..., so denke ich, dass das Problem sein kann ... Sie zuerst Ihren Code ausführen sollen und dann die Aufgabe zurückkehren ... oder eine ContinueWith setzen. .. wie ...

public override Task OnConnected() 
    { 
     Task task = new Task(() => 
      { 
       UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1); 

       int amountOfConnections = UserHandler.ConnectedIds.Count; 
       var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault(); 
       var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList(); 

       if (amountOfConnections == 1) 
       { 
        Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one"); 
       } 
       else 
       { 
        Clients.Clients(allExceptLast).hello("Send to everyone except last"); 
        Clients.Client(lastConnection.Key).hello("Send to only the last one"); 
       } 
      }); 

     task.ContinueWith(base.OnConnected()); 

     return task; 
    } 

ich habe, dass ... es ist nur eine Vermutung ..

3

Da Sie noch eine Verbindung aufgebaut haben nicht nicht getestet, innerhalb versuchen, Ihre Client .hello() Funktion aufzurufen OnConnected ist zu diesem Zeitpunkt nicht möglich. Wir können jedoch eine Server-Hub-Methode definieren und diese sofort über unsere Verbindung .done Callback aufrufen. Dann können wir in unserer neuen Servermethode die Logik neu zuweisen, die Sie derzeit in OnConnected haben.

Dies wird unser Setup einiges ändern und einige zusätzliche Schritte einführen, aber beachten Sie das folgende Beispiel ...

// WhateverHub 
public override Task OnConnected() 
{ 
    return base.OnConnected() 
} 

public void AfterConnected() 
{ 
    // if(stuff) -- whatever if/else first user/last user logic 
    // { 
     Clients.Caller.hello("message") 
    // } 
} 

var proxy= $.connection.whateverHub; 

proxy.client.hello = function(message) { 
    // last step in event chain 
} 

$.connection.hub.start().done(function() { 
    proxy.server.afterConnected() // call AfterConnected() on hub 
}); 

So ist die Grundidee ist es, zuerst

  1. Verbinden =>.done(function() { ... });
  2. Anruf server.afterConnected()
  3. Execute Logik innerhalb dieser Methode
  4. Wenn wir zufrieden sind mit den Bedingungen unserer .hello()-Client-Funktion

Hinweis nennen - diese Implementierung ist für einen Kunden JavaScript - aber die gleiche Idee kann in einen .net-Client übersetzt werden. Dies ist meist ein architektonisches Problem.

10

Wenn ich etwas aus Ihrer Frage vermissen, sieht die Lösung für mich ziemlich einfach, Sie brauchen nur zu wechseln, um mit

Clients.Caller.hello("Send to only the last one"); 

anstatt zu versuchen, sich selbst zu verstehen, wer die letzte verbundene ID ist. Das Gleiche gilt für die anderen, können Sie verwenden:

Clients.Others.hello("Send to everyone except last"); 

Sie nicht die gesamte Logik Sie Setup benötigen, tun diese zwei Linien, was Sie brauchen, und sie arbeiten innerhalb OnConnected.

+0

vielen Dank für diesen Code. Es macht meinen Code viel einfacher! – Mittchel

Verwandte Themen