尚无此类主机。(使用HttpClient从webapi控制器调用weatherAPI)

时间:2019-01-22 21:12:28

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

我正在尝试从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:内部服务器错误

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

Startup.cs

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

当我尝试将完整的openweather URL放入浏览器时,它返回json,但是当尝试从ASP.NET CORE Web Api Controller运行时却给出了错误。

任何帮助将不胜感激。

预先感谢

2 个答案:

答案 0 :(得分:2)

可接受的答案是错误且危险的-切勿将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用作公共静态变量或将其包装在Singleton中。在ASP.NET Core应用程序中,使用the built-in factory创建HttpClient实例。

答案 1 :(得分:1)

您应该使用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}");
            }
}