I cannot answer about the air quality as the API doesn't seem to mention anything about that. But for the API itself you just need to append to the URL ?city=someplace
and it should limit the results. I assume it might potentially return back multiple results if you use a city name that is common so your existing code would work I believe.
public async Task<IEnumerable<City>> GetCityData( string city )
{
var client = new HttpClient();
client.BaseAddress = new Uri("https://docs.openaq.org/");
var results = await client.GetFromJsonAsync<RootModel>($"v2/cities?city={city}").ConfigureAwait(false);
return results.results;
}
//In your controller
public Task<ActionResult<City>> GetCity ( string name )
{
try
{
var city = GetCityData(name);
return city;
} catch (Exception e)
{
e.AddModelError("", e.Message);
return ??;
};
}
Using the helper method GetFromJsonAsync here. You shouldn't be parsing JSON manually. It is unclear what your model actually is but let the parser do the conversion. If anything goes wrong it'll throw an exception.
You should not be wrapping HttpClient
in a using statement. See here. The correct approach is to wrap the API calls in a standalone class that accepts the HttpClient
as a parameter to the constructor. The wrapper class should be created by your dependency injection container that ASP.NET Core already provides. Use AddHttpClient to configure this. Also that would get rid of the baseAddress setting you are doing, that is a configuration thing.
You shouldn't be creating and working with ModelState
outside a controller. Therefore the controller action should be responsible for adding exceptions to model state if you're not using global error handling already.
Finally note the preference for APIs is to use a code generator to generate the code for you. The Connected Services option in your project can do this or you could use a third party tool like Swagger, NSwag or equivalent. Calling APIs is boilerplate code so let the tools auto-generate the logic for you.