You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:06:09