Blazor WebAssembly聊天应用SignalR的OnDisconnectedAsync方法未触发问题
解决方法
1. 适配非正常断开的超时逻辑
直接关闭浏览器属于非正常断开场景,客户端不会主动向服务端发送断开信号,SignalR服务端默认设置了30秒的DisconnectTimeout超时,超时后才会判定客户端离线并触发OnDisconnectedAsync方法。关闭浏览器后保持服务端运行30秒以上,即可观察到断点命中。
调试阶段可以临时缩短超时时间加快验证,在服务端Program.cs中修改配置:
builder.Services.AddSignalR(opt => { // 调试用超时时间,生产环境建议保留默认30秒 opt.DisconnectTimeout = TimeSpan.FromSeconds(5); });
2. 补充客户端主动断开逻辑
如果需要用户关闭页面/退出应用时立即触发离线回调,需要在Blazor WebAssembly客户端补充连接销毁逻辑,主动通知服务端断开:
// 客户端维护SignalR连接的组件中添加销毁逻辑 protected override async ValueTask DisposeAsync() { if (HubConnection != null) { await HubConnection.StopAsync(); await HubConnection.DisposeAsync(); } await base.DisposeAsync(); }
3. 完善服务端方法的异常处理
当前实现缺少空判断和异常捕获,若Context.User为空会抛出异常导致方法提前终止,可能影响调试命中,建议调整实现:
public override async Task OnDisconnectedAsync(Exception? exception) { var userId = _userManager.GetUserId(Context?.User); if (!string.IsNullOrEmpty(userId)) { // 此处添加离线状态广播逻辑 } await base.OnDisconnectedAsync(exception); }
4. 开启Debug日志排查底层问题
如果上述操作后依然无法触发,可在服务端appsettings.json中开启SignalR调试日志,定位是否存在中间件拦截、认证失效等底层问题:
{ "Logging": { "LogLevel": { "Microsoft.AspNetCore.SignalR": "Debug", "Microsoft.AspNetCore.Http.Connections": "Debug" } } }
启动服务后复现断开场景,查看日志中是否存在断开相关的报错记录即可定位问题。
内容的提问来源于stack exchange,提问作者omar wasfi
相关产品推荐
相关产品推荐

