web-dev-qa-db-fra.com

La méthode client d'appel SignalR à partir du concentrateur extérieur à l'aide de GlobalHost.ConnectionManager.GetHubContext ne fonctionne pas. Mais appeler depuis le hub ne

J'essaie d'appeler une méthode client à partir d'une action de contrôleur d'API Web .net.

Puis-je faire ceci?

Le seul message que je peux trouver qui se rapproche de ce que je cherche à faire est celui-ci:

SignalR + poster un message sur un Hub via une méthode d'action

Là, un message est envoyé à partir d'une action de contrôleur MVC asp.net à l'aide de GlobalHost.ConnectionManager.GetHubContext.

Lorsque j'essaie cela dans mon action d'API Web, aucune erreur n'est générée, mais la méthode "methodInJavascript" n'est jamais invoquée côté client.

    Public ActionResult MyControllerMethod()
    {
        var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
        context.Clients.All.methodInJavascript("hello world");
        // or
        context.Clients.Group("groupname").methodInJavascript("hello world");
    }

Lorsque je définis un point d'arrêt à l'intérieur de cette action, je constate que le code est atteint et exécuté. Cependant, rien ne se passe du côté client javascript.

Pourquoi? L'API Web est-elle si différente sous le capot que cela ne fonctionnera pas? Quelqu'un d'autre a-t-il essayé et réussi?

Lorsque j'appelle la "méthodeInJavascript" de "l'intérieur" de mon hub, cela fonctionne parfaitement. Ne fonctionnera tout simplement pas lorsqu'il est appelé à partir d'une action de contrôleur d'API Web .net.

MISE À JOUR:

Après avoir étudié ce problème, je n'ai pas de solution. Je peux seulement supposer qu'il manque quelque chose dans des exemples comme celui-ci les messages du serveur au client ne passent pas par SignalR dans ASP.NET MVC 4 et cela appel du concentrateur SignalR à partir de problèmes de contrôleur WebAPI comme peut-être il y a une étape de configuration supplémentaire pour activer les appels à partir d'un HubContext ou quelque chose. Le code que j'ai initialement posté ici est comme celui qui apparaît dans ces exemples qui n'a été démontré en aucune façon. Quelqu'un peut-il voir une faille dans le code? Les appels depuis html fonctionnent. Je le fais largement dans mes applications et je ne rencontre jamais de problème. Je n'ai jamais vu un appel de HubContext dans un travail de contrôleur API. Aucune erreur. Tout simplement aucun résultat sur le client.

RESOLU (type de):

Le code ci-dessus fonctionne en effet tel quel lors de sa publication . Cependant, ne fonctionne pas dans l'environnement de développement Visual Studio via localhost. Aucune erreur mais aucun résultat du côté client. La publication du code tel quel sur un vrai serveur sur le web fonctionne en effet. Je n'ai jamais pensé qu'il y aurait une différence alors je n'ai jamais essayé. Si cela ne fonctionnait pas localement, il ne fonctionnerait pas publié. Cela fonctionne en direct maintenant, mais je me demande pourquoi cela ne fonctionne pas via localhost dans l'environnement de développement. Impossible de tester localement avec des points d'arrêt et autres.

J'ai l'impression que c'est ce répertoire virtuel signal. Quelque chose est différent lorsqu'il est exécuté localement ou publié. Je ne sais pas quoi mais je vois beaucoup de messages comme http://www.bitwisejourneys.com/signalr-hosting-in-iis-a-nasty-gotcha/ . Lisez maintenant pour voir s'il existe un moyen de le faire fonctionner localement et publié.

31
Robert

J'ai rencontré le même problème il y a quelques jours. Cela m'a pris 2 jours pour trouver une solution et la résoudre. Après une enquête sérieuse, la cause première du problème était le résolveur de dépendance signal que j'ai défini de manière personnalisée.

À la fin, j'ai trouvé ce lien et cela disait ceci:

Remplacement du DependencyResolver

Vous pouvez modifier DependencyResolver pour utiliser le conteneur DI de votre choix en définissant GlobalHost.DependencyResolver.

REMARQUE: NE PAS remplacer le résolveur global dans PreApplicationStart, cela ne fonctionnera pas ou ne fonctionnera que parfois. Faites-le dans PostApplicationStart (à l'aide de WebActivator) ou dans Global.asax.

L'endroit important ici la NOTE. Bien sûr, après signalr 2.0, cette documentation devient obsolète . J'ai donc mélangé certains d'entre eux avec la nouvelle API SignalR. Dans la nouvelle API SignalR n'utilisant plus WebActivatorEx. OwinStartup préféré au lieu de WebActivator.

[Assembly: OwinStartupAttribute(typeof(YourNamespace.Startup))]
namespace YourNamespace
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //IoC container registration process
            UnityConfig.RegisterComponents();

            UnityConfig.Container.RegisterType<AHub, AHub>();

            HubConfiguration config = new HubConfiguration();
            config.EnableJavaScriptProxies = true;


            //You should remove your dependency resolver code from here to Global.asax Application_Start method. Before setting the MVC properties.
            //config.Resolver = new SignalrDefaultDependencyResolver(UnityConfig.Container); // your dependency resolver
            //


            app.MapSignalR(config);
        }
    }
}

Et dans votre global.asax

namespace YourNamespace
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            //Here your SignalR dependency resolver
            GlobalHost.DependencyResolver = new SignalrDefaultDependencyResolver(UnityConfig.Container);


            //other settings goes on
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

Je ne veux pas envoyer tout le code ici, pour montrer le vrai problème.

Donc pour moi, tout fonctionne bien pour l'instant. L'injection de dépendance fonctionne également. Mais la mauvaise partie est partout où j'ai cherché David Fowler disait "Its by design". J'ai commencé à penser que cette conception était vraiment nécessaire ou une erreur.

J'espère que cela aide quelqu'un d'autre qui fait des recherches pour le même problème.

26
Yusuf Uzun

J'ai eu le même problème, et il est lié à l'IoC (avec quoi que ce soit, comme ninject ou château). Si vous définissez le résolveur de dépendance global sur votre gestionnaire IoC, il remplacera également la résolution du pipeline interne SignalR. Cela rend votre hub client SingleTon ne fonctionne pas correctement.

Je l'ai résolu en ayant uniquement les hubs de serveur étant édités en IoC. Le code ci-dessous nécessite SignalHubActivator (vous pouvez le trouver sur Internet)

Maintenant, GlobalHost.ConnectionManager.GetHubContext renverra l'instance unique ET les méthodes client seront à nouveau appelées correctement!

 //configuration.Resolver = signalrDependency ; dont, this will cause GlobalHost.ConnectionManager to be intercepted by Castle


 configuration.Resolver.Register(typeof(IHubActivator),
                                      () => new SignalHubActivator(container));
2
Egbert Nierop