.Net 服务端如何获取SignalR客户端上报异常的完整信息
问题原因
SignalR默认的JSON序列化器不会完整序列化Exception类型的所有成员:Exception的核心属性如StackTrace、HResult等多为只读属性,默认序列化规则不会处理这类属性,且Exception存在循环引用结构(如InnerException嵌套),最终反序列化到服务端时只会生成一个默认的空Exception实例,因此只会返回通用提示。
推荐解决方案(手动构造可序列化DTO)
不要直接传输Exception对象,自定义日志传输类,手动提取需要的异常字段,该方案可控性高、无安全风险、兼容性好:
- 客户端定义传输DTO
public class ExceptionLogDto { // 可根据需要扩展字段,比如错误码、发生时间、客户端标识等 public string ExceptionType { get; set; } public string Message { get; set; } public string StackTrace { get; set; } public string InnerExceptionInfo { get; set; } }
- 修改客户端上报逻辑
private async Task LogCallBack(Exception ex) { try { var logDto = new ExceptionLogDto { ExceptionType = ex.GetType().FullName, Message = ex.Message, StackTrace = ex.StackTrace, InnerExceptionInfo = ex.InnerException?.ToString() }; await Send("ClientLogs", logDto); } catch (Exception sendEx) { Serilog.Log.Error($"日志上报失败 - {sendEx}"); } }
- 修改服务端接收逻辑
public void ClientLogs(ExceptionLogDto logDto) { Serilog.Log.Error("客户端上报异常:类型={Type}, 消息={Message}, 堆栈={StackTrace}, 内部异常={Inner}", logDto.ExceptionType, logDto.Message, logDto.StackTrace, logDto.InnerExceptionInfo); }
其他可选方案(不推荐)
如果一定要直接传输Exception对象,需要统一配置服务端和客户端的SignalR序列化规则,以Newtonsoft.Json为例:
- 服务端配置序列化规则
builder.Services.AddSignalR() .AddNewtonsoftJsonProtocol(opt => { opt.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.Auto; opt.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
- 客户端也要对应使用Newtonsoft.Json序列化器,且保持序列化参数和服务端一致。
该方案存在序列化失败、敏感信息泄露、传输体积大等问题,非必要不使用。
内容的提问来源于stack exchange,提问作者HovhannesAvanesyan
相关产品推荐
相关产品推荐

