web-dev-qa-db-fra.com

ASP.NET Core RC2 SignalR Hub Context en dehors du thread de demande

J'essaie actuellement le RC2 libération de ASP.NET Core et je rencontre un problème avec SignalR. Je dois pouvoir envoyer des messages au client en dehors du thread de demande.

Maintenant, dans le framework .NET complet, vous pouvez faire ceci comme:

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

Mais en ASP.NET Core il n'y a pas de GlobalHost.

J'ai trouvé une question similaire: Comment obtenir le contexte du concentrateur SignalR dans un projet vNext?

Où la deuxième réponse fournit une méthode pour obtenir le hubcontext en dehors du thread de demande, mais cela ne fonctionne pas non plus dans ASP.NET Core.

Ma question est donc la suivante: comment obtenir le contexte du concentrateur en dehors de la portée de la demande dans ASP.NET Core?

18
larzz11

Vous devrez extraire la version actuelle de github de: Signalr Github (Commit: b95ac7b au moment de l'écriture)

Une fois que vous avez cela et que vous avez chargé la solution ou ajouté les trois projets à votre solution existante, vous devrez modifier project.json dans les trois projets.

Microsoft.AspNetCore.SignalR.Server - project.json

Vous verrez des références à la version 1.1.0- * (RC3) de chaque assemblage. Remplacez-les par le RC2 actuel, jusqu'à ce que vous voyiez ce qui suit

"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",

Enregistrez maintenant le fichier et les dépendances seront mises à jour.

Faites de même avec les fichiers Messaging et Infrastructure project.json, en remplaçant tout 1.1.0- * par 1.0.0

Une fois cela fait, vous pouvez ajouter une référence de projet à votre projet principal de Microsoft.AspNetCore.SignalR.Server

Maintenant que vous l'avez chargé, ouvrez votre Startup.cs

Dans la méthode ConfigureServices, ajoutez:

 services.AddSignalR();

A l'intérieur de la méthode Configurer ajoutez:

 app.UseSignalR();

Ensuite, ajoutez une instruction using et importez l'espace de noms Infrastructure comme suit:

using Microsoft.AspNetCore.SignalR.Infrastructure;

Et enfin, créez une propriété statique dans Startup.cs appelée ConnectionManager comme suit:

public static IConnectionManager ConnectionManager;

Enfin, ajoutez une propriété IServiceProvider à la méthode Configure dans Startup.cs (besoin d'importer l'espace de noms System). Chargez ensuite ConfigurationManager à partir de cela.

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

Maintenant, dans vos hubs/n'importe où ailleurs, au lieu d'utiliser Globalhost, utilisez simplement le démarrage. Par exemple:

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

Une autre possibilité consiste à injecter votre HubContext dans votre contrôleur comme:

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

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

Ensuite, vous pouvez également appeler

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

Mais vous dirigerez ensuite les méthodes d'appel sur tous les clients.

Voir aussi Appelez la méthode Hub SignalR Core du contrôleur pour une autre possibilité

7
Stephu

Si vous souhaitez utiliser votre contexte de concentrateur en dehors du contrôleur comme dans un service, vous pouvez essayer ceci.

Dans votre classe StartUp:

    private IHubContext<SomeHub> hubContext;

Dans la méthode ConfigureServices injectez le hubContext dans votre service:

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

Dans la méthode Configure:

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

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

Cela a résolu mon problème de ne pas pouvoir appeler les méthodes client à partir d'une classe de service backend.

3
Max