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

使用HttpClient SendAsync调用API触发两次的问题及解决咨询

问题:使用HttpClient调用API时接口被触发两次

我编写了使用HttpClient的SendAsync方法的代码,测试时发现API接口被触发了两次。相关代码如下:

控制器代码

[HttpGet("GetAllStores")]
public async Task<bookstores> GetAllStores()
{
   Console.WriteLine("Trigger Stores");
   return await dbContext.Set<bookstores>().ToListAsync();
}

HttpClient代码

public async Task<IEnumerable<bookstores>> FetchAllStores()
{
    var requestContent = new HttpRequestMessage
    {
        Method = HttpMethod.Get
    };
    var response = await httpClient.SendAsync("http://127.0.0.1:5000/GetAllStores", HttpCompletionOption.ResponseHeadersRead);
    response.EnsureSuccessStatusCode();
    return JsonSerializer.Deserialize<bookstores>(await response.Content.ReadAsStringAsync(), defaultJsonSerializerOptions);
}

测试代码

public async Task GetSettingProfile_AsExpected()
{
    var sut = new ApiClient(
        new HttpClient() { BaseAddress=new Uri("http://localhost:40331") });
   
    await sut.FetchAllStores();
}

控制台输出显示“Trigger Stores”两次,请问如何让API仅被调用一次?


解决方法

1. 修正BaseAddress与请求URL的冲突

你的HttpClient实例设置了BaseAddress = new Uri("http://localhost:40331"),但调用SendAsync时又传入了完整URL"http://127.0.0.1:5000/GetAllStores",这种混合使用的方式可能导致HttpClient内部URL解析异常,触发重复请求。

修复方案:
选择一种URL使用方式:

  • 保留BaseAddress,只传入相对路径:
    var response = await httpClient.SendAsync("GetAllStores", HttpCompletionOption.ResponseHeadersRead);
    
  • 移除BaseAddress,直接使用完整URL,避免路径拼接冲突。

2. 调整HttpCompletionOption参数

使用HttpCompletionOption.ResponseHeadersRead时,HttpClient会在读取响应头后就标记请求完成,但后续读取响应内容时如果出现异常,可能触发底层的重试逻辑。部分服务器或中间件也可能对这种模式的请求做出重复响应。

修复方案:
使用默认的HttpCompletionOption.ResponseContentRead(可省略该参数),确保请求在完整读取响应内容后才完成:

var response = await httpClient.SendAsync("http://127.0.0.1:5000/GetAllStores");

3. 修正序列化类型不匹配问题

你的方法返回值声明为IEnumerable<bookstores>,但序列化时使用了JsonSerializer.Deserialize<bookstores>(...),类型不匹配会导致序列化失败。如果HttpClient配置了自动重试策略,失败的请求会被重新发送。

修复方案:
将泛型类型改为与返回值一致的集合类型:

return JsonSerializer.Deserialize<IEnumerable<bookstores>>(await response.Content.ReadAsStringAsync(), defaultJsonSerializerOptions);

4. 排查测试环境的重复执行可能

部分测试框架(如xUnit)如果检测到异步测试存在异常,可能会自动重试测试方法;或者测试类中存在多个测试方法调用了同一个接口,导致重复触发。

排查方向:

  • 确认测试类中只有GetSettingProfile_AsExpected这一个测试方法调用FetchAllStores
  • 检查测试框架的配置,是否开启了测试重试机制

内容的提问来源于stack exchange,提问作者Carrie Kaski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:20:27