protected virtual async Task<GeocodingResult> DoGeocodingQuery(string addressToGeocode)
{
string message;
var result = new GeocodingResult();
var geocoder = new GoogleGeocoder();
List<GoogleAddress> addresses = new List<GoogleAddress>();
while (true)
{
try
{
//Wait if needed to avoid making geocoding calls faster than we should
await GeocodingRateLimiter.WaitNextAsync();
//Geocode the address and break out of the loop if successful.
Log.Debug($"Geocoding '{addressToGeocode}'");
addresses.AddRange(await geocoder.GeocodeAsync(addressToGeocode));
break;
}
catch (GoogleGeocodingException ex) when (ex.Status == GoogleStatus.OverQueryLimit)
{
//If we're making queries too quickly, slow down.
Log.Debug($"OverQueryLimit @ '{addressToGeocode}'");
GeocodingRateLimiter.IncreaseDelay();
}
}
if (addresses.Count <= 0)
{
message = $"Warning: No results found for address: {addressToGeocode}.";
}
else if (addresses.Count > 1)
{
StringBuilder multiples = new StringBuilder();
for (int i = 0; i < addresses.Count; i++)
{
multiples.Append($"\n[Result {i + 1} ====> {addresses[i].FormattedAddress}]");
}
message = $"Warning: Multiple addresses found for {addressToGeocode}: {multiples}";
}
else if (addresses[0].IsPartialMatch)
{
message = $"Warning: Partial match for address: {addressToGeocode} => [{addresses[0].FormattedAddress}].";
}
else
{
result.Location = addresses[0].Coordinates;
return result;
}
//If we get down here, there was some kind of problem. Store the details and log the warning before returning.
result.StateInfo = new LookupStateInfo<GoogleAddress> { Message = message, PossibleResults = addresses };
Log.Warn(message);
return result;
}