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

SignalR收到服务器关闭消息错误,注册监听方法后连接异常如何解决

你遇到的报错核心是SignalR无法序列化Task类型对象,结合你贴的代码,具体有3个必改问题:

  • 前端异步逻辑顺序错误:hubConnection.start() 是异步方法,你没有等待连接完成就直接读取connectionId、赋值connection对象,会偶发获取到空值,部分场景下也会导致监听事件注册失效。
  • 后端异步方法未等待执行完成就传参:你在OnConnectedAsync、OnDisconnectedAsync里调用_elasticRepository.GetAllAsync(_indexName)后没有加await,直接把未完成的Task对象传给了SendAsync方法,SignalR尝试序列化Task时就会抛出你截图里的错误。你注释掉UserConnected相关逻辑后不会触发序列化Task的操作,所以程序能正常运行。
  • 后端重写的连接生命周期方法未正确await父类实现,且无Cookie分支漏了父类方法调用,会导致连接状态异常,另外你手动new的HttpContextAccessor无法正常拿到当前请求上下文,需要从容器注入。

修改后的Vue代码

// 外层方法需要标注async,比如写在async mounted()或者自定义async方法中
const hubConnection = new signalR.HubConnectionBuilder()
        .configureLogging(signalR.LogLevel.Debug)
        .withUrl("http://localhost:7002/ChatHub", {
          skipNegotiation: true,
          transport: signalR.HttpTransportType.WebSockets,
        })
        .build();
// 先注册所有监听事件再启动连接,避免连接成功后事件漏发
hubConnection.on("UserConnected",(users) => console.log(users));
hubConnection.on(categoryId, (all) => {
  all = JSON.parse(all);
  this.userMessage = {
    id: all.Id,
    text: all.Text,
    userId:all.UserId,
    userName:all.UserName,
    categoryName: all.CategoryName,
    createdOn: all.CreatedOn,
  };          
  this.messages.push(this.userMessage);
  console.log(this.userMessages);
});
// 等待连接成功后再读取连接ID
await hubConnection.start();
this.connectionId = hubConnection.connectionId;
this.connection = hubConnection; 

修改后的C# ChatHub代码

首先需要在Program.cs中注册HttpContextAccessor:

builder.Services.AddHttpContextAccessor();

再修改ChatHub实现:

using Microsoft.AspNetCore.SignalR;
using System.Text;
using Microsoft.AspNetCore.Http;
using System.Net.Http.Headers;
using System.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Collections.Generic;
using System.Threading.Tasks;
using Message.Dal.Abstract;
using Message.Dal.Model;
using Microsoft.Extensions.Configuration;
namespace Message.Dal.SignalRHub
{
    public class ChatHub : Hub
    {
        private readonly IHubContext<ChatHub> _chatHub;    
        private readonly IHttpContextAccessor _httpContextAccessor; 
        private readonly IElasticRepository<OnlineUserModel> _elasticRepository;  
        private readonly string _indexName;
        public ChatHub(IHubContext<ChatHub> chatHub,IElasticRepository<OnlineUserModel> elasticRepository,IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
        {
            _chatHub = chatHub; 
            // 从构造函数注入HttpContextAccessor,不要手动new
            _httpContextAccessor = httpContextAccessor;
            _elasticRepository = elasticRepository;
            _indexName = configuration["elasticsearchserver:User"].ToString();
        }
        public async Task SendMessage(Guid categoryId,string message)
        {          
            await _chatHub.Clients.All.SendAsync(categoryId.ToString(),message);           
        }        
        
        public override async Task OnConnectedAsync()
        {      
           var token = string.Empty;           
           var httpContext = _httpContextAccessor.HttpContext.Request.Cookies;
           var onlineUserModel = new OnlineUserModel();
           onlineUserModel.Id = Context.ConnectionId;           
           if(httpContext.Any())
           {
               token = httpContext.FirstOrDefault(x=> x.Key == "CodeChatBackend").Value;
               if(AuthenticationHeaderValue.TryParse(token,out var headerVal))
                {                
                    var handler = new JwtSecurityTokenHandler();
                    var val = handler.ReadJwtToken(headerVal.ToString());  
                    onlineUserModel.UserName = val.Claims.FirstOrDefault(x => x.Type == "Name").Value;           
                } 
                var checkOnlineUser = await _elasticRepository.GetUserAsync(onlineUserModel.UserName,_indexName); 
                if(checkOnlineUser == null)
                {
                    await _elasticRepository.CreateUserAsync(onlineUserModel.Id,onlineUserModel,_indexName);
                }       
                var getOnlineUser = await _elasticRepository.GetAllAsync(_indexName);
                await _chatHub.Clients.All.SendAsync("UserConnected",getOnlineUser);
           }
           // 无论是否有Cookie都要调用父类连接逻辑
           await base.OnConnectedAsync();         
        }     

         public override async Task OnDisconnectedAsync(Exception exception)
        {
            await _elasticRepository.DeleteUserAsync(Context.ConnectionId,_indexName); 
            var getOnlineUser = await _elasticRepository.GetAllAsync(_indexName);
            await _chatHub.Clients.All.SendAsync("UserConnected",getOnlineUser);   
            await base.OnDisconnectedAsync(exception);  
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 21:45:00