// Gets locator metadata for the currently specified locator service URL
        private void doUpdateLocatorInfo(object parameter)
        {
            // Cancel search if one is in-progress
            if (IsSearching)
                doCancel(null);

            if (!(canUpdateLocatorInfo(parameter)))
                throw new Exception(Strings.CommandNotExecutable);

            LocatorInfo = null; // Reset locator info
            IsUpdatingLocatorInfo = true; // Update execution state
            _results.Clear(); // Clear results from previous searches
            _queuedResults.Clear();

            // Get proxy
            string proxyUrl = UseProxy ? ProxyUrl : null;

            // Make request for service metadata
            ArcGISService.GetServiceInfoAsync(LocatorServiceUrl, null, (o, e) =>
            {
                if (e.Service != null && e.Service is LocatorService)
                {
                    LocatorInfo = (LocatorService)e.Service;

                    // Initialize locator task
                    if (_locator == null)
                    {
                        _locator = new Locator();
                        _locator.AddressToLocationsCompleted += AddressToLocationsCompleted;
                        _locator.Failed += Locator_Failed;
                    }
                    _locator.Url = LocatorInfo.Url;
                    _locator.ProxyURL = UseProxy ? ProxyUrl : null;

                    // Try to auto-select fields to use for the extent of results
                    autoSelectExtentFields();

                    UseExtentFields = ExtentFields.XMinField != null && ExtentFields.YMinField != null
                        && ExtentFields.XMaxField != null && ExtentFields.YMaxField != null;
                }

                IsUpdatingLocatorInfo = false; // Update execution state
            }, proxyUrl);
        }
        /// <summary>
        /// Gets the service information for an ArcGIS Server service.
        /// </summary>
        /// <param name="url">The URL of the service</param>
        /// <param name="userState">Object to be passed to the callback</param>
        /// <param name="callback">The method to invoke when information retrieval has completed</param>
        /// <param name="proxyUrl">The URL of a proxy server to use when making the request</param>
        public static void GetServiceInfoAsync(string url, object userState, EventHandler <ServiceEventArgs> callback, string proxyUrl = null)
        {
            string jsonUrl = url.Contains("?") ? url + "&f=json" : url + "?f=json";

            WebUtil.OpenReadAsync(new Uri(jsonUrl), url, (sender, e) =>
            {
                if (e.Error != null)
                {
                    callback(null, new ServiceEventArgs());
                    return;
                }
                string requestUrl = (string)e.UserState;

                MapService mapService = WebUtil.ReadObject <MapService>(e.Result);
                if (mapService != null && mapService.Name != null && mapService.Units != null)
                {
                    mapService.Url           = requestUrl;
                    mapService.RequiresProxy = e.UsedProxy;
                    mapService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = mapService, UserState = userState
                    });
                    return;
                }

                FeatureService featureService = WebUtil.ReadObject <FeatureService>(e.Result);
                if (featureService != null && featureService.Layers != null && featureService.Layers.Length > 0)
                {
                    featureService.Url           = requestUrl;
                    featureService.RequiresProxy = e.UsedProxy;
                    featureService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = featureService, UserState = userState
                    });
                    return;
                }

                ImageService imageService = WebUtil.ReadObject <ImageService>(e.Result);
                if (imageService != null && imageService.PixelType != null)
                {
                    imageService.Url           = requestUrl;
                    imageService.RequiresProxy = e.UsedProxy;
                    imageService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = imageService, UserState = userState
                    });
                    return;
                }

                FeatureLayerService featureLayerService = WebUtil.ReadObject <FeatureLayerService>(e.Result);
                if (featureLayerService != null && featureLayerService.Type == "Feature Layer")
                {
                    featureLayerService.Url           = requestUrl;
                    featureLayerService.RequiresProxy = e.UsedProxy;
                    featureLayerService.Title         = featureLayerService.Name;
                    callback(null, new ServiceEventArgs()
                    {
                        Service = featureLayerService, UserState = userState
                    });
                    return;
                }

                LocatorService locatorService = WebUtil.ReadObject <LocatorService>(e.Result);
                if (locatorService != null && locatorService.CandidateFields != null &&
                    (locatorService.AddressFields != null || locatorService.SingleLineAddressField != null))
                {
                    locatorService.Url           = requestUrl;
                    locatorService.RequiresProxy = e.UsedProxy;
                    locatorService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = locatorService, UserState = userState
                    });
                    return;
                }

                callback(null, new ServiceEventArgs());
            }, proxyUrl);
        }