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

SignalR调用方法后断开连接,提示找不到ParseMessage

SignalR调用StartTimer触发断开,报错找不到"ParseMessage"

我有两个独立的.NET 7应用,分别作为SignalR服务端和客户端。连接能正常建立,但点击「Start Timer」按钮调用StartTimer方法时会触发断开逻辑,报错显示找不到"ParseMessage"。


服务端Hub代码

using Microsoft.AspNetCore.SignalR;

namespace SignalRTest;

public class MyHub : Hub
{
    // 映射用户连接与活跃计时器(多用户场景可用)
    private static readonly Dictionary<string, CancellationTokenSource> UserTimers = new Dictionary<string, CancellationTokenSource>();

    public override async Task OnConnectedAsync()
    {
        string connectionId = Context.ConnectionId;
        Console.WriteLine($"Client connected: {connectionId}");

        await Clients.Client(connectionId).SendAsync("ReceiveMessage", $"Welcome! Your connection ID is {connectionId}");
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        string connectionId = Context.ConnectionId;
        Console.WriteLine($"Client disconnected: {connectionId}");

        if (exception != null)
        {
            Console.WriteLine($"Disconnected due to an error: {exception.Message}");
        }

        if (UserTimers.ContainsKey(connectionId))
        {
            UserTimers[connectionId].Cancel();
            UserTimers.Remove(connectionId);
        }

        await base.OnDisconnectedAsync(exception);
    }

    public async Task StartTimer()
    {
        var connectionId = Context.ConnectionId;

        if (UserTimers.ContainsKey(connectionId))
        {
            await Clients.Caller.SendAsync("ReceiveMessage", "Timer already running.");
            return;
        }

        var cts = new CancellationTokenSource();
        UserTimers[connectionId] = cts;

        await Clients.Caller.SendAsync("ReceiveMessage", "Timer started.");

        int counter = 0;
        while (!cts.Token.IsCancellationRequested)
        {
            counter += 5;
            await Clients.Caller.SendAsync("ReceiveTimerUpdate", counter);
            try
            {
                await Task.Delay(5000, cts.Token);
            }
            catch (TaskCanceledException)
            {
                break;
            }
        }
    }

    public async Task StopTimer()
    {
        var connectionId = Context.ConnectionId;
        if (UserTimers.ContainsKey(connectionId))
        {
            UserTimers[connectionId].Cancel();
            UserTimers.Remove(connectionId);
            await Clients.Caller.SendAsync("ReceiveMessage", "Timer stopped.");
        }
        else
        {
            await Clients.Caller.SendAsync("ReceiveMessage", "No active timer found.");
        }
    }
}

客户端Index.html代码

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SignalR Timer Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.js"></script>
</head>
<body>
    <button id="startButton">Start Timer</button>
    <button id="stopButton">Stop Timer</button>
    <div id="timerOutput"></div>

    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("https://localhost:7156/my-hub", {
                withCredentials: true
            })
            .withAutomaticReconnect()
            .build();

        connection.start().then(() => {
            console.log("Connected to SignalR");
        }).catch(err => console.error(err));

        document.getElementById("startButton").addEventListener("click", () => {
            connection.invoke("StartTimer").catch(err => console.error(err));
        });

        document.getElementById("stopButton").addEventListener("click", () => {
            connection.invoke("StopTimer").catch(err => console.error(err));
        });

        connection.on("ReceiveTimerUpdate", (counter) => {
            document.getElementById("timerOutput").innerText = `Time: ${counter} seconds`;
        });

        connection.on("ReceiveMessage", (message) => {
            console.log(message);
        });
    </script>
</body>
</html>

点击按钮后的日志

服务端日志

服务端日志截图

客户端日志

客户端日志截图


问题解决方法

核心原因

服务端基于.NET 7(对应SignalR 7.x协议),但客户端引入的是SignalR 8.0.7版本的JS库,跨版本的协议不兼容导致消息解析失败,触发断开连接并抛出"找不到ParseMessage"的错误。

修复步骤

  1. 统一SignalR版本:将客户端的SignalR JS库替换为与.NET 7匹配的7.x版本,例如7.0.20(最新稳定版):
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/7.0.20/signalr.js"></script>
    
  2. 确认Hub路由配置:检查服务端Program.cs中是否正确注册Hub路由,确保与客户端withUrl中的地址一致:
    // Program.cs中添加
    app.MapHub<MyHub>("/my-hub");
    
  3. 验证长任务逻辑:服务端StartTimer的异步循环实现正确,无需修改,版本统一后即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:25:18