sending different parameters to an API, and displaying the air quality results for a given city

Aaron soggi 246 Reputation points
2022-05-10T13:45:52.68+00:00

Hello im working on a task at the moment, and so far ive been able to retrieve the cities from the following API:

https://docs.openaq.org/v2/cities

What i would like to do is send parameters to the API - https://docs.openaq.org and display the air quality results for a given city. I am quite new to retrieving data from an external API so i am a bit unsure on how i would be able to do this.

Could someone please give me some advice?

Heres the function i currently have for retrieving all City data from https://docs.openaq.org/v2/cities

 public async Task<IEnumerable<City>> GetAllCityData()
        {
            IEnumerable<City> city = null;
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("https://docs.openaq.org/");
                var responseTask = client.GetAsync("v2/cities");
                //responseTask.Wait();
                await responseTask;             

                var result = responseTask.Result;

                if (result.IsSuccessStatusCode)
                {
                    var readData = result.Content.ReadAsStringAsync();
                    await readData;

                    //using System.Text.Json;
                    var jsonresult = JsonConvert.DeserializeObject<RootModel>(readData.Result);
                    city = jsonresult.results;               

                }
                else
                {
                    city = Enumerable.Empty<City>();
                    ModelStateDictionary modelState = new ModelStateDictionary();
                    modelState.AddModelError(string.Empty, "Server error has occured");

                }
            }

            return city;

        }

Thankyou!

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,208 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 48,826 Reputation points
    2022-05-10T14:07:29.327+00:00

    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.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 56,931 Reputation points
    2022-05-10T15:38:58.547+00:00

    if you goto the root. they have a swagger ui that explains the api and responses

    https://docs.openaq.org

    you may want to use swagger codegen to create wrappers

    https://swagger.io/tools/swagger-codegen/

    0 comments No comments