diff --git a/CityFinder/CityFinder.csproj b/CityFinder/CityFinder.csproj index 29f5640..15bdb79 100644 --- a/CityFinder/CityFinder.csproj +++ b/CityFinder/CityFinder.csproj @@ -22,6 +22,7 @@ + diff --git a/CityFinder/Models/GeocodeApiErrorResponse.cs b/CityFinder/Models/GeocodeApiErrorResponse.cs new file mode 100644 index 0000000..d2913db --- /dev/null +++ b/CityFinder/Models/GeocodeApiErrorResponse.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +using System.Globalization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace CityFinder.Models +{ + public partial class GeocodeApiErrorResponse + { + [JsonProperty("error_message")] + public string ErrorMessage { get; set; } + + [JsonProperty("results")] + public List Results { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + } + + public partial class GeocodeApiErrorResponse + { + public static GeocodeApiErrorResponse FromJson(string json) => JsonConvert.DeserializeObject(json, JsonConverter.Settings); + } +} diff --git a/CityFinder/Models/GeocodeApiResponse.cs b/CityFinder/Models/GeocodeApiResponse.cs new file mode 100644 index 0000000..a86ff4b --- /dev/null +++ b/CityFinder/Models/GeocodeApiResponse.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; + +using System.Globalization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace CityFinder.Models +{ + public partial class GeocodeApiResponse + { + [JsonProperty("results")] + public List Results { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + } + + public partial class Result + { + [JsonProperty("address_components")] + public List AddressComponents { get; set; } + + [JsonProperty("formatted_address")] + public string FormattedAddress { get; set; } + + [JsonProperty("place_id")] + public string PlaceId { get; set; } + + [JsonProperty("types")] + public List Types { get; set; } + } + + public partial class AddressComponent + { + [JsonProperty("long_name")] + public string LongName { get; set; } + + [JsonProperty("short_name")] + public string ShortName { get; set; } + + [JsonProperty("types")] + public List Types { get; set; } + } + + public partial class GeocodeApiResponse + { + public static GeocodeApiResponse FromJson(string json) => JsonConvert.DeserializeObject(json, JsonConverter.Settings); + } +} diff --git a/CityFinder/Models/JsonConverter.cs b/CityFinder/Models/JsonConverter.cs new file mode 100644 index 0000000..8f4ff2a --- /dev/null +++ b/CityFinder/Models/JsonConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +using System.Globalization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace CityFinder.Models +{ + internal static class JsonConverter + { + public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + { + MetadataPropertyHandling = MetadataPropertyHandling.Ignore, + DateParseHandling = DateParseHandling.None, + Converters = + { + new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } + }, + }; + } +} diff --git a/CityFinder/Program.cs b/CityFinder/Program.cs index 84227a1..329ff17 100644 --- a/CityFinder/Program.cs +++ b/CityFinder/Program.cs @@ -46,6 +46,9 @@ namespace CityFinder Console.WriteLine("Enter a zip/postal code:"); string postalCodeInput = Console.ReadLine(); + + // Get the city using an API call + await GetCity(countryInput, postalCodeInput); /// /// This method sets up the json config file and sets the user-agent header on the HttpClient. /// @@ -99,6 +102,43 @@ namespace CityFinder return countryInput; } + /// + /// This method queries the Google Geocode API to get a city name from a country and postal code. + /// + /// The country code to search for. + /// The postal code to search for. + /// Returns nothing, but it needs awaiting as it's calling an external API. + private static async Task GetCity(string countryCode, string postalCode) + { + string apiKey = config["GoogleMapsGeocodeApiKey"]; + string requestUri = $"https://maps.googleapis.com/maps/api/geocode/json?key={apiKey}&address={postalCode}®ion={countryCode}"; + string responseBody = string.Empty; + + try + { + HttpResponseMessage response = await client.GetAsync(requestUri); + responseBody = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); + + GeocodeApiResponse geocodeApiResponse = GeocodeApiResponse.FromJson(responseBody); + string cityName = geocodeApiResponse.Results.FirstOrDefault().AddressComponents.FirstOrDefault(a => a.Types.Contains("postal_town")).LongName; + + Console.WriteLine($"The city is called {cityName}"); + } + catch (HttpRequestException ex) + { + GeocodeApiErrorResponse geocodeApiErrorResponse = GeocodeApiErrorResponse.FromJson(responseBody); + + Console.WriteLine($"Exception caught - Message :{ex.Message}"); + Console.WriteLine($"Google API request failed with status {geocodeApiErrorResponse.Status}"); + Console.WriteLine(geocodeApiErrorResponse.ErrorMessage); + } + catch (Exception ex) + { + Console.WriteLine($"Exception caught - Message :{ex.Message}"); + } + } + /// /// This method displays a table of valid country codes. ///