ASP.NET调用天气API报错:非静态成员需要对象引用
错误产生原因
你遇到的报错由3个代码逻辑问题共同导致:
- 模型定义逻辑错误:你将
Current、Location等实体类全部嵌套在WeatherApi类内部,但WeatherApi本身没有定义任何Current类型的实例属性。当你在视图中通过@model WeatherApi声明模型后,写Model.Current时编译器会认为你在访问嵌套类Current的类型本身(静态引用),而非实例对象的属性,直接访问类型上的实例属性Temperature就会触发“非静态字段、方法或属性需要对象引用”的错误。 - 控制器反序列化类型不匹配:你在控制器中反序列化JSON时使用了未定义的
WeatherApiResponse类型,和你自己写的模型结构完全不对应,最终传给视图的对象类型和视图声明的模型类型不一致。 - 附加隐患:你在async标记的Action中调用
GetAsync时使用了.Result做同步阻塞,容易引发线程池死锁,虽然不是本次报错的直接原因,但需要修正。
可行修复方案
按以下步骤逐段修正代码即可:
1. 重构模型层代码
去掉无意义的嵌套类结构,平级定义所有API返回对应的实体类,统一根返回类的命名和控制器里的调用对应:
using Newtonsoft.Json; namespace Exercice.Models { public class Current { [JsonProperty("observation_time")] public string ObservationTime { get; set; } [JsonProperty("temperature")] public int Temperature { get; set; } [JsonProperty("weather_code")] public int WeatherCode { get; set; } [JsonProperty("weather_icons")] public List<string> WeatherIcons { get; set; } [JsonProperty("weather_descriptions")] public List<string> WeatherDescriptions { get; set; } [JsonProperty("wind_speed")] public int WindSpeed { get; set; } [JsonProperty("wind_degree")] public int WindDegree { get; set; } [JsonProperty("wind_dir")] public string WindDir { get; set; } [JsonProperty("pressure")] public int Pressure { get; set; } [JsonProperty("precip")] public int Precip { get; set; } [JsonProperty("humidity")] public int Humidity { get; set; } [JsonProperty("cloudcover")] public int Cloudcover { get; set; } [JsonProperty("feelslike")] public int Feelslike { get; set; } [JsonProperty("uv_index")] public int UvIndex { get; set; } [JsonProperty("visibility")] public int Visibility { get; set; } [JsonProperty("is_day")] public string IsDay { get; set; } } public class Location { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("country")] public string Country { get; set; } [JsonProperty("region")] public string Region { get; set; } [JsonProperty("lat")] public string Lat { get; set; } [JsonProperty("lon")] public string Lon { get; set; } [JsonProperty("timezone_id")] public string TimezoneId { get; set; } [JsonProperty("localtime")] public string Localtime { get; set; } [JsonProperty("localtime_epoch")] public int LocaltimeEpoch { get; set; } [JsonProperty("utc_offset")] public string UtcOffset { get; set; } } public class Request { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("query")] public string Query { get; set; } [JsonProperty("language")] public string Language { get; set; } [JsonProperty("unit")] public string Unit { get; set; } } // 统一根返回类名,和控制器调用对应 public class WeatherApiResponse { [JsonProperty("request")] public Request Request { get; set; } [JsonProperty("location")] public Location Location { get; set; } [JsonProperty("current")] public Current Current { get; set; } } }
2. 修正控制器代码
替换不存在的反序列化类型,去掉同步阻塞的.Result写法,补充请求成功校验:
public async Task<IActionResult> Weather() { string baseAddress = "http://api.weatherstack.com/"; // 生产环境建议将HttpClient注册为单例复用,避免端口耗尽问题 HttpClient client = new HttpClient(); client.BaseAddress = new Uri(baseAddress); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); string path = "current?access_key=<MYACCESSKEY>&query=Madrid"; // 用await异步等待请求,不要用.Result阻塞 HttpResponseMessage response = await client.GetAsync(path); response.EnsureSuccessStatusCode(); string myJsonResponse = await response.Content.ReadAsStringAsync(); // 反序列化类型修正为实际定义的WeatherApiResponse WeatherApiResponse apiResponse = JsonConvert.DeserializeObject<WeatherApiResponse>(myJsonResponse); return View(apiResponse); }
3. 修正视图层模型声明
将视图的模型类型替换为控制器实际传入的WeatherApiResponse:
@model Exercice.Models.WeatherApiResponse <p>Temperature @Model.Current.Temperature°</p>
改完之后重新编译运行即可正常获取并展示温度数据。
内容的提问来源于stack exchange,提问作者qwerty
相关产品推荐
相关产品推荐

