For those of you who may want to get access to the 85 million unique rooftop or parcel centroid accurate points we've aggregated in the Virtual Earth Web Service (VEWS), I figured it was only fair that I post a little something to help move you along. Hopefully, this helps you get past a sticking point in your application development. Also, I did all of this on staging so everyone who has an account can do this.

Okay, so, first things first, you need to authenticate - see my post Authentication and Tokens with Virtual Earth for authentication. You'll need a token to use any part of the VEWS and there's a good explanation on how to do that for VEWS in my other post (and information on getting a map) - Getting a Map with the Virtual Earth Web Service, but I'll copy the code to be nice.

The application consists of 3 files - Authentication.cs (a class file for getting me a token); Geocoding.aspx (the UI file for adding web parts); and, Geocoding.aspx.cs (the code behind file where the magic happens). As for my code, it's only meant to get you up and running to understand architecture - it is not production code. You'll want error handling and try catches and all the good stuff - this is just the meat and potatoes.


using System;
using System.Data;
using System.Configuration;
using VEWSStaging; //VEWS is a reference to

/// <summary>
/// Authenticating for VE Tokens
/// </summary>
public class Authentication
    public static string strVEWSToken;
    public static string Authenticate(string strIP)
        CommonService commonService = new CommonService();
        commonService.Url = "";
        commonService.Credentials = new System.Net.NetworkCredential("XXXX", "YYYY");

        // Create the TokenSpecification object to pass to GetClientToken.
        TokenSpecification tokenSpec = new TokenSpecification();

        // Use the Page object to retrieve the end-client’s IPAddress.
        tokenSpec.ClientIPAddress = strIP;

        // The maximum allowable token duration is 480 minutes (8 hours).
        // The minimum allowable duration is 15 minutes.
        tokenSpec.TokenValidityDurationMinutes = 480;

        // Now get a token from the Virtual Earth Platform Token service.
        strVEWSToken = commonService.GetClientToken(tokenSpec);
        return strVEWSToken;

Next, I'll need to set a reference to the geocoding service (WCF) - Website | Add Service Reference. I named my service "GeocodeService" which you can see has two methods - Geocode and ReverseGeocode.


Next, we'll need to add UI elements to Geocoding.aspx. I added a Label (as a title), a Text box (to input addresses or places), a Button (to submit the data) and a Table (to store the results). When I'm done, Geocoding.aspx looks like this...


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Geocoding.aspx.cs" Inherits="Geocoding" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">

<html xmlns="">
<head runat="server">
    <title>CP's Geocoding Page</title>
    <form id="form1" runat="server">
        Enter a location</div>
    <asp:TextBox ID="TextBox1" runat="server" Height="20px" Width="375px"></asp:TextBox>
    <asp:Button ID="Button1" runat="server" Height="21px" onclick="Button1_Click"
        Text="Geocode!" Width="80px" />
    <asp:Table ID="Table1" runat="server" Height="475px" style="margin-top: 0px"

And now for the magic. We'll use these elements to make a service request to VEWS to submit the data in the text box and geocode the location. I'll take the entire response and break up each part so you can see most of what gets returned in the response. Make sure you add a reference to the GeocodeService we added above.


using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using GeocodeService;

public partial class Geocoding : System.Web.UI.Page
    protected void Page_Load(object sender, EventArgs e)

    protected void Button1_Click(object sender, EventArgs e)
        //Get user IP for token
        string token = Authentication.Authenticate(Page.Request.UserHostAddress);
        //Instantiate geocode request
        GeocodeRequest myGeocodeRequest = new GeocodeRequest();
        //Instantiate credentials for geocode request
        myGeocodeRequest.Credentials = new GeocodeService.Credentials();
        //Add token to geocode request
        myGeocodeRequest.Credentials.Token = token;
        //Using GeocodeRequest.Query so we don't need a structured request - just single box
        myGeocodeRequest.Query = TextBox1.Text;
        //Instantiate confidence filter - I just want one filter
        ConfidenceFilter[] myConfidenceFilter = new ConfidenceFilter[1];
        //Instantiate filter
        myConfidenceFilter[0] = new ConfidenceFilter();
        //!Had to specify Geocode Service because Confidence is defined also in Imagery Service!
        //Setting confidence to low so I get maximum results
        myConfidenceFilter[0].MinimumConfidence = GeocodeService.Confidence.Low;
        //Instantiate Geocode options
        GeocodeOptions myGeocodeOptions = new GeocodeOptions();
        //I only want at most 5 results
        myGeocodeOptions.Count = 5;
        //Pass in my confidence filter
        myGeocodeOptions.Filters = myConfidenceFilter;
        //Pass in my geocode options
        myGeocodeRequest.Options = myGeocodeOptions;
        //Instatiate geocode service client for connection to VEWS
        GeocodeServiceClient myGeocodeServiceClient = new GeocodeServiceClient();
        //Physically making VEWS request!
        GeocodeResponse myGeocodeResponse = myGeocodeServiceClient.Geocode(myGeocodeRequest);
        //Loop through results to pull out response and put into a table
        //I'll only get 1 response, but it could have multiple results
        for(int i = 0; i < myGeocodeResponse.Results.Length; i++)
            TableRow tRow = new TableRow();
            TableCell tCell0 = new TableCell();
            tCell0.VerticalAlign = VerticalAlign.Top;
            tCell0.Text = "Formatted Address = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.FormattedAddress;
            tCell0.Text += "<br> Address Line= ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.AddressLine;
            tCell0.Text += "<br> Locality = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.Locality;
            tCell0.Text += "<br> Admin District = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.AdminDistrict;
            tCell0.Text += "<br> Postal Code = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.PostalCode;
            tCell0.Text += "<br> Country = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.CountryRegion;
            tCell0.Text += "<br> District = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.District;
            tCell0.Text += "<br> Postal Town = ";
            tCell0.Text += myGeocodeResponse.Results[i].Address.PostalTown;
            tCell0.Text += "<br> Confidence = ";
            tCell0.Text += myGeocodeResponse.Results[i].Confidence;
            tCell0.Text += "<br> Display Name = ";
            tCell0.Text += myGeocodeResponse.Results[i].DisplayName;
            tCell0.Text += "<br> Entity Type = ";
            tCell0.Text += myGeocodeResponse.Results[i].EntityType;
            tCell0.Text += "<br> Altitude= ";
            tCell0.Text += myGeocodeResponse.Results[i].Locations[i].Altitude;
            /* If there are multiple response types, the latitude, longitude and
             * Calculation methods will have more than one result in their array. This
             * is where you'll want to differentiate them to use either interpolated,
             * rooftop or parcel centroids depending on how accurate you want them. */
            for (int j = 0; j < myGeocodeResponse.Results[i].Locations.Length; j++)
                tCell0.Text += "<br> Latitude = ";
                tCell0.Text += myGeocodeResponse.Results[i].Locations[j].Latitude;
                tCell0.Text += "; Longitude = ";
                tCell0.Text += myGeocodeResponse.Results[i].Locations[j].Longitude;
                tCell0.Text += "; (";
                tCell0.Text += myGeocodeResponse.Results[i].Locations[j].CalculationMethod;
                tCell0.Text += ")";

The end results is a nice little parsing of some address information returned from VEWS:


There isn't any difference in the geocoding results you get back between VEWS and the Virtual Earth AJAX control. Both now have rooftop and parcel centroid geocoding points totaling 85 million in the United States. Now, if I can just figure out what's up with the space between my text box and my table....[FIXED - tCell0.VerticalAlign = VerticalAlign.Top; ]