Как получить контекст концентратора SignalR в ядре ASP.NET?

Я пытаюсь получить контекст для концентратора, используя следующее:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<SomeHub>();

Проблема в том, что GlobalHost не определен. Я вижу, это часть dll SignalR.Core. На данный момент у меня в файле .json моего проекта есть следующие зависимости:

"Microsoft.AspNet.SignalR.Server": "3.0.0-*"

Если я добавлю последнюю доступную версию Core:

"Microsoft.AspNet.SignalR.Server": "3.0.0-*",
"Microsoft.AspNet.SignalR.Core" :  "2.1.2"

Я получаю массу ошибок, потому что сервер и ядро ​​конфликтуют. Если я изменю их на использование версии «3.0.0- *», все конфликты исчезнут, но GlobalHost не будет найден. Если я удалю сервер и только пользователь Core версии 2.1.2, тогда GlobalHost будет работать, но все остальные вещи, требующие сервера, очевидно, нет.

Любые идеи?


person Community    schedule 04.12.2014    source источник
comment
Текущее решение предоставлено в этом ответе на аналогичный вопрос.   -  person brichins    schedule 09.03.2017


Ответы (5)


Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager - это внедренная служба DI, через которую вы можете получить контекст концентратора ... Например:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Infrastructure;
using Microsoft.AspNet.Mvc;

public class TestController : Controller
{
     private IHubContext testHub;

     public TestController(IConnectionManager connectionManager)
     {
         testHub = connectionManager.GetHubContext<TestHub>();
     }
 .....
person Kiran Challa    schedule 04.12.2014
comment
Раньше это работало в RC1, но не работает в RC2 (я получаю сообщение об ошибке) - вы знаете, как это исправить? - person Jakub Wisniewski; 23.05.2016
comment
привет, откуда вы взяли эту информацию. Я не мог найти документы после нескольких часов поиска. Благодарность.. - person SHM; 10.07.2017

IConnectionManager больше не существует в SignalR для ASP.Net Core.
Я использовал HubContext для получения доступа к концентратору.

public class HomeController : Controller
{
    private readonly IHubContext<LiveHub> _hubContext;

    public HomeController(IHubContext<LiveHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public void SendToAll(string message)
    {
        _hubContext.Clients.All.InvokeAsync("Send", message);
    }
}

Я использую .net core 2.0.0 и SignalR 1.0.0-alpha1-final

person Soren    schedule 20.09.2017
comment
Привет! Не могли бы вы опубликовать пример того, как вы регистрируете класс HubContext в контейнере IoC? - person Andrew Nikolin; 27.09.2017
comment
@AndrewNikolin, регистрировать HubContext не нужно. просто представьте свой хаб в Configure методе. app.UseSignalR(routes => { routes.MapHub<LiveHub>("live"); }); Думаю, к services.AddSignalR(); HubContext будет зарегистрирован автоматически ... - person Soren; 28.09.2017
comment
Спасибо, это очень помогло. Но как мне получить доступ к HubContext извне контроллера? Есть ли способ вызвать метод концентратора также из статического контекста? - person lenniep; 16.10.2017
comment
@lenniep HubContext доступен везде, где доступен IServiceProvider. вы можете получить доступ к IServiceProvider в статическом классе с помощью некоторых советов и уловок но это совсем не рекомендуется. - person Soren; 17.10.2017
comment
@Soren имеет смысл, большое спасибо. Я буду избегать этого, так как согласен, что это довольно плохой дизайн. Это тоже помогло мне: blog.ploeh.dk/2010/02/ 03 / ServiceLocatorisanAnti-Pattern - person lenniep; 17.10.2017
comment
для меня связи с этим фрагментом кода становятся пустыми. Любая помощь!! - person santu47; 27.12.2018
comment
Я думал, что мне нужно реализовать IHubContext<MyHub>, а затем ввести это с помощью DI, но потом я понял, что мне придется реализовать Clients и Groups и т.д., но, прочитав комментарии, я понял, что services.AddSignalR(); фактически вводит IHubContext<MyHub> по умолчанию, поэтому это меня сильно спасло разочарования! документация не совсем ясна по этому поводу, насколько мне известно. спасибо @Soren! - person Niklas; 10.05.2019
comment
@Soren, который работает, если у Hub нет других зависимостей, то есть от MyApi. - person William Jockusch; 13.02.2020
comment
для .net 5 await _hubContext.Clients.All.SendAsync (yourmethod, yourparameters); - person user2475096; 01.05.2021

Чтобы использовать концентратор в фоновой службе, помимо контроллеров, вы должны использовать интерфейс IHostedService и получить концентратор с помощью DI.

public class MyBackgroundService : IHostedService, IDisposable
{
    public static IHubContext<NotifierHub> HubContext;

    public MyBackgroundService(IHubContext<NotifierHub> hubContext)
    {
        HubContext = hubContext;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        //TODO: your start logic, some timers, singletons, etc
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        //TODO: your stop logic
        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

Затем вы можете вызвать свой хаб из любого места вашего кода из статического поля HubContext:

MyBackgroundService.HubContext.Clients.All.SendAsync("UpdateData", myData).Wait();

Подробнее об IHostedService: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1

Вы можете создать и запустить таймер в MyBackgroundService и вызвать хаб в ElapsedEvent.

person RenanStr    schedule 16.10.2018
comment
Большое спасибо. Это было именно то, что мне нужно было сделать, чтобы заставить SignalR работать из фоновых (зависающих) заданий. - person Aaron; 16.11.2019

Я добавил код в свой Startup.cs, чтобы получить ссылку на ConnectionManager, который затем можно использовать для создания GetHubContext в любое время из любого места вашего кода. Подобно ответу Нимо, но немного по-другому, может быть, проще.

services.AddSignalR(options =>
{
    options.Hubs.EnableDetailedErrors = true;
});

var provider = services.BuildServiceProvider();

//Hold on to the reference to the connectionManager
var connManager = provider.GetService(typeof(IConnectionManager)) as IConnectionManager;

//Use it somewhere else
var hub = connManager.GetHubContext<SignalHub>();
person Matt Watson    schedule 12.06.2016
comment
Как найти connManager где-нибудь еще? Разве вам не нужно как-то вводить или обновлять его, поскольку он не статичен? - person stibay; 19.07.2016
comment
Начиная с последней сборки, 0.0.2-alpha1-21709, этот метод больше не работает. Я создаю статическую переменную для IConnectionManager в классе запуска. Когда на него ссылаются в другом классе, IHubContext доступен, но hub.Clients.All.SendMessage (foo) не отправляет сообщение клиентам. - person Bill Shihara; 28.07.2016
comment
@BillShihara - вы решили проблему, о которой говорили здесь? - person Glen Little; 03.04.2018

Мне нужно было иметь доступ к Hub Context извне потока запроса приложения, потому что я подписывался на сообщения NServicebus, и мне нужно было иметь возможность запускать клиентскую функцию, когда я получаю сообщение.

Вот как я это отсортировал:

public static IServiceProvider __serviceProvider;

затем во время начальной настройки

app.UseServices(services =>
        {
            __serviceProvider = new ServiceCollection()
            .BuildServiceProvider(CallContextServiceLocator.Locator.ServiceProvider);
        });

Затем в любом другом месте приложения vNext asp.net (любой другой поток)

 var manager = Startup.__serviceProvider.GetRequiredService<IConnectionManager>();
            var hub = manager.GetHubContext<ChatHub>();

Надеюсь это поможет!

person nimo    schedule 05.12.2014