Текущий ответ не отвечает на поставленный вопрос.
Простой ответ - вы не можете напрямую вызвать метод концентратора из контроллера MVC или из другого места. Это сделано намеренно. Думайте о концентраторе как о содержащем конечные точки для вызова клиентов SignalR Core, а не для методов сервера или контроллера.
Вот что Microsoft говорит (это документация до SignalR Core, но она по-прежнему применима к SignalR Core):
Вы не создаете экземпляр класса Hub и не вызываете его методы из собственного кода на сервере; все, что делает за вас конвейер SignalR Hubs. SignalR создает новый экземпляр вашего класса Hub каждый раз, когда ему нужно обрабатывать операцию Hub, например, когда клиент подключается, отключается или выполняет вызов метода на сервере.
Поскольку экземпляры класса Hub являются временными, вы не можете использовать их для поддержания состояния от одного вызова метода к другому. Каждый раз, когда сервер получает вызов метода от клиента, новый экземпляр вашего класса Hub обрабатывает сообщение. Чтобы поддерживать состояние с помощью нескольких подключений и вызовов методов, используйте какой-либо другой метод, например базу данных, или статическую переменную в классе Hub, или другой класс, который не является производным от Hub. Если вы сохраняете данные в памяти с помощью такого метода, как статическая переменная в классе Hub, данные будут потеряны при перезапуске домена приложения.
Если вы хотите отправлять сообщения клиентам из вашего собственного кода, который выполняется за пределами класса Hub, вы не можете сделать это, создав экземпляр класса Hub, но вы можете сделать это, получив ссылку на объект контекста SignalR для вашего класса Hub. ...
Если в хабе есть код, который нужно вызвать, лучше поместить его во внешний класс или службу, доступную из любого места.
Итак, вот пример использования простой встроенной инфраструктуры DI для ASP.NET Core:
Предполагая, что код, который вам нужно вызвать, находится в DoStuff.cs:
public class DoStuff : IDoStuff
{
public string GetData()
{
return "MyData";
}
}
public interface IDoStuff
{
string GetData();
}
В Startup.cs настройте синглтон с помощью встроенного контейнера:
services.AddSingleton<IDoStuff, DoStuff>();
Полный Startup.cs выглядит так:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSignalR();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<IDoStuff, DoStuff>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>("/myhub");
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Для вашего класса-концентратора введите синглтон и используйте его в методе:
public class MyHub : Hub
{
private readonly IDoStuff _doStuff;
public MyHub(IDoStuff doStuff)
{
_doStuff = doStuff;
}
public string GetData()
{
return _doStuff.GetData();
}
}
Затем в вашем контроллере введите IHubContext и синглтон:
public class HomeController : Controller
{
private readonly IDoStuff _doStuff;
private readonly IHubContext<MyHub> _hub;
public HomeController(IDoStuff doStuff, IHubContext<MyHub> hub)
{
_doStuff = doStuff;
_hub = hub;
}
public async Task<IActionResult> Index()
{
var data = _doStuff.GetData();
await _hub.Clients.All.SendAsync("show_data", data);
return View();
}
}
Конечно, в вашем Javascript или другом клиенте должен быть настроен обратный вызов show_data.
Обратите внимание, что мы используем внедренный контекст концентратора для отправки данных всем клиентам SignalR: _hub.Clients.All.SendAsync (...)
person
swiftest
schedule
29.10.2018