Wep API无法从HttpClient调用返回数据

时间:2019-05-28 06:05:44

标签: c# .net asp.net-web-api

我无法弄清为什么发生以下问题:

我已经创建了一个简单的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解决方案都会返回数据。

任何帮助将不胜感激

2 个答案:

答案 0 :(得分:2)

您确定您没有代理吗?

您确定您的DNS服务器可以查找api.plos.org吗?

更深入地检查您的异常,检查其内部异常将帮助您了解DNS问题还是代理问题。

如果您位于代理后面,请不要忘记为HttpClient设置代理。

更新1:

  

连接尝试失败,因为被连接方未   一段时间后正确响应或建立连接   失败,因为连接的主机未能响应216.74.38.80:80

每次在计算机上获得代理时,我都会遇到此错误。由于您说过“如果您运行提琴手,一切都会正常”,我假设您需要从Windows Lan Settings删除代理设置。

  1. run中,键入inetcpl.cpl,然后按Enter。
  2. 转到Connections标签。
  3. 对话框的底部有Lan Settings按钮。点击它。
  4. 在“ 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();
    }
}

答案 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);
        }