使用GlobalHost.ConnectionManager.GetHubContext从外部集线器调用SignalR的客户端方法不起作用 . 但是从集线器内部呼叫确实如此

我正在尝试从.net Web API控制器操作中调用客户端方法 .

我可以这样做吗?

我能找到的唯一一个接近我要做的就是这个:

SignalR + posting a message to a Hub via an action method

在那里,使用GlobalHost.ConnectionManager.GetHubContext从asp.net MVC控制器动作中发送消息 .

当我在我的Web API操作中尝试时,不会抛出任何错误,但是从不在客户端调用方法“methodInJavascript” .

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

当我在该动作中设置断点时,我看到代码正在被触及并执行 . 但是在javascript客户端没有任何事情发生 .

为什么? Web API是如此不同,以至于这不起作用?有没有其他人尝试过并取得了成功?

当我从我的中心“内部”调用“methodInJavascript”时,它完美地工作 . 从.net Web API控制器操作中调用时,将无法正常工作 .

UPDATE:

在研究这个问题后,我没有解决方案 . 我只能假设像这样的例子中缺少一些东西Server to client messages not going through with SignalR in ASP.NET MVC 4和这个calling SignalR hub from WebAPI controller issues就像有一个额外的配置步骤来启用从HubContext或其他东西调用 . 我最初在这里发布的代码就像那些示例中出现的代码没有被证明有任何缺陷 . 任何人都可以看到代码中的缺陷吗?从html调用工作 . 我在我的应用程序中广泛使用它,从未遇到过问题 . 我从未在API控制器工作中看到来自HubContext的调用 . 没有错误 . 对客户端没有任何结果 .

SOLVED (kind of):

上面的代码确实可以正常工作 when published . 但是,通过localhost在Visual Studio开发环境中不起作用 . 客户端没有错误但没有结果 . 将代码原样发布到Web上的真实服务器确实有效 . 我从没想过'd be a difference so I never tried. Figured if it didn'在本地工作它现在不能正常工作但我在开发环境中通过localhost工作了.1307389_t . 无法使用断点等进行本地测试 .

我感觉这是signalr虚拟目录 . 在本地运行和发布时有些不同 . 不知道什么,但我看到很多帖子,如http://www.bitwisejourneys.com/signalr-hosting-in-iis-a-nasty-gotcha/ . 现在阅读,看看是否有办法让它在本地和发布工作 .

回答(2)

2 years ago

我几天前遇到过同样的问题 . 花了我2天的时间才找到解决方案并解决它 . 经过一番认真的调查后,问题的根本原因是我自定义的信号依赖解析器 .

最后我找到了this link,这就是这样说的:

替换DependencyResolver您可以通过设置GlobalHost.DependencyResolver来更改DependencyResolver以使用您选择的DI容器 . 注意:不要覆盖PreApplicationStart中的全局解析器,它不起作用,或者它只在某些时候起作用 . 在PostApplicationStart(使用WebActivator)或Global.asax中执行此操作 .

这里的重要地方是NOTE . 当然,在信号器2.0之后,这个文档变成 deprecated . 所以我在这里混合了一些新的SignalR API . 在不再使用WebActivatorEx的新SignalR API中 . OwinStartup首选而不是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);
        }
    }
}

在你的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);
        }
    }
}

我不想在这里发送所有代码,以显示真正的问题 .

所以对我来说,现在一切正常 . 依赖注入也有效 . 但不好的地方到处都是我搜索过David Fowler说的“它的设计” . 我开始认为这种设计确实是必要的或错误的 .

希望它可以帮助那些研究相同问题的人 .

2 years ago

我遇到了同样的问题,它与IoC(无论是ninject还是城堡等)有关 . 如果将全局依赖关系解析器设置为IoC管理器,它还将替换SignalR内部管道解析 . 这使您的SingleTon客户端集线器无法正常工作 .

我解决了它只是让服务器集线器被IoC-ed下面的代码需要SignalHubActivator(你可以在互联网上找到它)

现在,GlobalHost.ConnectionManager.GetHubContext将返回单个实例,并且将再次正确调用客户端方法!

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


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