我正在尝试从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运行时却给出了错误。
任何帮助将不胜感激。
预先感谢
答案 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}");
}
}