C# ApiController被HttpClient GetAsync调用两次问题求助
解决HttpClient GetAsync导致API接口被调用两次的问题
咱们先拆解下你遇到的这个奇怪问题,核心是同步阻塞异步代码+路由配置的小疏漏,共同导致了接口被执行两次的情况:
1. 同步阻塞异步方法是关键隐患
你的调用代码里混用了.Result和.Wait()这种同步阻塞方式,这在异步编程里是大忌,很容易触发意外的重复请求(比如上下文调度冲突、HttpClient隐性重试):
// 问题代码:同步阻塞异步操作 var response = _client.GetAsync("api/documents/GetAllDocuments").Result; response.Content.LoadIntoBufferAsync().Wait();
正确的姿势是全程用async/await,保持异步流程的一致性,避免阻塞线程导致的异常:
public static async Task<Document> GetAllDocuments() { try { var response = await _client.GetAsync("api/documents/GetAllDocuments"); await response.Content.LoadIntoBufferAsync(); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsAsync<Document>(new[] { new JsonMediaTypeFormatter() }); } catch (Exception ex) { return null; } }
2. 路由末尾的斜杠触发了重定向
你的WebApiConfig里第三个路由的末尾多了个斜杠:
config.Routes.MapHttpRoute( "GetAllDocuments", "api/documents/GetAllDocuments/"); // 末尾斜杠是坑!
当你请求api/documents/GetAllDocuments(不带斜杠)时,服务器会返回301重定向到带斜杠的地址,而HttpClient默认会自动跟随重定向,这就导致了两次调用接口。
解决方法很简单,移除路由末尾的斜杠,确保请求地址和路由规则完全匹配:
config.Routes.MapHttpRoute( "GetAllDocuments", "api/documents/GetAllDocuments");
3. 额外的小优化建议
- 你的ApiController返回
List<Document>,但调用方的返回类型是Task<Document>,类型不匹配可能会引发序列化异常,建议对齐两者的返回类型(要么接口返回单个Document,要么调用方返回Task<List<Document>>)。 _documentsRepository = DocumentsRepository.Instance;放在lock里没必要,单例的Instance本身应该是线程安全的,建议移到类初始化阶段完成。
按照上面的步骤修改后,应该就能彻底解决接口被重复调用的问题了。
内容的提问来源于stack exchange,提问作者Ben Sin
相关产品推荐
相关产品推荐

