问题
I am currently trying out the RC2
release of ASP.NET Core
and I am running into an issue with SignalR
. I need to be able to send messages to the client outside of the request thread.
Now in the full .NET framework you can do this like:
var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.<SendMessage>()
But in ASP.NET
Core there is no GlobalHost
.
I found a similar question: How to get SignalR Hub Context in a vNext Project?
Where the second answer provides a method to get the hubcontext outside the request thread, but this also does not work in ASP.NET Core
.
So my question is: how can I get the hub context outside of the request scope in ASP.NET Core?
回答1:
You will have to pull the current github version from : Signalr Github (Commit: b95ac7b at time of writing)
Once you have this, and have loaded the solution, or added all three of the projects to your existing solution, you will need to change project.json in all three projects.
Microsoft.AspNetCore.SignalR.Server - project.json
You will see references to version 1.1.0-* (RC3) of each assembly. Change these to the current RC2, until you see the following
"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",
Now save the file, and the dependencies will update.
Do the same with The Messaging and Infrastructure project.json file's, replacing any 1.1.0-* with 1.0.0
Once that is done, you can add a project reference to your main project of Microsoft.AspNetCore.SignalR.Server
Now that you have that loaded, Open your Startup.cs
Inside the ConfigureServices method, add:
services.AddSignalR();
Inside the Configure Method add:
app.UseSignalR();
Next, add a using statement and import the Infrastructure namespace as follows:
using Microsoft.AspNetCore.SignalR.Infrastructure;
And finally Create a static property in Startup.cs called ConnectionManager as follows:
public static IConnectionManager ConnectionManager;
Finally add a IServiceProvider property to the Configure method in Startup.cs (Need to import the System namespace). Then Load the ConfigurationManager from this.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
ConnectionManager = serviceProvider.GetService<IConnectionManager>();
Now, in your hubs / anywhere else, instead of using Globalhost, Simply use startup. For example:
IHubContext context = Startup.ConnectionManager.GetHubContext<SomeHub>();
context.Clients.All.someMethod();
回答2:
Another possibility is to inject your HubContext into your controller like:
public VarDesignCommController(IHubContext<VarDesignHub> hubcontext)
{
HubContext = hubcontext;
...
}
private IHubContext<VarDesignHub> HubContext
{
get;
set;
}
Then you can also call
await this.HubContext.Clients.All.InvokeAsync("Completed", id);
But then you will direct call methods on all clients.
See also Call SignalR Core Hub method from Controller for an other possibility
回答3:
If you want to use your hub context outside of the controller like in a service, you can try this.
In your StartUp class:
private IHubContext<SomeHub> hubContext;
In the ConfigureServices method inject the hubContext in your service:
services.AddScoped<ISomeService, SomeService>((factory) => {
return new SomeService(hubContext);
});
In the Configure method:
app.UseSignalR(routes =>
{
routes.MapHub<SomeHub>("/hubRoute");
});
hubContext = app.ApplicationServices.GetService<IHubContext<SomeHub>>();
This solved my issue of not being able to call client methods from a backend service class.
来源:https://stackoverflow.com/questions/37318209/asp-net-core-rc2-signalr-hub-context-outside-request-thread