Отправка сообщений из-за пределов концентратора

Центр SignalR является основной абстракцией для отправки сообщений клиентам, подключенным SignalR к серверу. Кроме того, можно отправлять сообщения из других мест в приложении с помощью IHubContext службы. В этой статье объясняется, как получить доступ SignalRIHubContext к запросу для отправки уведомлений клиентам извне концентратора.

Примечание

Объект IHubContext предназначен для отправки уведомлений клиентам, он не используются для вызова методов в Hub.

Просмотрите или скачайте пример кода (описание процедуры скачивания).

Получение экземпляра IHubContext

В ASP.NET Core SignalRможно получить доступ к экземпляру путем IHubContext внедрения зависимостей. Экземпляр можно внедрить в контроллер, ПО промежуточного IHubContext слоя или другую службу ВНЕДРЕНИЯ. Используйте экземпляр для отправки сообщений клиентам.

Примечание

Это отличается от ASP.NET версии 4.xSignalR, которая использовала GlobalHost для предоставления доступа к .IHubContext ASP.NET Core имеет платформу внедрения зависимостей, которая устраняет необходимость в этом глобальном одноэлементном объекте.

Внедрение экземпляра IHubContext в контроллер

Экземпляр можно внедрить IHubContext в контроллер, добавив его в конструктор:

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

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

С доступом к экземпляру IHubContextвызовите клиентские методы, как если бы вы находились в самом концентраторе:

public async Task<IActionResult> Index()
{
    await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
    return View();
}

Получение экземпляра ПО промежуточного IHubContext слоя

Получите доступ к конвейеру ПО промежуточного IHubContext слоя следующим образом:

app.Use(async (context, next) =>
{
    var hubContext = context.RequestServices
                            .GetRequiredService<IHubContext<ChatHub>>();
    //...
    
    if (next != null)
    {
        await next.Invoke();
    }
});

Примечание

Когда клиентские методы вызываются из-за пределов Hub класса, вызывающий объект не связан с вызовом. Таким образом, нет доступа к свойствам и Others свойствам.ConnectionIdCaller

Получение экземпляра IHubContext из IHost

IHubContext Доступ к веб-узлу полезен для интеграции с областями за пределами ASP.NET Core, например с использованием сторонних платформ внедрения зависимостей:

    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            var hubContext = host.Services.GetService(typeof(IHubContext<ChatHub>));
            host.Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => {
                    webBuilder.UseStartup<Startup>();
                });
    }

Внедрение строго типизированного HubContext

Чтобы внедрить строго типизированный HubContext, убедитесь, что центр наследует от Hub<T>. Внедрите его с помощью IHubContext<THub, T> интерфейса, а не IHubContext<THub>.

public class ChatController : Controller
{
    public IHubContext<ChatHub, IChatClient> _strongChatHubContext { get; }

    public ChatController(IHubContext<ChatHub, IChatClient> chatHubContext)
    {
        _strongChatHubContext = chatHubContext;
    }

    public async Task SendMessage(string user, string message)
    {
        await _strongChatHubContext.Clients.All.ReceiveMessage(user, message);
    }
}

Дополнительные сведения см. в разделе "Строго типизированные концентраторы ".

Использование IHubContext в универсальном коде

Внедренный IHubContext<THub> экземпляр можно привести к IHubContext без указания универсального Hub типа.

class MyHub : Hub
{ }

class MyOtherHub : Hub
{ }

app.Use(async (context, next) =>
{
    var myHubContext = context.RequestServices
                            .GetRequiredService<IHubContext<MyHub>>();
    var myOtherHubContext = context.RequestServices
                            .GetRequiredService<IHubContext<MyOtherHub>>();
    await CommonHubContextMethod((IHubContext)myHubContext);
    await CommonHubContextMethod((IHubContext)myOtherHubContext);

    await next.Invoke();
}

async Task CommonHubContextMethod(IHubContext context)
{
    await context.Clients.All.SendAsync("clientMethod", new Args());
}

Это полезно, если:

  • Написание библиотек, у которых нет ссылки на конкретный Hub тип, который используется приложением.
  • Написание кода, который является универсальным и может применяться к нескольким различным Hub реализациям

Дополнительные ресурсы