2016-04-30 6 views
12

Ich habe eine selbst gehostete SignalR-Anwendung, die im Kontext einer Konsolen-App läuft. Ich verbinde mich über eine Wrapper-Klasse mit den Hubs, um zu verhindern, dass ich die SignalR.Core-Assemblies aus meinem ASP.NET-Projekt referenzieren muss. Es ist also eine andere C# -Klasse innerhalb meiner Anwendung, die für das Senden von Nachrichten an verbundene Clients zuständig ist.SignalR 2.2 Clients, die keine Nachrichten empfangen

Ich bin in der Lage, die PlanHub Methoden (Register und Unregister) direkt von Javascript, diese Breakpoints getroffen werden. Wenn ich jedoch Client-Methoden von einer Klasse außerhalb des Hubs aufrufe (selbst wenn ich Clients.All verwende, um Probleme mit der Gruppenregistrierung zu beseitigen), erhalten die Clients die Nachricht nie. Was mache ich falsch?

Wenn ich diesen Code ausführe, kann ich überprüfen, ob der Code Clients.All.updateStatus(planId, message); erfolgreich ist, aber nichts wird in der Konsole auf dem Client protokolliert.

Hier ist der relevante Code:

PlanHub.cs

public class PlanHub : Hub 
{ 
    private const string GroupPrefix = "PlanGroup_"; 

    public void Register(int companyId) 
    { 
     Groups.Add(Context.ConnectionId, $"{GroupPrefix}{companyId}"); 
    } 

    public void Unregister(int companyId) 
    { 
     Groups.Remove(Context.ConnectionId, $"{GroupPrefix}{companyId}"); 
    } 
} 

PlanPublisher.cs

public class PlanPublisher 
{ 
    private readonly static Lazy<PlanPublisher> _instance = new Lazy<PlanPublisher>(() => 
     new PlanPublisher(GlobalHost.ConnectionManager.GetHubContext<PlanHub>().Clients)); 
    private IHubConnectionContext<dynamic> Clients { get; set; } 

    private PlanPublisher(IHubConnectionContext<dynamic> clients) 
    { 
     Clients = clients; 
    } 

    public static PlanPublisher Instance => _instance.Value; 

    public void UpdateStatus(int planId, string message) 
    { 
     //This code gets hit and no exceptions are thrown, but the clients 
     //never receive the message. Using Clients.All instead of my 
     //Groups for testing -- still doesn't work 
     Clients.All.updateStatus(planId, message); 
    } 
} 

