c# - Wep API 无法从 HttpClient 调用返回数据
问题描述
我无法弄清楚为什么会发生以下问题:
我创建了一个简单的 Web api 控制器(.Net Framework 4.6.1)
public class TestController : ApiController
{
// GET api/<controller>
public async Task<string> Get()
{
var url = "http://api.plos.org/search?q=title:DNA";
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync(url))
{
using (var content = response.Content)
{
var result = await content.ReadAsStringAsync();
return result;
}
}
}
}
}
当我运行上面的代码时,大约 20 秒后出现以下错误。
{
"Message": "An error has occurred.",
"ExceptionMessage": "An error occurred while sending the request.",
"ExceptionType": "System.Net.Http.HttpRequestException",
"StackTrace": " at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at restapitest2.Controllers.TestController.<Get>d__0.MoveNext() in C:\\restapitest2\\restapitest2\\Controllers\\TestController.cs:line 19\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__1`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "Unable to connect to the remote server",
"ExceptionType": "System.Net.WebException",
"StackTrace": " at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)\r\n at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 216.74.38.80:80",
"ExceptionType": "System.Net.Sockets.SocketException",
"StackTrace": " at System.Net.Sockets.Socket.InternalEndConnect(IAsyncResult asyncResult)\r\n at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)\r\n at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)"
}
}
}
当我创建一个 dotnet core web api 控制器时,相同的代码可以正常工作。
这就是点网核心代码的样子。
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public async Task<ActionResult<string>> Get()
{
var url = "http://api.plos.org/search?q=title:DNA";
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync(url))
{
using (var content = response.Content)
{
var result = await content.ReadAsStringAsync();
return result;
}
}
}
}
}
奇怪的是,如果我使用内部 URL,两个 api 解决方案都会返回数据。
任何帮助,将不胜感激
解决方案
你确定你不是在代理后面吗?
你确定你的 DNS 服务器可以查到api.plos.org
吗?
更深入地检查您的异常,检查其内部异常将帮助您了解是 DNS 问题还是代理问题。
如果您使用代理,请不要忘记为 HttpClient 设置代理。
更新1:
连接尝试失败,因为连接的一方在一段时间后没有正确响应,或者连接失败,因为连接的主机没有响应 216.74.38.80:80
每次在我的机器上获得代理时,我都会遇到这个错误。既然您说“如果您运行 fiddler 一切正常”,我假设您需要从 windows 中删除代理设置Lan Settings
。
- 在
run
类型中inetcpl.cpl
并按回车。 - 转到
Connections
选项卡。 - 在对话框的底部,有一个
Lan Settings
按钮。点击它。 - 在 LAN 设置对话框中,确保您已取消选中所有复选框,尤其是
use proxy for your lan
。
题外话推荐:
HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重复使用。为每个请求实例化一个 HttpClient 类将耗尽重负载下可用的套接字数量。这将导致 SocketException 错误。下面是一个正确使用 HttpClient 的例子。
public class GoodController : ApiController
{
// OK
private static readonly HttpClient HttpClient;
static GoodController()
{
HttpClient = new HttpClient();
}
}
推荐阅读
- json - Beego httplib.get 过滤器 JSON
- wpf - 鼠标悬停时 Slider1 的背景颜色应为 DarkOrange
- excel - VBA:使用 Excel WorksheetFunction 显示最小值、最大值、平均值,不包括取消和不显示
- javascript - React-router - 如何在 React 的页面之间传递数据?
- r - Flexmix R:具有不同分量变量的混合回归
- javascript - 如何使用 JS 复制文本并粘贴到文本区域?
- c# - C# 程序关闭而不打印最终的 WriteLine 语句
- c# - 插入多个表并将主键作为外键结转
- c# - 如何在 c# icmp socket 中使用外部 IP 地址?
- java - Spring Boot Data JPA manyToMany 添加项抛出 UnsupportedOperationException