从 ASP.net 4 Web API 2 项目通过 HttpClient 调用 REST 服务导致异常

Posted

技术标签:

【中文标题】从 ASP.net 4 Web API 2 项目通过 HttpClient 调用 REST 服务导致异常【英文标题】:Calling REST service via HttpClient from ASP.net 4 Web API 2 project results in exception 【发布时间】:2016-08-07 05:57:41 【问题描述】:

现状:我使用 WebAPI 2 模板创建了一个 ASP.net 项目(网络项目)。现在,其中一个 HTTPGET 方法尝试使用以下代码向另一个 REST API 发出请求。

[HttpGet]
public string Get()

    var uri = @"http://api.../...";

    var httpClient = new HttpClient();
    var response = httpClient.GetAsync(uri).GetAwaiter().GetResult(); // <- exception here

    response.EnsureSuccessStatusCode();

    string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    return content;

在标有注释的行中,抛出以下带有“无法连接到远程服务器”消息的HttpRequestException(内部异常)。

System.Net.Http.HttpRequestException was unhandled by user code
  HResult=-2146233088
  Message=An error occurred while sending the request.
  Source=mscorlib
  ...
  InnerException: 
       HResult=-2146233079
       Message=Unable to connect to the remote server
       Source=System
       StackTrace:
            at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
            at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
       InnerException: 
            ErrorCode=10060
            HResult=-2147467259
            Message=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 ...
            NativeErrorCode=10060
            Source=System
            StackTrace:
                 at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
                 at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
            InnerException: 

到目前为止我尝试了什么:

    我在浏览器中使用了完全相同的 URI(通过复制和粘贴),并返回了带有一些数据的 JSON。 在创建 WebAPI2 项目之前,我使用了 ASP.net 5 的 RC 候选对象。我基于 ASP.net 5 模板“Web API”创建了一个项目。我有完全相同的代码,并且运行良好。

假设: 我的假设是 ASP.net 4 Web API 2 模板中的配置有一些配置阻止了响应。我在 SO 上发现了一些类似的question,似乎某些私有网络已被禁用。

问题:在基于 ASP.net 4 Web API 2 的项目中使用 HttpClient 时,什么会阻止接收响应?

【问题讨论】:

你能试试其他的get方法比如GetStringAsync(String)吗? 完全一样的结果 【参考方案1】:

这可能是他没有允许 Public 使用,可能有一些特定的域被允许。在我看来。

您可以阅读这篇文章以获得更好的理解: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

【讨论】:

【参考方案2】:

我能够找出根本原因是什么。简短的回答是 ASP.net 5 模板使用了代理,可能是通过 Windows 组策略配置的代理,而 ASP.net 4 模板直接连接到其他 REST 服务。但是由于某些防火墙禁止这样做,所以它不起作用。

长答案:为了检查两个模板(ASP.net 4 和 5)的网络流量,我使用了 sysinternals 工具中的 Process Monitor。我将过滤器设置为 IISExpress.exe 和 dnx.exe。

对于 ASP.net 4 模板,如下所示。

只有两个条目可以看到 IISExpress 直接连接到 REST 服务。在 ASP.net 5 的情况下,有更多条目,因为它使用代理而不是直接连接。我实际上认为这是一个代理,因为它的主机名。这里需要注意的一点是,dnx.exe 不是 IISExpress.exe,而是建立连接。

为了让 IISExpress 使用 ASP.net 4 模板的代理,我在项目 web.config 中添加了以下几行。我使用了进程监视器中显示的主机名和端口。

<system.net>
  <defaultProxy>
    <proxy usesystemdefault="True"
           proxyaddress="http://proxy.<hostname>:<port>"
           bypassonlocal="True"/>
  </defaultProxy>
</system.net>

所以我的假设是在 Windows 的某个地方配置了这个代理,可能是通过组策略(?)。 Firefox、dnx.exe 和其他人正在使用此配置。但是 IISExpress 忽略了这一点,因此没有收到来自 REST API 的答复。

【讨论】:

以上是关于从 ASP.net 4 Web API 2 项目通过 HttpClient 调用 REST 服务导致异常的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Web API 从 MVC 4 控制器失败

为啥 ASP.NET web api 3 项目在 ASP.NET web api 2 执行时没有请求就无法启动?

ASP.NET MVC 4 / MVVM / Web API 的良好结构? [关闭]

Asp.Net Web API 2第三课——.NET客户端调用Web API

ASP.Net MVC 4 Web API 控制器不适用于 Unity.WebApi

前端 ASP.NET MVC4 作为一个项目,ASP.NET Web API 作为同一解决方案中的另一个项目 - 如何从前端调用 WebAPI?