【问题标题】:No such host is known.(calling weatherAPI from webapi controller using HttpClient)不知道这样的主机。(使用 HttpClient 从 Web api 控制器调用天气 API)
【发布时间】:2019-01-22 21:12:27
【问题描述】:

我正在尝试从 asp.net WebAPI 调用 openWeatherApi。当我从前端收到一个城市的名称时,我用它从数据库中查找城市/机场。然后,我使用机场的经纬度来调用 openweather API。我想使用响应进行进一步的计算和预测。

我的代码是:

HttpClient client = new HttpClient();

try
                {
                    client.BaseAddress = new Uri("http://api.openweather.org");
                     var response = await client.GetAsync($"/data/2.5/weather?lat={airport.AirportLatitude}&lon={airport.AirportLongitude}&appid={apiKey}");
                  //  var response = await // client.GetAsync($"/data/2.5/weather?q=London,uk&appid={apiKey}");
                    response.EnsureSuccessStatusCode();

                    var stringResult = await response.Content.ReadAsStringAsync();
                    var rawWeather = JsonConvert.DeserializeObject<OpenWeatherResponse>(stringResult);
                    System.Console.WriteLine("$$$$$$$$$$$After API call made$$$$$$$$$$$$$$$");
                    System.Console.WriteLine(response);
                    return Ok(new {
                        Temp = rawWeather.Main.Temp,
                        Summary = string.Join(",", rawWeather.Weather.Select(x=>x.Main)),
                        City = rawWeather.Name
                    });
                    // return Ok(response);
                }

                catch(HttpRequestException httpRequestException)
                {   
                    System.Console.WriteLine(httpRequestException.Message); 
                    return BadRequest($"Error getting weather : {httpRequestException.Message}");
                }

运行此应用时,有时会收到 400BadRequest,有时会收到 500:Internal Server Error

1) 没有这样的主机是已知的。 2) System.InvalidOperationException:该实例已经启动了一个或多个请求。只能在发送第一个请求之前修改属性。

Startup.cs

services.AddTransient<HttpClient>(); 
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

当我尝试将完整的 openweather url 放入浏览器时,它会返回 json,但在尝试从 ASP.NET CORE Web Api 控制器运行时会出错。

任何帮助将不胜感激。

提前致谢

【问题讨论】:

    标签: asp.net-mvc asp.net-core asp.net-core-webapi dotnet-httpclient


    【解决方案1】:

    公认的答案是错误且危险的 - 您永远不应将 HttpClient 包装在 using 块中,因为它可能会在大量使用时导致端口耗尽。

    有关这方面的更多详细信息,您可以查看此 Microsoft 认可的博客文章:You're using HttpClient wrong and it is destabilizing your software

    另外,来自this article from Microsoft

    很有可能,每次您需要访问 Web 服务时,您一直在创建一个 HttpClient 对象,然后将其丢弃。 不幸的是,这对您的应用程序不利,因为您可能会用完 WebSockets(是的,即使您在丢弃对象之前调用了该对象的 Dispose 方法)。虽然,我不得不承认,您只会拥有这个如果您经常使用 HttpClient,则会出现问题。尽管如此,继续创建和销毁它是一个坏主意。

    在 .NET Framework 中,目的是让您在应用程序中创建一次 HttpClient 并反复使用它。为此,您必须将 HttpClient 对象声明为全局或静态变量。当然,这也会产生问题。

    但是,在 ASP.NET Core 中,您有一个更好的选择:HttpClientFactory。 HttpClientFactory 为您提供 HttpClient 对象,但负责管理客户端可以使用的资源。将其视为“Web 服务的连接池”。

    因此,在桌面应用程序中,将HttpClient 用作公共静态变量或将其包装在单例中。在 ASP.NET Core 应用程序中,使用 the built-in factory 创建您的 HttpClient 实例。

    【讨论】:

      【解决方案2】:

      您应该使用using 语句

      using (var client = new HttpClient())
      {
                try
                  {
                      client.BaseAddress = new Uri("http://api.openweather.org");
                       var response = await client.GetAsync($"/data/2.5/weather?lat={airport.AirportLatitude}&lon={airport.AirportLongitude}&appid={apiKey}");
                    //  var response = await // client.GetAsync($"/data/2.5/weather?q=London,uk&appid={apiKey}");
                      response.EnsureSuccessStatusCode();
      
                      var stringResult = await response.Content.ReadAsStringAsync();
                      var rawWeather = JsonConvert.DeserializeObject<OpenWeatherResponse>(stringResult);
                      System.Console.WriteLine("$$$$$$$$$$$After API call made$$$$$$$$$$$$$$$");
                      System.Console.WriteLine(response);
                      return Ok(new {
                          Temp = rawWeather.Main.Temp,
                          Summary = string.Join(",", rawWeather.Weather.Select(x=>x.Main)),
                          City = rawWeather.Name
                      });
                      // return Ok(response);
                  }
      
                  catch(HttpRequestException httpRequestException)
                  {   
                      System.Console.WriteLine(httpRequestException.Message); 
                      return BadRequest($"Error getting weather : {httpRequestException.Message}");
                  }
      }
      

      【讨论】:

      • 在编写上述代码之前我已经尝试过了。
      • 这是错误的 - 你应该永远HttpClient 包裹在 using 块中 - 这可能会导致端口耗尽。在 ASP.NET Core 中,他们为此提供了一个工厂;在桌面应用程序中,您应该在 Singleton 中使用相同的实例。
      • 在 ASP.NET Core 中管理HttpClient 的正确机制可以在here 中找到——这里显示的方式非常错误,尤其是对于流量很大的 API。
      猜你喜欢
      • 1970-01-01
      • 2021-11-17
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多