Løsning 1
En anden mulighed er at injicere din HubContext i din controller som:
public VarDesignCommController(IHubContext<VarDesignHub> hubcontext)
{
HubContext = hubcontext;
...
}
private IHubContext<VarDesignHub> HubContext
{ get; set; }
Så kan du også ringe
await this.HubContext.Clients.All.InvokeAsync("Completed", id);
Men så vil du dirigere opkaldsmetoder på alle klienter.
Løsning 2
Du kan også arbejde med indtastede hubs:Simpelt opret en grænseflade, hvor du definerer, hvilke metoder din server kan kalde på klienterne:
public interface ITypedHubClient
{
Task BroadcastMessage(string name, string message);
}
Arv fra Hub:
public class ChatHub : Hub<ITypedHubClient>
{
public void Send(string name, string message)
{
Clients.All.BroadcastMessage(name, message);
}
}
Injicer den indtastede hubcontext i din controller, og arbejd med den:
[Route("api/demo")]
public class DemoController : Controller
{
IHubContext<ChatHub, ITypedHubClient> _chatHubContext;
public DemoController(IHubContext<ChatHub, ITypedHubClient> chatHubContext)
{
_chatHubContext = chatHubContext;
}
// GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
_chatHubContext.Clients.All.BroadcastMessage("test", "test");
return new string[] { "value1", "value2" };
}
}
Det aktuelle svar besvarer ikke det stillede spørgsmål.
Det enkle svar er, at du ikke direkte kan kalde en hub-metode fra en MVC-controller eller andre steder. Dette er ved design. Tænk på hubben som indeholdende slutpunkterne for SignalR Core-klienter at kalde, ikke for server- eller controllermetoderne.
Her er, hvad Microsoft siger (dette er præ-SignalR Core-dokumentation, men det gælder stadig for SignalR Core):
Hvis der er kode i hub'en, som du skal ringe til, er det bedre at placere den i en ekstern klasse eller tjeneste, der er tilgængelig fra hvor som helst.
Så her er et eksempel, der bruger den enkle indbyggede DI-ramme til ASP.NET Core:
Forudsat at koden du skal ringe til er i DoStuff.cs:
public class DoStuff : IDoStuff
{
public string GetData()
{
return "MyData";
}
}
public interface IDoStuff
{
string GetData();
}
I Startup.cs skal du konfigurere en singleton ved hjælp af den indbyggede container:
services.AddSingleton<IDoStuff, DoStuff>();
Hele Startup.cs ser sådan ud:
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?}");
});
}
}
For din hub-klasse, injicer singletonen, og brug den i en metode:
public class MyHub : Hub
{
private readonly IDoStuff _doStuff;
public MyHub(IDoStuff doStuff)
{
_doStuff = doStuff;
}
public string GetData()
{
return _doStuff.GetData();
}
}
Injicer derefter IHubContext og singletonen i din controller:
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();
}
}
Selvfølgelig skal dit Javascript eller en anden klient have et show_data-tilbagekald konfigureret.
Bemærk, at vi bruger den injicerede hub-kontekst til at sende data til alle SignalR-klienter:_hub.Clients.All.SendAsync(...)
Dette er nu veldokumenteret her