You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SignalR客户端与服务端版本兼容异常求助

解决SignalR版本不兼容的偶发连接失败问题

问题核心分析

你遇到的错误"You are using a version of the client that isn't compatible with the server. Client version 1.5, server version undefined",本质是服务器端SignalR组件版本不一致,加上可能的前端JS加载异常,导致握手时版本校验失败。你的后端混合使用了1.2.2和2.2.3版本的SignalR包,这是最可能的根源。

分步解决方案

1. 统一后端所有SignalR包版本

当前后端依赖的SignalR包版本混乱:Microsoft.AspNet.SignalR.Client和Microsoft.AspNet.SignalR.Owin是1.2.2,而Core和SystemWeb是2.2.3。这种混合版本会导致服务器内部处理握手请求时,返回的版本信息异常(出现undefined)。

操作:

  • 在NuGet包管理器中,将所有Microsoft.AspNet.SignalR.*相关包统一升级到2.2.3版本,确保没有遗漏任何SignalR相关依赖。

2. 确保前端仅加载正确版本的SignalR JS

错误中显示客户端版本为1.5,说明前端可能加载了旧版本的SignalR脚本(可能是页面中存在多个版本引用,或者缓存了旧脚本)。

操作:

  • 检查index.html中SignalR JS的引用,确认是v2.2.3,并且没有其他地方引入了旧版本的jquery.signalR-x.x.x.js。
  • 强制清除浏览器缓存,或者给脚本URL添加版本号(比如/scripts/jquery.signalR-2.2.3.js?v=20240520),避免缓存旧脚本。

3. 修复前端连接重试逻辑

当前代码只在$.connection不存在时重试,但连接失败(fail回调)时没有重试逻辑,且重试间隔固定500ms,容易导致频繁请求加重服务器负担。

修改后的前端代码:

startHub(self) {
    if ($.connection && $.connection.hub && $.connection.userNotificationHub) {
        $.connection.hub.url = Util.url + 'signalr';
        $.connection.hub.logging = true;

        $.connection.userNotificationHub.client.onLogoutCustomMessage = self.onLogoutCustom;
        
        const startConnection = () => {
            $.connection.hub.start()
                .done(function (connection) {
                    console.log('Service Started', connection.id);
                    self.retryCount = 0; // 连接成功重置重试计数
                })
                .fail(function (error) {
                    console.log('Could not Connect!', error);
                    // 指数退避重试:1s, 2s, 4s... 最多到30s
                    const retryDelay = Math.min(Math.pow(2, self.retryCount || 0) * 1000, 30000);
                    self.retryCount = (self.retryCount || 0) + 1;
                    setTimeout(() => startConnection(), retryDelay);
                });
        };
        
        startConnection();
    } else {
        setTimeout(() => self.startHub(self), 1000);
    }
}

4. 启用CORS(如果存在跨域场景)

如果前端和后端部署在不同域名下,必须启用CORS,否则握手请求会被浏览器拦截,可能表现为版本不兼容的错误。

修改后端Startup.cs代码,启用CORS:

public void Configuration(IAppBuilder app)
{
    GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(3600);
    
    app.Map("/signalr", map =>
    {
        // 启用CORS,允许所有来源(生产环境建议限制特定域名)
        map.UseCors(CorsOptions.AllowAll);
        
        var hubConfiguration = new HubConfiguration
        {
            EnableJavaScriptProxies = true,
            EnableDetailedErrors = true
        };
        
        map.RunSignalR(hubConfiguration);
    });
}

5. 可选:关闭JavaScript代理,手动指定Hub名称

如果启用EnableJavaScriptProxies导致代理生成异常,可以尝试关闭代理,手动指定Hub名称,避免版本相关的代理问题。

修改前端连接代码:

// 关闭自动代理,手动创建Hub连接
const hubConnection = $.hubConnection(Util.url + 'signalr');
const userNotificationHub = hubConnection.createHubProxy('userNotificationHub');

userNotificationHub.on('onLogoutCustomMessage', self.onLogoutCustom);

hubConnection.logging = true;
hubConnection.start()
    .done(connection => console.log('Service Started', connection.id))
    .fail(error => console.log('Could not Connect!', error));

修改后端HubConfiguration:

var hubConfiguration = new HubConfiguration
{
    EnableJavaScriptProxies = false, // 关闭自动代理
    EnableDetailedErrors = true
};

额外排查点

  • 检查服务器日志:启用EnableDetailedErrors后,服务器会输出更详细的错误信息,查看是否有握手阶段的异常日志。
  • 检查网络请求:在浏览器开发者工具中查看SignalR的握手请求(/signalr/negotiate),查看返回的ProtocolVersion是否为2.2.3,如果返回异常,说明服务器端版本仍有问题。

内容的提问来源于stack exchange,提问作者Ankit Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 13:43:25