/// <summary> /// Executes the query. /// </summary> /// <param name="url">The URL.</param> /// <param name="autoLoadDetails">if set to <c>true</c> [automatic load details].</param> /// <returns>Task<IList<IAddress>>.</returns> private async Task <IGeoSearchResult> ExecuteQueryAsync(UrlBuilder url, bool autoLoadDetails = true) { var httpClient = new HttpClient(); Log.Debug("ExecuteQuery: {0}", url.Uri.ToString()); var httpGetResponse = await httpClient.GetAsync(url.Uri).ConfigureAwait(false); if (httpGetResponse == null || !httpGetResponse.IsSuccessStatusCode) { Log.Error("Failed to execute query for address search. HTTP Result: {0}", httpGetResponse?.StatusCode); return(null); } try { var httpMsgResponse = await httpGetResponse.Content.ReadAsStringAsync().ConfigureAwait(false); Log.Debug("ExecuteQuery Result: {0}", httpMsgResponse); var results = JsonConvert.DeserializeObject <GoogleGeoSearchRoot>(httpMsgResponse, new JsonSerializerSettings { ContractResolver = new ContractResolverDelegate(type => Resolver.IsRegistered(type), type => Resolver.Resolve(type)) }); if (results.Status != GoogleStatusCodeTypes.Ok) { //TODO Should we thrown an exception here? Log.Error("Failed to execute query for address search. {@results}", results); throw new GoogleGeoProviderException(results.Status, httpMsgResponse, "Failed to execute query for address"); } if (!autoLoadDetails) { var result = new GeoSearchResult { Items = results.Items.Where(x => x.Types.Contains(GoogleAddressTypes.StreetAddress)) .Select(x => x.ToAddress()) .ToList(), Session = results.NextPageToken }; return(result); } var tmpList = results.Items.Where(x => !x.Types.Intersect( new[] { //GoogleAddressTypes.StreetAddress, GoogleAddressTypes.Route, GoogleAddressTypes.Intersection, GoogleAddressTypes.Political, GoogleAddressTypes.Country, GoogleAddressTypes.AdministrativeAreaLevel1, GoogleAddressTypes.AdministrativeAreaLevel2, GoogleAddressTypes.AdministrativeAreaLevel3, GoogleAddressTypes.AdministrativeAreaLevel4, GoogleAddressTypes.AdministrativeAreaLevel5, //GoogleAddressTypes.Establishment, GoogleAddressTypes.ColloquialArea, GoogleAddressTypes.Locality, GoogleAddressTypes.Ward, GoogleAddressTypes.Sublocality, GoogleAddressTypes.Neighborhood, GoogleAddressTypes.PostalCode, GoogleAddressTypes.NaturalFeature, GoogleAddressTypes.PostalTown, GoogleAddressTypes.Geocode, GoogleAddressTypes.PostalCodePrefix, GoogleAddressTypes.PostalCodeSuffix, GoogleAddressTypes.SublocalityLevel5, GoogleAddressTypes.SublocalityLevel4, GoogleAddressTypes.SublocalityLevel3, GoogleAddressTypes.SublocalityLevel2, GoogleAddressTypes.SublocalityLevel1, GoogleAddressTypes.Accounting, GoogleAddressTypes.Atm }).Any()); var taskList = tmpList.Select(result => GetAddressByIdAsync(result.PlaceID).ContinueWith(ctxAddress => { return(ctxAddress.Result); })).ToList(); var taskResult = Task.WhenAll(taskList).ContinueWith(ctxTaskList => { var result = new GeoSearchResult { Items = ctxTaskList.Result.Where(x => x != null).ToList(), Session = results.NextPageToken }; return((IGeoSearchResult)result); }); var detailsResults = await taskResult.ConfigureAwait(false); return(detailsResults); } catch (Newtonsoft.Json.JsonSerializationException ex) { Log.Error(ex, "Failed to desearlize json from google"); } return(null); }
/// <summary> /// Searches the specified request. /// </summary> /// <param name="request">The request.</param> /// <returns>Task<IList<IAddress>>.</returns> public async Task <IGeoSearchResult> SearchAsync(IGeoSearchRequest request) { Log.Debug("Search Request: {@request}", request); IGeoSearchResult searchResult = null; if (request.Address != null) { if (!string.IsNullOrEmpty(request.Address.Source?.ObjectID)) { var address = await _wrapper.GetAddressByIdAsync(request.Address.Source.ObjectID).ConfigureAwait(false); if (address != null) { searchResult = new GeoSearchResult(); searchResult.Items.Add(address); return(searchResult); } } // Do we have a Lat/Long? If so, lets use that if (request.Address.Location?.Latitude != null) { Log.Debug("Executing FindLocation"); searchResult = await _wrapper.FindLocationAsync(request.Address.Location).ConfigureAwait(false); if (searchResult != null) { return(searchResult); } } // Do we have enough of an address to try to use that -- this includs a full line 1 or a postcode that includes the "extra" details in the US? if (!string.IsNullOrEmpty(request.Address.Line1) || (!string.IsNullOrEmpty(request.Address.PostalCode) && request.Address.PostalCode.Length > 7)) { Log.Debug("Executing FindAddress"); if (searchResult == null || searchResult.Items.All(x => x == null)) { searchResult = await _wrapper.FindAddressAsync(request.Address).ConfigureAwait(false); return(searchResult); } } } // If all else fails, lets try a general search with as much as possible var searchRequest = new GooglePlacesSearchRequest() { Keyword = string.Format("{0} {1}", request.Name, request.Address != null ? string.Format("{0} {1} {2} {3}", request.Address.City, request.Address.Region, request.Address.Country, request.Address.PostalCode) : null).Trim(), Lattitude = request.Address != null && request.Address.Location != null && request.Address.Location.Latitude.HasValue ? request.Address.Location.Latitude : null, Longitude = request.Address != null && request.Address.Location != null && request.Address.Location.Longitude.HasValue ? request.Address.Location.Longitude : null, Types = request.AddressTypes.Select(x => (GoogleAddressTypes)Enum.Parse(typeof(GoogleAddressTypes), x.ToString())).ToList(), Distance = request.Distance }; if (!string.IsNullOrEmpty(searchRequest.Keyword)) { Log.Debug("Executing General Search: {@searchRequest}", searchRequest); searchResult = await _wrapper.SearchAsync(searchRequest).ConfigureAwait(false); } return(searchResult); }