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

React对接ASP.NET Core SignalR获取活跃连接数报错

React对接ASP.NET Core SignalR协商失败问题修复

问题表现

React前端连接ASP.NET Core后端SignalR Hub时抛出错误:

Error: Failed to complete negotiation with the server: TypeError: Failed to fetch

修复步骤

1. 补全后端CORS配置

SignalR跨域请求对CORS有明确要求,必须允许凭证,且Origin必须精确匹配前端地址。在ASP.NET Core的Program.cs中添加如下配置:

// 服务注册阶段添加CORS策略
builder.Services.AddCors(options =>
{
    options.AddPolicy("SignalRAllowFront", policy =>
    {
        policy.WithOrigins("http://localhost:3000") // 替换为React前端实际运行地址,不要带末尾斜杠
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // SignalR强制要求开启该项
    });
});

// 中间件配置阶段,注意顺序:UseRouting之后,UseAuthorization、MapHub之前调用
app.UseCors("SignalRAllowFront");

// Hub路由配置保持原有即可
endpoints.MapHub<OnConnectionHub>("hubs/onConnectionHub");

注意:如果前端用HTTPS、端口不是3000,必须把Origin改成和浏览器地址栏里前端地址完全一致,包括协议、域名、端口三部分。

2. 修正后端Hub的异步阻塞写法

原有代码里用.GetAwaiter().GetResult()属于同步阻塞异步代码的写法,高并发下会引发线程池死锁,改成标准async/await写法:

public class OnConnectionHub : Hub
{
    public static int ConnectionCount { get; set; }

    public override async Task OnConnectedAsync()
    {
        ConnectionCount++;
        await Clients.All.SendAsync("updateConnectionCount", ConnectionCount);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        ConnectionCount--;
        await Clients.All.SendAsync("updateConnectionCount", ConnectionCount);
        await base.OnDisconnectedAsync(exception);
    }
}

3. 修复React组件连接逻辑

原有代码把连接创建、事件绑定、启动逻辑直接写在组件函数体中,每次组件重渲染都会重复创建连接、重复绑定事件,是前端侧的核心问题。将连接逻辑移入useEffect,保证只在组件挂载时执行一次,卸载时清理连接:

import { HubConnectionBuilder, LogLevel } from "@microsoft/signalr";
import { useState, useEffect } from "react";

export const ConnectionCount = () => {
    const [connectionCount, setConnectionCount] = useState(0);

    useEffect(() => {
        // 创建连接实例
        const connection = new HubConnectionBuilder()
            .withUrl("https://localhost:7199/hubs/onConnectionHub")
            .configureLogging(LogLevel.Information) // 开启调试日志,方便排查问题
            .withAutomaticReconnect() // 可选配置,开启自动重连
            .build();

        // 绑定服务端推送事件
        connection.on("updateConnectionCount", (count) => {
            setConnectionCount(count);
        });

        // 启动连接并处理异常
        const startConnect = async () => {
            try {
                await connection.start();
            } catch (err) {
                console.error("连接失败,5秒后重试", err);
                setTimeout(startConnect, 5000);
            }
        };
        startConnect();

        // 组件卸载时关闭连接,清理资源
        return () => {
            connection.stop();
        };
    }, []); // 空依赖数组,仅在组件首次挂载时执行

    return <p>Active members {connectionCount}</p>;
};

排查验证

改完后如果仍有问题,按以下顺序验证:

  • 直接在浏览器访问https://localhost:7199/hubs/onConnectionHub/negotiate?negotiateVersion=1,如果返回404,检查Hub路由配置和中间件顺序是否正确。
  • 如果浏览器控制台明确报CORS错误,重新检查CORS配置的Origin是否完全匹配,是否遗漏AllowCredentials()配置。
  • 如果后端用HTTPS,确认本地开发证书已被系统信任,访问后端地址没有证书风险提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:12:32