ASP.NET Core RC2 SignalR Hub Контекст вне запроса

В настоящее время я тестирую RC2 выпуск ASP.NET Core, и у меня возникает проблема с SignalR. Мне нужно иметь возможность отправлять сообщения клиенту за пределами потока запросов.

Теперь в полной платформе .NET вы можете сделать это, например:

var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.<SendMessage>()

Но в ASP.NET Core нет GlobalHost.

Я нашел аналогичный вопрос: Как получить контекст концентратора SignalR в проекте vNext?

Где второй ответ предоставляет метод для получения hubcontext вне потока запросов, но это также не работает в ASP.NET Core.

Итак, мой вопрос: как я могу получить контекст концентратора вне области запроса в ASP.NET Core?

Ответ 1

Вам нужно будет вытащить текущую версию github из: Signalr Github (Commit: b95ac7b во время записи)

После этого, и загрузите решение, или добавьте все три проекта в существующее решение, вам нужно будет изменить project.json во всех трех проектах.

Microsoft.AspNetCore.SignalR.Server - project.json

Вы увидите ссылки на версию 1.1.0- * (RC3) каждой сборки. Измените их на текущий RC2, пока не увидите следующее

"Microsoft.AspNetCore.DataProtection": "1.0.0",
"Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0",
"Microsoft.AspNetCore.Http.Extensions": "1.0.0",
"Microsoft.Extensions.DependencyModel": "1.0.0",

Теперь сохраните файл, и зависимости будут обновляться.

Сделайте то же самое с файлами проекта Сообщения и Инфраструктура project.json, заменив любой 1.1.0- * на 1.0.0

Как только это будет сделано, вы можете добавить ссылку на проект в свой основной проект Microsoft.AspNetCore.SignalR.Server

Теперь, когда вы загрузили, откройте Startup.cs

Внутри метода ConfigureServices добавьте:

 services.AddSignalR();

Внутри метода Настроить добавьте:

 app.UseSignalR();

Затем добавьте оператор using и импортируйте пространство имен инфраструктуры следующим образом:

using Microsoft.AspNetCore.SignalR.Infrastructure;

И, наконец, создайте статическое свойство в Startup.cs, называемом ConnectionManager, следующим образом:

public static IConnectionManager ConnectionManager;

Наконец, добавьте свойство IServiceProvider к методу Configure в Startup.cs(необходимо импортировать пространство имен System). Затем загрузите ConfigurationManager из этого.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
    {
        ConnectionManager = serviceProvider.GetService<IConnectionManager>();

Теперь, в ваших хабах/где-либо еще, вместо использования Globalhost, просто используйте startup. Например:

IHubContext context = Startup.ConnectionManager.GetHubContext<SomeHub>();
context.Clients.All.someMethod();

Ответ 2

Другая возможность - добавить свой HubContext в свой контроллер, например:

public VarDesignCommController(IHubContext<VarDesignHub> hubcontext)
{
    HubContext = hubcontext;
    ...
}

private IHubContext<VarDesignHub> HubContext
{
    get;
    set;
}

Затем вы также можете вызвать

await this.HubContext.Clients.All.InvokeAsync("Completed", id);

Но тогда вы будете называть методы вызова для всех клиентов.

См. также метод Call SignRR Core Hub от контроллера для другой возможности

Ответ 3

Если вы хотите использовать свой контекст концентратора вне контроллера, как в сервисе, вы можете попробовать это.

В вашем классе StartUp:

    private IHubContext<SomeHub> hubContext;

В методе ConfigureServices введите hubContext в ваш сервис:

    services.AddScoped<ISomeService, SomeService>((factory) => {
        return new SomeService(hubContext);
    });

В методе настройки:

    app.UseSignalR(routes =>
        {
            routes.MapHub<SomeHub>("/hubRoute");
        });

        hubContext = app.ApplicationServices.GetService<IHubContext<SomeHub>>();

Это решило мою проблему невозможности вызова клиентских методов из внутреннего класса обслуживания.