2016-04-30 3 views
12

У меня есть самодостаточное приложение SignalR, работающее в контексте консольного приложения. Я подключаюсь к концентраторам внутри него, используя класс-оболочку, чтобы я не мог ссылаться на сборки SignalR.Core из моего проекта ASP.NET. Таким образом, это еще один класс C# из моего приложения, который отвечает за передачу сообщений связанным клиентам.Клиенты SignalR 2.2, не получающие сообщений

Я могу назвать методы PlanHub (Register и Unregister) непосредственно с Javascript, эти точки останова попадают. Однако, когда я вызываю методы-клиенты из класса за пределами концентратора (даже если я использую Clients.All для устранения проблем с регистрацией группы), клиенты никогда не получат сообщение. Что я делаю не так?

При запуске этого кода я могу убедиться, что код Clients.All.updateStatus(planId, message); успешно удалён, но ничего не записывается в консоль на клиенте.

Вот соответствующий код:

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

Вызов кода (из другого C# класса)

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 Output

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 

Он регистрирует успешно, но никогда не получает каких-либо данных. Точка останова Clients.All.updateStatus(planId, message); была поражена несколько раз, но консоль никогда не получала никаких дополнительных данных регистрации.

EDIT: Было высказано предположение, что я смотрю, работает ли пользовательский зависимый преобразователь. Код, размещенный здесь, живет в своем собственном проекте с очень небольшим количеством, кроме того, что вы видите здесь. Код, который вызывает PlanPublisher.UpdateStatus() У пользователя есть настраиваемый зависимый преобразователь, но это не имеет значения, поскольку он изолирован в своей собственной сборке. PlanPublisher.cs и PlanHub.cs содержатся в очень простом проекте, который имеет ссылки только на SignalR.Core и SignalR.SelfHost.

+1

Вам необходимо предоставить минимальный пример, который воспроизводит проблему. Я просто попытался запустить с точным кодом, который вы предоставили на сервере и на стороне клиента, и все прошло отлично, без каких-либо проблем. – Evk

+0

@Scott, вам это удалось как-то решить? Потому что я столкнулся с такой же проблемой. Смешная часть - если я пытаюсь опубликовать ее для группы, она работает, но не для всех. С другой стороны, когда я создаю отдельный проект, чтобы попробовать эту функциональность, все работает отлично. – Max

ответ

2

Попробуйте это:

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

Я думаю, что проблема в том, что PlanPublisher инициализируется перед контекстом хаба (и клиентов) создаются.

+0

Спасибо за предложение. Просто попробовал, такое же поведение. – Scott

+0

Можете ли вы опубликовать отладку консоли .js? '$ .connection.hub.logging = true;' –

2

Я попытался упростить ваш пример (используя SignalR 2.2.0) Класс

Hub:

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

Так как я на самом деле не имеют бэкенд, и я не знаю, как вы собираетесь сделать это, я просто установить таймер для вызова метода из C# каждые 10 секунд.

Призвание и фиктивная таймер:

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

Результат в консоли браузера:

enter image description here

Смежные вопросы