如何配置Refit的反序列化时机及指定状态码跳过序列化?
解决Refit反序列化时机与特定状态码处理问题
嘿,针对你遇到的Refit序列化坑,我有几个实用方案帮你搞定👇
1. 能不能配置Refit执行反序列化的时机?
当然可以!Refit提供了多种灵活的方式让你干预反序列化的时机:
- 最直接的是用
ApiResponse<T>包装返回类型,这样你能拿到原始响应,完全自己决定什么时候触发反序列化; - 也可以通过自定义
IResponseHandler或者HttpContentSerializer来全局控制反序列化的触发条件。
2. 能不能指定特定Http状态码不尝试序列化响应体?
必须可以!而且正好能解决你遇到的203状态码返回HTML导致序列化异常的问题。下面给你两种常用的解决方法:
方法一:全局自定义响应处理器(推荐)
通过实现IResponseHandler,你可以在Refit处理响应前拦截请求,根据状态码直接跳过反序列化并抛出ApiException:
public class CustomAuthFailureHandler : IResponseHandler { public async Task<HttpResponseMessage> HandleResponse(HttpResponseMessage response) { // 拦截203状态码(你的认证失败场景) if (response.StatusCode == HttpStatusCode.NonAuthoritativeInformation) { // 可选:读取HTML响应体,方便后续排查问题 var htmlContent = await response.Content.ReadAsStringAsync(); // 直接抛出ApiException,Refit就不会再尝试反序列化了 throw new ApiException(response, null, htmlContent); } // 其他状态码交给Refit默认处理 return response; } }
然后把这个处理器注册到Refit配置中:
var refitSettings = new RefitSettings { ResponseHandler = new CustomAuthFailureHandler() }; // 初始化API客户端时传入配置 var myApi = RestService.For<IMyApi>("https://your-api-url.com", refitSettings);
方法二:接口层面用ApiResponse<T>手动处理
如果你不想做全局配置,可以在接口方法中返回ApiResponse<T>,自己控制每个请求的处理逻辑:
// 定义API接口 public interface IMyApi { [Get("/your-target-endpoint")] Task<ApiResponse<YourDataDto>> GetData(); }
调用时手动判断状态码并处理:
var apiResponse = await myApi.GetData(); if (!apiResponse.IsSuccessStatusCode) { if (apiResponse.StatusCode == HttpStatusCode.NonAuthoritativeInformation) { // 处理认证失败逻辑,比如读取HTML内容 var htmlContent = await apiResponse.Content.ReadAsStringAsync(); throw new InvalidOperationException("认证失败,响应内容:" + htmlContent); } // 其他错误让Refit抛出标准ApiException apiResponse.EnsureSuccessStatusCode(); } // 成功状态下再执行反序列化 var data = apiResponse.Content;
额外优化:指定仅200为成功状态码
如果你想让Refit只把200视为成功状态,可以在配置中设置SuccessStatusCodeRange:
var refitSettings = new RefitSettings { // 限定只有200属于成功状态范围 SuccessStatusCodeRange = new Range<int>(200, 200) };
结合上面的自定义响应处理器,就能完美避免非200状态下的不必要序列化啦!
内容的提问来源于stack exchange,提问作者Jamie Peacock
相关产品推荐
相关产品推荐