Code aufrufen (aus einem anderen C# Klasse)

PlanPublisher.Instance.UpdateStatus(plan.Id, $"Publishing started for {plan.Name}..."); 

Javascript

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> 
<script src="~/scripts/jquery.signalR-2.2.0.min.js"></script> 
<script src="http://localhost:8080/signalr/hubs"></script> 
<script> 
    $(document).ready(function() { 
     $.connection.hub.url = "http://localhost:8080/signalr"; 

     var planMessagePublisher = $.connection.planHub; 

     planMessagePublisher.client.updateStatus = function (planId, message) { 
      console.log('Status: ' + planId + ' - ' + message); 
     }; 

     $.connection.hub.start().done(function() { 
      //This works! My PlanHub.Register method gets called successfully 
      planMessagePublisher.server.register(@Model.CompanyId); 

      // New connection ID is successfully sent to console 
      console.log('Now connected, connection ID=' + $.connection.hub.id); 
     }); 
    }); 
</script> 

JS Console Debugger Ausgabe

jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Auto detected cross domain url. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Client subscribed to hub 'planhub'. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Negotiating with 'http://localhost:8080/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22planhub%22%7D%5D'. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: webSockets transport starting. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Connecting to websocket endpoint 'ws://localhost:8080/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAA5D8YUVyzBEG4tTlTaGn0MgAAAAACAAAAAAADZgAAwAAAABAAAABDjF1MaCTzZI0XTM8gC29xAAAAAASAAACgAAAAEAAAAKrk0jv%2FKF4YFzDvNwmSR8IoAAAAacm1d1r7dJpjOtVtCFIFRpugkubyZm1e5Z8OtOFtnhZyEBO1SO4lqhQAAABiG7hBydTiypPh8k2ZYz20ropNxw%3D%3D&connectionData=%5B%7B%22name%22%3A%22planhub%22%7D%5D&tid=6'. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Websocket opened. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: webSockets transport connected. Initiating start request. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: The start request succeeded. Transitioning to the connected state. 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332, keep alive timeout of 20000 and disconnecting timeout of 30000 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Invoking planhub.Register 
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Invoked planhub.Register 

Es erfolgreich registriert, erhält aber nie irgendwelche Daten. Der Breakpoint Clients.All.updateStatus(planId, message); wurde mehrmals getroffen, aber die Konsole erhielt nie zusätzliche Protokolldaten.

EDIT: Es wurde vorgeschlagen, dass ich prüfen, ob ein benutzerdefinierte Abhängigkeit Resolver im Spiel ist oder nicht. Der hier veröffentlichte Code lebt in einem eigenen Projekt mit sehr wenig anderem als dem, was Sie hier sehen. Der Code, der PlanPublisher.UpdateStatus() aufruft, verfügt über einen benutzerdefinierten Abhängigkeits-Resolver, aber das sollte keine Rolle spielen, da es in einer eigenen Assembly isoliert ist. PlanPublisher.cs und PlanHub.cs sind in einem sehr einfachen Projekt enthalten, das nur auf SignalR.Core und SignalR.SelfHost verweist.

+1

Sie müssen minimal Beispiel schaffen, die das Problem reproduziert. Ich habe gerade versucht, mit dem genauen Code zu laufen, der sowohl auf der Server- als auch auf der Client-Seite bereitgestellt wurde, und es lief problemlos. – Evk

+0

@Scott, hast du es irgendwie gelöst? Denn ich stehe vor genau demselben Problem. Der lustige Teil - wenn ich versuche, für die Gruppe zu veröffentlichen, funktioniert es, aber nicht für Alle. Auf der anderen Seite, wenn ich ein separates Projekt erstellen, nur um diese Funktionalität auszuprobieren, funktioniert alles gut. – Max

Antwort

2

Versuchen Sie folgendes:

public void UpdateStatus(int planId, string message) 
{ 
    var clients = GlobalHost.ConnectionManager.GetHubContext<PlanHub>().Clients; 
    clients.All.updateStatus(planId, message); 
} 

Ich denke, das Problem ist, dass PlanPublisher vor dem Hub Kontext initialisiert (und Clients) erstellt wird.

+0

Danke für den Vorschlag. Ich habe es versucht, aber das gleiche Verhalten. – Scott

+0

Können Sie das Debugging der .js-Konsole posten? '$ .connection.hub.logging = true;' –

2

Ich habe versucht, Ihr Beispiel zu vereinfachen (mit SignalR 2.2.0)

Hub Klasse:

public class PlanHub : Hub 
{ 
    private const string GroupPrefix = "PlanGroup_"; 

    // hubcontext 
    private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext <PlanHub>(); 

    public void Register(int companyId) 
    { 
     Groups.Add(Context.ConnectionId, $"{GroupPrefix}{companyId}"); 
    } 

    public void Unregister(int companyId) 
    { 
     Groups.Remove(Context.ConnectionId, $"{GroupPrefix}{companyId}"); 
    } 

    // static method using hub context 
    public static void Static_UpdateStatus(int planId, string message) 
    { 
     hubContext.Clients.All.updateStatus(planId, message); 
    } 
} 

Da ich nicht wirklich einen Backend habe, und ich weiß nicht, wie du gehst zu tun, dass ich einrichten nur einen Timer die Methode aufzurufen aus C# alle 10 Sekunden.

Aufruf und Dummy-Timer:

public void startTimer() 
    { 
     timer = new System.Timers.Timer(); 
     timer.Elapsed += new System.Timers.ElapsedEventHandler(ExecuteTimerJob); 
     timer.Interval = 10000; // 10 sec 
     timer.Start(); 
    } 

    public static void ExecuteTimerJob(object source, System.Timers.ElapsedEventArgs e) 
    { 
     // this is the call from C# 
     PlanHub.Static_UpdateStatus(123, "some message"); 
    } 

JS:

$(function() { 
    var planHub = $.connection.planHub; 
    $.connection.hub.start().done(function() { 
     console.debug('Connected to PlanHub...'); 
    }) 
    planHub.client.updateStatus = function (planId, message) { 
     console.log("planId: " + planId); 
     console.log("message: " + message); 
    } 
}); 

Ergebnis in Browser-Konsole:

enter image description here

Verwandte Themen