如何在C#泛型API客户端中返回结构化ApiResponse<T>类型?
可行实现方案
首先你需要定义一个独立的ApiResponse<T>包装类,它和业务模型完全解耦,不需要业务模型继承它。然后修正MakeHttpRequestAsync的泛型定义,在方法内部完成请求、错误捕获和结果包装,业务代码只需处理这个统一的返回类型即可。
1. 定义统一的ApiResponse类型
这个类型用来封装所有API请求的结果,包含状态标识、业务数据和错误信息:
public class ApiResponse<T> { // 请求是否成功 public bool IsSuccess { get; set; } // 业务返回数据(请求成功时有效) public T? Data { get; set; } // 错误信息(请求失败时有效) public string? ErrorMessage { get; set; } // HTTP状态码(可选,便于排查问题) public int? StatusCode { get; set; } }
2. 修正HttpClientHelper的MakeHttpRequestAsync方法
你遇到的TResponse找不到错误,大概率是因为方法的泛型参数没有正确声明。下面是修正后的泛型方法实现,统一处理各类请求错误:
public class HttpClientHelper { private readonly HttpClient _httpClient; public HttpClientHelper(HttpClient httpClient) { _httpClient = httpClient; } // 正确声明泛型参数T(对应你的业务模型类型) public async Task<ApiResponse<T>> MakeHttpRequestAsync<T>(string url, HttpMethod method, HttpContent? content = null) { var response = new ApiResponse<T>(); try { using var request = new HttpRequestMessage(method, url); if (content != null) { request.Content = content; } var httpResponse = await _httpClient.SendAsync(request); // 处理HTTP状态码错误 if (!httpResponse.IsSuccessStatusCode) { response.IsSuccess = false; response.StatusCode = (int)httpResponse.StatusCode; response.ErrorMessage = $"HTTP请求失败,状态码:{(int)httpResponse.StatusCode},原因:{httpResponse.ReasonPhrase}"; return response; } // 序列化业务数据到T类型 var responseContent = await httpResponse.Content.ReadAsStringAsync(); response.Data = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); response.IsSuccess = true; response.StatusCode = (int)httpResponse.StatusCode; } catch (HttpRequestException ex) { response.IsSuccess = false; response.ErrorMessage = $"请求异常:{ex.Message}"; } catch (JsonException ex) { response.IsSuccess = false; response.ErrorMessage = $"数据序列化失败:{ex.Message}"; } catch (Exception ex) { response.IsSuccess = false; response.ErrorMessage = $"未知错误:{ex.Message}"; } return response; } }
3. 业务代码调用示例
业务代码不需要处理底层HTTP错误,只需要判断ApiResponse<T>的IsSuccess状态即可:
// 注入或实例化HttpClientHelper var httpClientHelper = new HttpClientHelper(new HttpClient()); // 调用API,业务模型为UserInfo(无需继承任何类) var apiResponse = await httpClientHelper.MakeHttpRequestAsync<UserInfo>("https://api.example.com/users/1", HttpMethod.Get); if (apiResponse.IsSuccess) { // 处理业务数据 var user = apiResponse.Data; Console.WriteLine($"用户名:{user?.Name}"); } else { // 处理错误 Console.WriteLine($"请求失败:{apiResponse.ErrorMessage},状态码:{apiResponse.StatusCode}"); } // 你的业务模型示例 public class UserInfo { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; }
关键说明
- 泛型参数
T直接对应业务模型类型,业务模型和ApiResponse<T>完全解耦,不需要继承关系。 - 所有HTTP请求错误、序列化错误都在
MakeHttpRequestAsync内部捕获并包装,业务代码只需关注结果状态。 - 之前的
TResponse找不到错误,是因为方法定义时未正确声明泛型参数(正确写法应为Task<ApiResponse<T>> MakeHttpRequestAsync<T>(...),而非使用未声明的TResponse)。
内容的提问来源于stack exchange,提问作者Enrico
相关产品推荐
相关产品推荐

