如何在RestSharp中细粒度区分并处理网络/服务器/序列化错误?
RestSharp细粒度错误处理方案咨询
我的RestSharp客户端代码
var opts = new RestClientOptions("http://api.muyservice.com/") { // 反序列化失败时不将ResponseStatus设为Error FailOnDeserializationError = false, }; using var client = new RestClient(opts); var request = new RestRequest("myEndpoint"); var response = await client.ExecuteAsync<ResponseDto>(request); // 错误处理逻辑 // 网络错误?无法直接区分 // 同时覆盖4xx/5xx状态码(404除外) if (response.ResponseStatus != ResponseStatus.Completed) { // 记录网络错误 } else if (response.StatusCode != HttpStatusCode.OK) { // HTTP请求完成,但服务器返回非200结果 // 处理服务器错误 if (response.StatusCode == HttpStatusCode.BadRequest) { // 从响应体提取错误详情 } else { // 处理通用服务器错误 } } else if (response.Data == null) { // 序列化失败 } else { // 一切正常,处理结果 }
遇到的问题
我希望对网络、服务器和序列化错误做差异化的细粒度处理(比如记录不同细节、请求超时时提示调整配置),但目前遇到以下阻碍:
- 网络错误或服务器返回4xx/5xx(除404外)时,
response.ResponseStatus都会变为Error,无法直接区分两类错误 - 请求超时后,
ResponseStatus为TimedOut,但ErrorMessage和ErrorException仅显示“Operation was canceled”,未明确标注是超时导致 IsSuccessfulStatusCode会将HTTP 404判定为成功状态- 无专门的序列化错误状态标识,若
ResponseDto允许null作为有效值,完全无法判断是否是序列化失败导致的null
请问RestSharp中有没有直接实现细粒度错误处理的方法?
解决方案
1. 区分网络错误与HTTP错误
RestSharp中,网络类错误(如连接失败、DNS解析失败、超时)会导致ResponseStatus变为TimedOut/Aborted/Error,且StatusCode为0;而HTTP错误(4xx/5xx)的ResponseStatus始终是Completed,同时StatusCode会对应具体的HTTP状态码。
调整判断逻辑即可区分:
if (response.ResponseStatus != ResponseStatus.Completed) { // 处理网络类错误 if (response.ResponseStatus == ResponseStatus.TimedOut) { // 专门处理超时:记录并提示调整超时配置 Console.WriteLine("请求超时,建议修改RestClientOptions.Timeout参数"); } else { // 其他网络错误:比如连接失败、DNS异常等 var exception = response.ErrorException; // 记录异常堆栈等详情 } } else { // HTTP请求已完成,处理状态码逻辑 bool isExpectedSuccess = response.StatusCode == HttpStatusCode.OK; if (!isExpectedSuccess) { // 处理4xx/5xx错误 if (response.StatusCode == HttpStatusCode.NotFound) { // 单独处理404场景 } else { // 提取服务器返回的错误响应体 var errorContent = response.Content; } } }
2. 明确识别超时错误
RestSharp的超时本质是触发TaskCanceledException,可通过ErrorException的类型和取消标记判断:
if (response.ResponseStatus == ResponseStatus.TimedOut) { if (response.ErrorException is TaskCanceledException tce && !tce.CancellationToken.IsCancellationRequested) { // 这是真正的超时,而非手动取消请求 Console.WriteLine($"请求超时,当前超时配置:{opts.Timeout}毫秒"); } }
3. 自定义成功状态码判断
不要依赖内置的IsSuccessfulStatusCode,自己定义符合业务需求的判断逻辑:
bool IsExpectedSuccess(HttpStatusCode code) { // 只把200视为成功,可根据业务调整 return code == HttpStatusCode.OK; } // 使用示例 if (IsExpectedSuccess(response.StatusCode)) { // 处理成功逻辑 } else { // 处理HTTP错误 }
4. 检测序列化错误
由于设置了FailOnDeserializationError = false,序列化失败时Data会为null,但如果ResponseDto允许null,可通过response.ErrorException判断——序列化失败时该属性会包含序列化器抛出的异常(如JsonSerializationException):
if (response.ResponseStatus == ResponseStatus.Completed && IsExpectedSuccess(response.StatusCode)) { if (response.Data == null) { // 检查是否存在序列化异常 if (response.ErrorException != null && response.ErrorException.GetType().Name.Contains("Serialization")) { // 处理序列化错误:记录异常信息、重试等 } else { // 服务器确实返回了null有效值 } } else { // 正常处理返回数据 } }
额外建议:封装错误处理扩展方法
可以把这些判断逻辑抽离成扩展方法,避免重复代码:
public static class RestResponseExtensions { public static bool IsNetworkError(this RestResponse response) { return response.ResponseStatus != ResponseStatus.Completed; } public static bool IsTimeoutError(this RestResponse response) { return response.ResponseStatus == ResponseStatus.TimedOut && response.ErrorException is TaskCanceledException tce && !tce.CancellationToken.IsCancellationRequested; } public static bool IsSerializationError(this RestResponse response) { return response.ResponseStatus == ResponseStatus.Completed && response.StatusCode == HttpStatusCode.OK && response.Data == null && response.ErrorException != null && response.ErrorException.GetType().Name.Contains("Serialization"); } }
使用时只需直接调用:
if (response.IsNetworkError()) { if (response.IsTimeoutError()) { // 处理超时 } else { // 处理其他网络错误 } } else if (!IsExpectedSuccess(response.StatusCode)) { // 处理HTTP错误 } else if (response.IsSerializationError()) { // 处理序列化错误 } else { // 正常处理业务逻辑 }
内容的提问来源于stack exchange,提问作者Serg
相关产品推荐
相关产品推荐

