Add geocoding to your app

The process of transforming an address or place name to a geographical location on a map is known as geocoding. The opposite task, searching for the nearest address to a particular point on a map using geographic coordinates, is referred to as reverse geocoding. This tutorial describes how to perform geocoding and reverse geocoding using a LocatorTask.

The ArcGIS Runtime SDK for .NET provides two LocatorTask classes. The OnlineLocatorTask relies on ArcGIS for Server geocode services to perform these functions, while the LocalLocatorTask can use a locally available locator (*.loc file).

This tutorial introduces you to the OnlineLocatorTask, which you can use to work with address information in your app. Your completed app will allow users to search for an address, zoom to a match, and display a result on the map. It will also provide reverse geocoding functionality, allowing users to get an interpolated address for a point on the map.


This tutorial requires a supported version of Microsoft Visual Studio and ArcGIS Runtime SDK for .NET. See Install the SDK and System requirements for more information.

Familiarity with Visual Studio and a basic understanding of XAML and C# or Visual Basic .NET (VB .NET) is recommended.

Create a WPF app

You'll use Visual Studio to create a WPF app.

  1. Open a supported version of Microsoft Visual Studio.
  2. Choose File > New > Project (or click New Project on the Start page) to create a project.
  3. Click Windows Desktop > WPF Application in the New Project dialog box (you can create your project in either C# or VB .NET).

    Visual Studio 2015 organizes project types slightly differently. You'll find WPF Application projects under Windows > Classic Desktop


    ArcGIS Runtime SDK for .NET provides a project template for creating your mapping app, called ArcGIS Runtime 10.2.7 for .NET App. Creating your project from the template will add the appropriate references and a page with a map view containing a single base layer. In this tutorial, you'll build your app from a blank template.

  4. Choose a folder location for your new project and name it Geocoding.

    Visual Studio New Project dialog box

  5. Click OK to create the project.

    Your project opens in Visual Studio and contains a single WPF window called MainWindow.xaml.

  6. Next, you'll add a reference to the ArcGIS Runtime SDK for .NET API assembly.
  7. Right-click the References node under the Geocoding project listing in the Visual Studio Solution Explorer window, and click Add Reference in the context menu.
  8. Check the listing for the Esri.ArcGISRuntime assembly under Assemblies > Extensions.

    Visual Studio Reference Manager dialog box

  9. Click OK to add the reference to ArcGIS Runtime for .NET.

    Visual Studio project references

  10. The Esri.ArcGISRuntime library contains the Map control and all core API components and classes you'll need.

Create a map with a streets basemap layer

Now that you've created a simple project and referenced ArcGIS Runtime SDK, you're ready to add a map to your app. You'll create a map to display the ArcGIS Online world street maps basemap layer to provide context for your address results. After implementing the geocoding functionality, your results will be displayed as graphics on top of this layer.

    To use the ESRI.ArcGISRuntime library in the XAML designer, you must first make the required reference to its XML namespace.
  1. Open the MainWindow.xaml file in the Visual Studio designer.
  2. Go to the XAML view of the designer, and add the following XML namespace reference to the Window XAML element. Visual Studio offers IntelliSense to help complete the URL portion of the statement.
  3. Next, you'll add a MapView control to the window and define a layer to display.
  4. Add the following XAML inside the <Grid> element to define a new MapView control on the page. The map will contain the World Streets Map basemap layer from ArcGIS Online and an empty graphics layer for displaying geocode results.
    <esri:MapView x:Name="MyMapView">
      <esri:Map x:Name="MyMap">
        <esri:ArcGISTiledMapServiceLayer ID="Streets" 
        <esri:GraphicsLayer ID="GeocodeResults"/>            

    In the previous XAML, a value is provided for each layer's ID property. This simplifies referring to the layer programmatically. For the MapView and Map controls, the x:Name property serves the same purpose.


    In addition to the World imagery map, ArcGIS Online provides basemaps of streets, topographic data, historical maps, and many others. Visit Living Atlas of the World to browse some of the available basemaps. If you find a basemap you'd like to use in your app, you can copy the service URI from its description page.

Create a UI for finding an address

You'll add some simple controls to allow users to enter an address to locate on the map.

  1. Add the following XAML to define a simple UI for address input. It's important to add this XAML below the code for your MapView element to ensure the address controls display on top of the map.

    <StackPanel Orientation="Vertical" 
               HorizontalAlignment="Left" VerticalAlignment="Top" >
       <StackPanel Orientation="Horizontal">
          <TextBox x:Name="AddressTextBox" Text="1145 17th St NW, Washington, DC 20036" Margin="10,0"/>
          <Button x:Name="FindAddressButton" Content="Find"/>                

  2. Add the following XAML to the Button element to define a handler for its Click event. When prompted by Visual Studio IntelliSense, press the Tab key to create the new event handler, which will be called FindAddressButton_Click as shown in the following code example:

    <Button x:Name="FindAddressButton" Content="Find" Click="FindAddressButton_Click"/>

  3. Right-click the text FindAddressButton_Click in the designer and choose Go To Definition from the context menu that appears.

    Visual Studio context menu > Go To Definition

    The code view opens for your page, to the new FindAddressButton_Click handler.

Add code to find an address

In the following steps, you'll add code to find matches for an address string provided by the user.

  1. At the top of the MainWindow.xaml.cs file, add the following using statements to bring in required geocoding and geometry functionality.

    using Esri.ArcGISRuntime.Tasks.Geocoding;
    using Esri.ArcGISRuntime.Geometry;

  2. Return to the FindAddressButton_Click event handler and add the following code to create an OnlineLocatorTask object. The constructor takes two arguments: the URI for the geocode service and a token (required for secured services).

    var uri = new Uri("");
    var token = String.Empty;
    var locator = new OnlineLocatorTask(uri, token);

  3. Finding an address using the OnlineLocatorTask requires an OnlineLocatorFindParameters object, which holds all relevant information for the address search.
  4. Add the following code to define the find parameter:

    var findParams = new OnlineLocatorFindParameters(AddressTextBox.Text);
    findParams.OutSpatialReference = MyMapView.SpatialReference;
    findParams.SourceCountry = "US";

    The Text property defines the address to locate. By setting the OutSpatialReference property to that of the MapView, you'll get results that can be used in the map without having to reproject. SourceCountry is an optional property that can be set to restrict address searches to a specific country (which can improve performance). This value can be set using the ISO country code, a list of which can be found at

  5. Call the FindAsync method on the locator by adding the following code:

    var results = await locator.FindAsync(findParams, new System.Threading.CancellationToken());

    The FindAsync method takes two arguments: OnlineLocatorFindParameters and System.Threading.CancellationToken. The cancellation token can be used to allow the user to cancel long-running tasks. By passing in a new CancellationToken, you have essentially ignored this argument.

    Using the await keyword, your query will complete asynchronously, then resume execution with the lines that follow. The compiler treats this code as a callback for the function called with await.To use the await keyword, however, you must mark the function containing it with the async keyword.

  6. Mark the FindAddressButton_Click event handler with the async keyword, as shown in the following code example:

    private async void FindAddressButton_Click(object sender, RoutedEventArgs e)

  7. After the call to FindAsync completes, check for results. If there is at least one result (address match), you'll get the location of the first match, as shown in the following code example:

    if (results.Count > 0)
       var firstMatch = results[0].Feature;
       var matchLocation = firstMatch.Geometry as MapPoint; 

  8. Continue the code in the if statement with the following code to build an Envelope that surrounds the location. Zoom the map to that extent by passing the envelope to SetViewAsync.

    var matchExtent = new Envelope(matchLocation.X - 100, 
                                   matchLocation.Y - 100, 
                                   matchLocation.X + 100, 
                                   matchLocation.Y + 100);
    await MyMapView.SetViewAsync(matchExtent);

    The Envelope is created by subtracting 100 meters from the location's minimum X and Y values and adding 100 meters to the maximum X and Y values.

  9. Run the app and test the Find button.

    Map zoomed to the extent of the first address match

The map zooms to the extent of the first result found.


If you want the user to review all matches, you can modify the app to show the list of results along with the value of each candidate's Score property (an int between 0 and 100).

Add a point graphic at the address location

Your app currently zooms to the extent of a match but does not show its precise location. In the following steps, you'll add code to place a point graphic to indicate the location of the match.

  1. At the top of your MainWindow.xaml.cs code file, add the following using statements to bring in the required Esri.ArcGISRuntime.Symbology and Esri.ArcGISRuntime.Layers namespaces.

    using Esri.ArcGISRuntime.Symbology;
    using Esri.ArcGISRuntime.Layers;

  2. Return to the FindAddressButton_Click event handler. Below the line that instantiates the matchLocation variable, add the following code to instantiate a new PictureMarkerSymbol for displaying the point. Set the source of the marker's picture using the SetSourceAsync method with the await keyword.

    var matchSym = new PictureMarkerSymbol();
    var pictureUri = new Uri("");
    await matchSym.SetSourceAsync(pictureUri);


    The Static Images topic in the API reference contains a list of available images hosted on

  3. Create a new Graphic. Pass in the geometry and symbol to the constructor.

    var matchGraphic = new Graphic(matchLocation, matchSym);

  4. Get a reference to the graphic layer you defined for the map, and add the new graphic.

    var graphicsLayer = MyMap.Layers["GeocodeResults"] as GraphicsLayer;

  5. Test the app. In addition to zooming to the match location, you'll also see a pushpin marker at the match location.

    Point graphic on the map showing the location of the match

  6. Instead of an address, search for a well known place name. Try Smithsonian or White House, for example.

    The world geocoding service allows you to find locations by providing an address or—for well known places—a name.

Use reverse geocoding to determine addresses for locations on the map

In the previous sections, you used geocoding to find points on the map using an input address string. In this section, you'll use the opposite approach: taking a location on the map as input and determining the (approximate) address for the point supplied.

  1. Open the MainWindow.xaml page and add a new Button called ReverseGeocodeButton to your existing XAML as shown in the following code example:

    <StackPanel Orientation="Vertical" 
               HorizontalAlignment="Left" VerticalAlignment="Top" >
       <StackPanel Orientation="Horizontal">
          <TextBox x:Name="AddressTextBox" Text="1145 17th St NW, Washington, DC 20036" Margin="10,0"/>
          <Button x:Name="FindAddressButton" Content="Find" Click="FindAddressButton_Click"/>                
       <Button x:Name="ReverseGeocodeButton" Content="Reverse Geocode"/>

  2. Add a click handler to the button. When prompted by IntelliSense, create a New Event Handler named ReverseGeocodeButton_Click.

    <Button x:Name="ReverseGeocodeButton" Content="Reverse Geocode" Click="ReverseGeocodeButton_Click"/>

  3. Right-click the ReverseGeocodeButton_Click handler in the XAML, and choose Go To Definition in the context menu that appears.

    Go To Definition menu choice

    The code view opens to the ReverseGeocodeButton_Click event handler.

  4. While the MapView control exposes touch and mouse events, such as MapViewTapped, MapViewDoupleTapped, and MapViewHolding, these events aren't always the best places to capture geometry from the user. Since such events fire when the user zooms and pans on the map, you need to add logic to prevent your code from running in those scenarios.

    The MapView control has an associated Editor that is accessible from the Editor property. In addition to helping you configure editing functionality, the Editor class provides methods for obtaining geometry from the user. You'll use the RequestPointAsync method on the Editor to get a point to reverse geocode from the user.

  5. Start the ReverseGeocodeButton_Click event handler with the following code to get a point from the user:

    var mapPoint = await MyMapView.Editor.RequestPointAsync();

    Because the call to RequestPointAsync is asynchronous, you must use the await keyword. This means that the function that contains the call must also be marked with the async keyword.

  6. Add the async keyword to the definition of the ReverseGeocodeButton_Click handler.

    private async void ReverseGeocodeButton_Click(object sender, RoutedEventArgs e)

  7. RequestPointAsync returns the user's map click as a MapPoint object. Because the map is in a Web Mercator spatial reference, and the OnlineLocatorTask you're using requires geographic points (decimal degrees of longitude and latitude), you need to project the point before performing the reverse geocode.
  8. Add the following code (after the line that instantiates the mapPoint variable) to project the user's point to geographic units:

    var mapPointGeo = GeometryEngine.Project(mapPoint, SpatialReferences.Wgs84) as MapPoint;

  9. Create an OnlineLocatorTask using the same code you wrote for the geocoding operation, as shown in the following code example:

    var uri = new Uri("");
    var token = String.Empty;
    var locator = new OnlineLocatorTask(uri, token);

  10. Use the OnlineLocatorTask to perform the reverse geocode on the geographic point by calling its ReverseGeocodeAsync method.

    var addressInfo = await locator.ReverseGeocodeAsync(mapPointGeo, 100, new System.Threading.CancellationToken());

    The ReverseGeocdodeAsync method returns a LocatorReverseGeocodeResult. The information about the address is available in the AddressFields property.

  11. Build the estimated reverse geocoding address string by reading values in the LocatorReverseGeocodeResult AddressFields property, which is a dictionary of strings.

    var address = addressInfo.AddressFields["Address"] + ", " +
                  addressInfo.AddressFields["City"] + ", " +
                  addressInfo.AddressFields["Region"] + " " +

    The following keys are available in the AddressFields dictionary:

    • Address: house number and street, intersection, or place name.
    • City: city or municipality containing the address.
    • Region: the largest administrative division associated with an address, such as a state or province.
    • Subregion: the next largest administrative division, such as county (not used for US or Mexico addresses).
    • Neighborhood: the smallest administrative division associated with an address (not used for US addresses).
    • Postal: standard postal code for an address, typically a 3-6 digit alpha-numeric code
    • PostalExt: postal code extension (additional postal code information, such as the last four digits of a "zip + 4" postal code)
    • CountryCode: the full country name in English or the official language of the country, the ISO 3166-1 2-digit country code, or the ISO 3166-1 3-digit country code.
    • Loc_name

  12. Display the address to the user.


  13. Test the app. Zoom to a portion of the map where streets are visible, click the Reverse Geocode button, and click near a street to see an interpolated address.

    Reverse geocode result

In this tutorial, you used the OnlineLocatorTask to perform geocoding and reverse geocoding operations using an ArcGIS for Server geocode service. To perform the same operations using a locator on the local file system, use the LocalLocatorTask class. To learn about providing routing functionality and detailed driving directions using the ArcGIS Runtime SDK for .NET, see the Get driving directions tutorial.

Related topics