/// <summary>
        /// Executes <code>GeocodingRequest</code> against Google Maps Geocoding API web service
        /// and returns the result as <seealso cref="GeocodingResponse"/>, in asynchronous fashion.
        /// </summary>
        /// <returns></returns>
        public GeocodingResponse GetResponseAsync()
        {
            Validate();

            string url = BuildRequestUrl();
            GeocodingResponseData data = ProcessAsync(url);

            if (data.IsOverQueryLimit)
            {
                data = _context.Retry(() => ProcessAsync(url), d => !d.IsOverQueryLimit);
            }

            return(new GeocodingResponse().Parse(data));
        }
        private GeocodingResponseData GetData(WebResponse response)
        {
            GeocodingResponseData jsonData = null;
            string responseData            = null;

            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                responseData = reader.ReadToEnd();
            }

            if (responseData != null)
            {
                var serializer = new JavaScriptSerializer();
                jsonData = serializer.Deserialize <GeocodingResponseData>(responseData);
            }

            return(jsonData);
        }
        public async Task <GeocodingResponse> GetResponseAsync()
        {
            Validate();

            string url = BuildRequestUrl();
            GeocodingResponseData data = await ProcessAsync(url);

            if (data.IsOverQueryLimit)
            {
                GeocodingResponseData retryData = await _context.RetryAsync(async() => await ProcessAsync(url), d => !d.IsOverQueryLimit);

                if (retryData != null)
                {
                    data = retryData;
                }
            }

            return(new GeocodingResponse().Parse(data));
        }
        internal GeocodingResponse Parse(GeocodingResponseData data)
        {
            Status = data?.status ?? GeocodingResponseStatus.None;

            if (Status == GeocodingResponseStatus.OK)
            {
                foreach (var r in data.results)
                {
                    List <AddressComponent> addressComponents = new List <AddressComponent>(r.address_components.Length);
                    foreach (var ac in r.address_components)
                    {
                        addressComponents.Add(new AddressComponent
                        {
                            LongName  = ac.long_name,
                            ShortName = ac.short_name,
                            Types     = ac.types
                        });
                    }

                    Geometry geometry = new Geometry()
                    {
                        LocationType = r.geometry.location_type
                    };

                    if (r.geometry.bounds != null)
                    {
                        geometry.Bounds = new Bounds
                        {
                            NorthEast = new LatLng
                            {
                                Latitude  = r.geometry.bounds.northeast.lat,
                                Longitude = r.geometry.bounds.northeast.lng
                            },
                            SouthWest = new LatLng
                            {
                                Latitude  = r.geometry.bounds.southwest.lat,
                                Longitude = r.geometry.bounds.southwest.lng
                            }
                        };
                    }

                    if (r.geometry.location != null)
                    {
                        geometry.Location = new LatLng
                        {
                            Latitude  = r.geometry.location.lat,
                            Longitude = r.geometry.location.lng
                        };
                    }

                    if (r.geometry.viewport != null)
                    {
                        geometry.Viewport = new Bounds
                        {
                            NorthEast = new LatLng
                            {
                                Latitude  = r.geometry.viewport.northeast.lat,
                                Longitude = r.geometry.viewport.northeast.lng
                            },
                            SouthWest = new LatLng
                            {
                                Latitude  = r.geometry.viewport.southwest.lat,
                                Longitude = r.geometry.viewport.southwest.lng
                            }
                        };
                    }

                    Results.Add(new GeocodingResult
                    {
                        AddressComponents = addressComponents,
                        FormattedAddress  = r.formatted_address,
                        Geometry          = geometry,
                        PartialMatch      = r.partial_match,
                        Types             = r.types
                    });
                }
            }

            return(this);
        }