【问题标题】:SignalR CORS error on request to Hub method向 Hub 方法请求 SignalR CORS 错误
【发布时间】:2015-08-05 21:39:52
【问题描述】:

我只是想让 SignalR 设置运行 owin 托管,我想通过 JavaScript 客户端进行连接。应该很容易吧?我能够快速设置并运行 SignalR 服务器以及连接到服务器的客户端。但是,当在客户端调用 done 回调时,我尝试调用集线器的 Send 方法,并在控制台中收到以下错误:

XMLHttpRequest 无法加载 http://localhost:8199/signalr/signalr/send?transport=serverSentEvents&clien...AxBg6iaFwlK50s2DnurE&connectionData=%5B%7B%22name%22%3A%22testhub%22%7D%5D。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost' 不允许访问。响应的 HTTP 状态代码为 500。

这是我的服务器端代码:

    public static IAppBuilder UseService(this IAppBuilder app)
    {
        log4net.Config.XmlConfigurator.Configure();
        app.UseService(NinjectConfig.CreateKernel);
        app.UseLogging();
        app.UseSignalr();
        return app;
    }
    internal static IAppBuilder UseSignalr(this IAppBuilder app)
    {
        app.Map("/signalr", map =>
            {
               map.UseCors(CorsOptions.AllowAll);

                var hubConfig = new HubConfiguration {EnableDetailedErrors = true};
                map.RunSignalR(hubConfig);
            }
        );
        return app;
    }

这里是客户端:

    var connection = $.hubConnection('http://localhost:8199/signalr');
    var testHub = connection.createHubProxy('testHub');

    testHub.on('addMessage', function(name){
        console.log(name);
    });

    connection.start().done(function () {
            testHub.invoke('send', 'testName');
        }).fail(function (e) {
            console.log('Failed to connect');
        });
        connection.error(function(error){
        console.log(error);
    });

为什么 CORS 请求适用于 start 调用而不是后续的 hub 方法调用?

更新: 在网络选项卡中,我可以看到有一个呼叫:http://localhost8199/signalr/negotiate - 此呼叫有效,CORS 标头按预期响应响应

然后调用:http://localhost:8199/signalr/connect 并且该调用也具有正确的 CORS 标头并且可以正常工作。

然后调用:http://localhost:8199/signalr/start 同样的好事发生在这里。

最后有一个调用:http://localhost:8199/signalr/send,这是失败的调用,每个失败消息都有零个 CORS 标头。

更新:

我也试过这样设置我的客户端:

    $.connection.hub.url = 'http://localhost:8199/signalr';
        var proxy = $.connection.testHub;
        proxy.client.addMessage = function(name){
            console.log(name);
    };

    $.connection.hub.start()
    .done(function () {
        console.log($.connection.hub.id);
        proxy.server.sendMessage()
            .done(function(val){
                console.log(val);
            });
     })
    .fail(function (e) {
        console.log('Failed to connect');
    });

我对这项工作的希望不大,因为我觉得问题出在服务器端。但只是想更新我在这里尝试过的内容。

【问题讨论】:

    标签: signalr


    【解决方案1】:

    原来我在浏览器中看到的错误是一条红鲱鱼。服务器端的 CORS 设置没有问题。我最终在 chrome 的控制台中单击错误中的 url:

    XMLHttpRequest 无法加载 http://localhost:8199/signalr/signalr/send?transport=serverSentEvents&clien...AxBg6iaFwlK50s2DnurE&connectionData=%5B%7B%22name%22%3A%22testhub%22%7D%5D。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost' 不允许访问。响应的 HTTP 状态代码为 500。

    这将我带到了一个 .Net 黄屏死机,它告诉我参数名称 s 不能为空,并且存在空引用异常。

    最后证明这是依赖解析器的问题。我们在这个项目中使用 ninject Kernel 来解决依赖关系。如果我的集线器类有无参数构造函数,我不知道 SignalR 需要我通知它我的依赖解析器,但是它确实需要这些信息。以下是我最终做的:

           app.Map("/signalr", map =>
            {
                var resolver = new NinjectSignalRDependencyResolver(kernel);
                GlobalHost.DependencyResolver = resolver;
                map.UseCors(CorsOptions.AllowAll);
    
                var hubConfig = new HubConfiguration { EnableDetailedErrors = true, EnableJSONP = true };
                map.RunSignalR(hubConfig);
            }
    

    所以要吸取的教训是点击超链接,可能会出现更深层次的根本错误。

    【讨论】:

    • 虽然你之前从未说过关于 Ninject 的一句话:)
    • 我遇到了类似的问题,negotiate cors API 正在工作,但 start 失败了,原来问题出在我的 nuget 包上。更新你的 Nuget 包
    【解决方案2】:

    看看这个:http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#crossdomain

    查看注释,他们指出,根据您使用的浏览器,您可能需要修复不同的问题。

    SignalR 1.0.1 Cross-domain request (CORS) with Chrome

    SignalR IE9 Cross Domain request don't work

    在你的启动方法中尝试 EnableJSONP:

        internal static IAppBuilder UseSignalr(this IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
               map.UseCors(CorsOptions.AllowAll);
    
                var hubConfig = new HubConfiguration {
                   EnableDetailedErrors = true,
                   EnableJSONP = true
                };
                map.RunSignalR(hubConfig);
            };
            return app;
        }
    

    【讨论】:

    • 澄清一下,我使用的是来自 Bower 的 Signalr 2.2.0 Nuget 包用于服务器和 2.2.0 JavaScript 包。我也在 Chrome 中遇到问题,所以 JSONP 不是答案。感谢您的回复。
    猜你喜欢
    • 2021-07-02
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 2011-11-24
    • 2021-11-02
    • 2019-09-15
    • 2013-03-06
    • 2018-04-04
    相关资源
    最近更新 更多