Вызов клиентов SignalR hub из других частей системы

#c# #javascript #asp.net-mvc #signalr #signalr-hub

#c# #javascript #asp.net-mvc #signalr #signalr-hub

Вопрос:

Я настроил SignalR hub для связи между сервером и клиентом. Код на стороне сервера-концентратора хранится в классе с именем Hooking.cs. Я хочу иметь возможность вызывать метод, определенный в Hooking.cs, чтобы я мог передавать сообщения любым подключенным клиентам из любого места в моем приложении. Похоже, что новый экземпляр Hooking.cs создается для каждого вызова клиент / сервер, поэтому я надеялся, что смогу использовать что-то вроде

 var hooking = new Hooking();
hooking.Test();
  

с помощью метода Test(), определенного в Hooking.cs, такого как

 public static void Test() {
    Clients.test()
}
  

и с помощью javascript на стороне клиента

 var hooking = $.connection.hooking;
hooking.test = function() { alert("test worked"); };
$.connection.hub.start()
  

К сожалению, это не так просто, поскольку клиенты не являются статическими, поэтому недоступны из статического метода.

Просматривая исходный код SignalR, я наткнулся на метод, который выглядел многообещающим, Hubs.Invoke(string hubName, string method, params object[] args) , поэтому я надеюсь, что смогу использовать что-то вроде, Hubs.Invoke("Hooking", "Test") но я не могу заставить его работать.

Любая помощь в этом была бы очень признательна

Комментарии:

1. Но, может быть, вы сможете мне помочь 😉 Есть идеи, как выполнить ваш код js в вашем широковещательном сообщении для всех других клиентов, а не для вызывающего абонента, который отправил сообщение? 🙂

2. К сожалению, я этого не делаю. Я обрабатывал эту клиентскую часть, отправляя идентификатор клиента обратно с ответом и просто не вызывая функцию, если идентификатор совпадает

Ответ №1:

Это правильный способ для SignalR 2.x:

 var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.All.addMessage(message);
  

В принципе, вы можете использовать распознаватель зависимостей для текущего хоста для разрешения IConnectionManager интерфейса, который позволяет вам получить доступ к объекту контекста для концентратора.

Дополнительную информацию можно найти в официальной документации.

Ответ №2:

Hub.GetClients исчез в версии 0.4.0.

Из вики теперь вы можете использовать:

 IConnectionManager connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
dynamic clients = connectionManager.GetClients<MyHub>();
  

Комментарии:

1. И не забудьте добавить using SignalR.Infrastructure;

Ответ №3:

Вы можете легко использовать концентратор, выполнив этот 2 шага-

  1. Создание экземпляра путем внедрения зависимостей следующим образом-

     public class ClassName
    {
        ........
        ........
        private IHubContext _hub;
    
        public BulletinSenderController(IConnectionManager connectionManager)
        {
            _hub = connectionManager.GetHubContext<McpHub>();
            ........
            ........
        }
    
        ............
        ............
    }
      

2. Использование hub объекта, подобного этому-

 _hub.Clients.All.onBulletinSent(bulletinToSend);
  

Больше можно найти здесь .

Пример кода можно найти в этом репозитории git.

Ответ №4:

Посмотрите, как это делается Chat.cs в SignalR.Samples.Hubs.Chat из https://github.com/SignalR/SignalR .

Я вижу там, что статические Dictionary<TKey, TValue> экземпляры создаются вверху, поэтому я полагаю, что они также поддерживаются постоянно, либо Chat класс является сохраняемым экземпляром (?), Либо этот массив каким-то образом обновляется.

Проверьте это, Дэвид Фаулер, вероятно, был бы лучшим в этом.

Комментарии:

1. Да, я использую образцы SignalR, чтобы попытаться решить эту проблему. Словари статичны, поэтому информация сохраняется в нескольких экземплярах класса, поэтому я надеялся, что смогу просто создать экземпляр Hooking.cs и использовать его, но это не работает

Ответ №5:

Это изменилось в .NET Core 2, теперь вы можете использовать внедрение зависимостей следующим образом:

     private readonly IHubContext<MyHub,IMyHubInterface> _hubContext;

    public MyController(MyHub,IMyHubInterface hubContext)
    {
        _hubContext = hubContext;
    }

    public bool SendViaSignalR()
    {
        _hubContext.Clients.All.MyClientSideSignalRMethod(new MyModel());
        return true;
    }