我无法弄清为什么发生以下问题:
我已经创建了一个简单的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核心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解决方案都会返回数据。
任何帮助将不胜感激
答案 0 :(得分:2)
您确定您没有代理吗?
您确定您的DNS服务器可以查找api.plos.org
吗?
更深入地检查您的异常,检查其内部异常将帮助您了解DNS问题还是代理问题。
如果您位于代理后面,请不要忘记为HttpClient设置代理。
更新1:
连接尝试失败,因为被连接方未 一段时间后正确响应或建立连接 失败,因为连接的主机未能响应216.74.38.80:80
每次在计算机上获得代理时,我都会遇到此错误。由于您说过“如果您运行提琴手,一切都会正常”,我假设您需要从Windows Lan Settings
删除代理设置。
run
中,键入inetcpl.cpl
,然后按Enter。Connections
标签。Lan Settings
按钮。点击它。use proxy for your lan
。离题推荐:
HttpClient旨在实例化一次并在整个过程中重复使用 应用程序的生命周期。为实例化HttpClient类 每个请求都会耗尽大量的可用插槽 负载。这将导致SocketException错误。下面是一个例子 正确使用HttpClient。
public class GoodController : ApiController
{
// OK
private static readonly HttpClient HttpClient;
static GoodController()
{
HttpClient = new HttpClient();
}
}
答案 1 :(得分:0)
正如其他人指出的那样,该代码有效,可能是HTTPS问题或代理,我将代码重写为以下内容,以在URL中包含HTTPS
[HttpGet]
public async Task<ActionResult<string>> Get()
{
var url = "https://api.plos.org/search?q=title:DNA";
var request = new HttpRequestMessage(HttpMethod.Get, url);
var httpClient = new HttpClient();
using (var response = await httpClient.SendAsync(request))
{
var content = response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
return Ok(content);
}
}
但是我会使用IHttpClientFactory,因为它可以解决套接字而不是HttpClient的问题。
要使用IHttpClientFactory,请执行以下操作
将服务添加到ConfigureServices.cs
services.AddHttpClient();
然后将调用注入到构造函数中
private readonly IHttpClientFactory _clientFactory;
public ValuesController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
然后您的API调用如下
var url = "https://api.plos.org/search?q=title:DNA";
var request = new HttpRequestMessage(HttpMethod.Get, url);
var httpClient = _clientFactory.CreateClient();
using (var response = await httpClient.SendAsync(request))
{
var content = response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
return Ok(content);
}