In this tutorial we are going to look at what you need to go from a a Address to a Lat Long(GeoCode) and from a Lat Long to a Address(reverse geocode)
First a picture of what the final project will look like.
Note:
You must! change the username in the web.config
<add key="VEUsername" value="YourKey"/>
<add key="VEPassword" value="YourPassword"/>
with your information
1) Learn about Tokens
Okay, so, first things first, you need to authenticate - see my post Authentication and Tokens with Virtual Earth for authentication.
2) Create a blank AJAX project in VS
Now that you are dialed in with your virtual earth tokens we are going to dive right into the web services. Lets go ahead and create a blank project in VS
3) Add the UI
I am going to spice this up a bit and make it Ajax enabled. So go ahead and install AJAX or if you are using VS2008 sp 1 you should be already cool. So go ahead and through a script manager down and a update panel, and a update progress manager down on the page. This is the web form should look like in between the body tags should look this now.
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1" DisplayAfter="5">
<ProgressTemplate>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
4 ) Add page propeties
Now are going to add our table to the update content template
<table border="1">
<tr>
<td valign="top">
Address: <asp:TextBox runat="server" ID="TextBox_Address" Width="250" />
<br />
<asp:Button runat="server" Text="Geocode" ID="Button_Geocode"
onclick="Button_Geocode_Click" />
</td>
<td>
Latitude: <asp:TextBox runat="server" ID="TextBox_Latitude" Width="250" />
<br />
Longitude: <asp:TextBox runat="server" ID="TextBox_Longitude" Width="250" />
<br />
<asp:Button runat="server" Text="Reverse Geocode" ID="Button_ReverseGeocode"
onclick="Button_ReverseGeocode_Click" />
</td>
</tr>
</table>
<br />
then add a div we are going to inject our information that we get back from Virtual Earth
<div runat="server" id="Div_Info" />
5) Add a web reference to the VE Geocode Service
Now are going to add a web reference to the VE Geocode Service
This is the address at the time of writing this article
http://staging.dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl
In our service refrence we now will have something that looks like this
Sweet that was easy.
6) Add a Utility class
Now that we have that we need to add a Utility class that will take our developer credentials and get us a token so we can start making requests against the web service api..
Here is a great class for doing that.. I named it Utils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.ServiceModel;
using VEWebServicesDemo.VEAuthenticationService;
using VEWebServicesDemo.VEGeocodeService;
using System.Configuration;
using System.Collections;
using System.Text.RegularExpressions;
namespace VEWebServicesDemo
{
public static class Utils
{
private static string GetVEUsername() { return ConfigurationManager.AppSettings["VEUsername"].ToString(); }
private static string GetVEPassword() { return ConfigurationManager.AppSettings["VEPassword"].ToString(); }
public static string StripHTMLTags(string HtmlToStrip)
{
return Regex.Replace(HtmlToStrip, @"<(.|\n)*?>", string.Empty);
}
/// <summary>Returns a token from the Virtual Earth web service</summary>
public static string Token(string ClientIP)
{
// This token will expire so that should be handled appropriately
// Create a CommonService so we can make the request
CommonService commonService = new CommonService
{
// Supply your Virtual Earth credentials
// to get a Virtual Earth developer account, go to https://mappoint-css.live.com/MwsSignup/
Credentials = new NetworkCredential(Utils.GetVEUsername(), Utils.GetVEPassword())
};
// Create a token specification
TokenSpecification tokenSpecification = new TokenSpecification
{
// Token will expire in 60 minutes, max is 480 minutes
TokenValidityDurationMinutes = 60,
// Supply the client's IP address
ClientIPAddress = ClientIP
};
return commonService.GetClientToken(tokenSpecification);
}
}
}
Great so we have our auth service and we have our credentials class lets get into the fun stuff.
7) Give it Guts
Now have our front end our data access layer lets set up the middlish tier
First thing I am going to do is load up the page with some default values in the page_load so that when i demo this it I can click and show .
protected void Page_Load(object sender, EventArgs e)
{
// Set a default address to search for.
if (this.IsPostBack == false)
{
// Default for the address box
this.TextBox_Address.Text = "1313 S Figueroa St, Los Angeles, California 90015, United States";
//LACC
this.TextBox_Latitude.Text = "34.0404";
this.TextBox_Longitude.Text = "-118.2688";
}
}
Next I am going to add functionality to the button to get a gecode from a address all information on the function are in the comments
/// <summary>Geocodes the address specified in the UI</summary>
/// <param name="sender">The sender</param>
/// <param name="e">Event arguments</param>
protected void Button_Geocode_Click(object sender, EventArgs e)
{
// Clear any existing data from our div
this.Div_Info.InnerHtml = "";
GeocodeRequest geocodeRequest = new GeocodeRequest();
// Create a new Credential object and provide the token
geocodeRequest.Credentials = new VEGeocodeService.Credentials();
geocodeRequest.Credentials.Token = Utils.Token(Request.UserHostAddress);
// Set the address from the UI on the request
geocodeRequest.Query = this.TextBox_Address.Text.Trim();
// Create a new geocode client
GeocodeServiceClient geocodeServiceClient = new GeocodeServiceClient();
// Execute the geocode request
GeocodeResponse geocodeResponse = geocodeServiceClient.Geocode(geocodeRequest);
// Iterate through each of the results and send write some data to the UI
foreach (GeocodeResult geocodeResult in geocodeResponse.Results)
{
this.WritePair("Formatted Address", geocodeResult.Address.FormattedAddress);
this.WritePair("Display Name", geocodeResult.DisplayName);
this.WritePair("Confidence", geocodeResult.Confidence.ToString());
// Iterate through each location within the result and send back the Lat/Long
foreach (GeocodeLocation geocodeLocation in geocodeResult.Locations)
{
this.WritePair("Calculation Method", geocodeLocation.CalculationMethod);
this.WritePair("Longitude", geocodeLocation.Latitude.ToString());
this.WritePair("Latitude", geocodeLocation.Longitude.ToString());
}
this.WriteInfo("");
}
}
I am going to add the reverse geocode functionality
/// <summary>Reverse geocodes the latatitude and longitude specified in the UI</summary>
/// <param name="sender">The sender</param>
/// <param name="e">Event arguments</param>
protected void Button_ReverseGeocode_Click(object sender, EventArgs e)
{
// Clear any existing data from our div
this.Div_Info.InnerHtml = "";
//Create a new ReverseGeoCode Request object
ReverseGeocodeRequest reverseGeocodeRequest = new ReverseGeocodeRequest();
// Create a new Credential object and provide the token
reverseGeocodeRequest.Credentials = new VEGeocodeService.Credentials();
reverseGeocodeRequest.Credentials.Token = Utils.Token(Request.UserHostAddress);
//New a VEGeocode Location object and set it's properties
reverseGeocodeRequest.Location = new Location
{
Latitude = Convert.ToDouble(this.TextBox_Latitude.Text),
Longitude = Convert.ToDouble(this.TextBox_Longitude.Text)
};
// New up a new GeocodeServiceClient to make our request with
GeocodeServiceClient geocodeServiceClient = new GeocodeServiceClient();
// Execute the ReverseGeocode request
GeocodeResponse geocodeResponse = geocodeServiceClient.ReverseGeocode(reverseGeocodeRequest);
// Write out the response information to the UI
foreach (GeocodeResult geocodeResult in geocodeResponse.Results)
{
this.WritePair("Display Name", geocodeResult.DisplayName);
this.WritePair("Entity Type", geocodeResult.EntityType);
this.WritePair("Confidence", geocodeResult.Confidence.ToString());
this.WritePair("Address Line", geocodeResult.Address.AddressLine);
this.WritePair("Locality (city)", geocodeResult.Address.Locality);
this.WritePair("Admin District (state)", geocodeResult.Address.AdminDistrict);
this.WritePair("Postal Code", geocodeResult.Address.PostalCode);
this.WriteInfo("");
}
}
A couple of little helper functions
// <summary>Writes a name/value pair to the UI, name is bolded.</summary>
/// <param name="name">Name of the name/value pair</param>
/// <param name="value">Value of the name/value pair</param>
protected void WritePair(string name, string value)
{
this.WriteInfo("<B>" + name + ":</B> " + value);
}
/// <summary>Writes information to the UI</summary>
/// <param name="html">HTML to write to the UI</param>
protected void WriteInfo(string html)
{
this.Div_Info.InnerHtml += html + "<br/>\n";
}
}
And Bam we have a working demo. 7 Steps to Virtual Earth Web Services.
Here is a shot of the what the reverse geocode spits out
Have Fun!