Prash's Blog

Using Virtual Earth / Bing Geocoding Webservice July 24, 2009

Filed under: Bing — prazjain @ 4:10 pm
Tags: , , , ,

Me being new in London, I took it upon myself to find pubs close to me. I created a database with location of pubs, now I had to do display them on map to find their proximity. As I just had the address of these pubs and not their geographic coordinates, I needed to convert address to geographic coordinates. And then I can use them on any of the various mapping platforms to display location on map.

I wrote a tool which would enrich the existing database of pubs with their respective geocodes. I am giving an overview of what / how I went ahead with doing that:

  1. Get a windows live id, if you do not already have one. You can get one here : https://accountservices.passport.net
  2. Get a license for using the Geocoding Webservice. You would need to register for Bing Maps Developer account. You can sign up here : https://mappoint-css.live.com/mwssignup/
  3. Now, I am assuming you already have a Visual Studio solution and project created where you are going to use this functionality, add a reference to this web service :

    https://staging.common.virtualearth.net/find-30/common.asmx, use this as URL for service and name it as ‘VEStagingToken’.

  4. Create a class GeoCodeFetcher that would hold all the logic for interacting with geocoding webservices.
  5. In your project create a reference to webservice VEGeocodingService pointing to this url: http://staging.dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl

PS : Bing limits you 30,000 transactions per day in the free developer account, which should be enough for any sample developer application. [Confirmed through offical sources and true as of July 2009]

For the rest, I have written commented code for your reading, this should be fairly self-explanatory.

Note: I could have refactored AddressToGeocode method a little bit to reduce the number of if/else conditions, but the aim of this post is to be make it more understandable for any new programmer who is using this service for the first time.

This Code sample is in C#, you can as well port this code to Java with minor syntax changes.


///<summary>
/// Responsible for getting geocodes for a pub address. This class also holds logic
///for connecting to databases and saving data back to databases.
///</summary>
public class GeoCodeFetcher
{
#region [ Private Variables ]
///<summary>
/// Token that is to be sent everytime a GeocodeService call is made to VE to get geocodes for
/// a pub address.
///</summary>
private string _clientToken;

#endregion

#region [ Constructors ]
///<summary>
/// Gets a token from VE webserice for making Geocode service calls.
///</summary>

public GeoCodeFetcher()
{
string veAccountId = "VEAccountId";
string veAccountPwd = "VEAccountPwd";
// create the token once for all calls
CreateToken(veAccountId, veAccountPwd);
}

#endregion

#region [ Private Methods ]

///<summary>
/// Get a token for invoking VE services with max validity of 60 mins.
///</summary>
///<param></param>
///<param></param>
private void CreateToken(string username, string pwd)
{

CommonService commonService = new CommonService();
commonService.Url = "https://staging.common.virtualearth.net/find-30/common.asmx";
commonService.Credentials = new System.Net.NetworkCredential(username, pwd);
// create token specification
TokenSpecification tokenSpec = new TokenSpecification();
// some ip, this is used for tracking by VE services. Ideally should be IP of machine that is
// making service calls. But it would not fail the call if its any valid ip.
// putting in some value as the service call should not fail because of this

tokenSpec.ClientIPAddress = "x.x.x.x";
tokenSpec.TokenValidityDurationMinutes = 60; // 8 hrs is max limit.
_clientToken = commonService.GetClientToken(tokenSpec);

}

#endregion

#region [ Public Methods ]
///<summary>
/// This gets the address as argument and returns the latitude and longitude geocode for it.
///</summary>
///<param></param>
///<param></param>
///<param></param>
public void AddressToGeocode(string address, out decimal latitude, out decimal longitude)
{
string results = string.Empty;
// create a geocode request
GeocodeRequest geocodeRequest = new GeocodeRequest();
//Set the token received from VE service as credential token
geocodeRequest.Credentials = new VEGeocodingService.Credentials();
geocodeRequest.Credentials.Token = _clientToken;
// set the address as query
geocodeRequest.Query = address;
// we want only the top result so min confidence is high

ConfidenceFilter[] filters = new ConfidenceFilter[1];

filters[0] = new ConfidenceFilter();
filters[0].MinimumConfidence = VEGeocodingService.Confidence.High;
//set the geocode options
GeocodeOptions geocodeOptions = new GeocodeOptions();
geocodeOptions.Filters = filters;
geocodeRequest.Options = geocodeOptions;
GeocodeServiceClient geocodeServiceClient = new GeocodeServiceClient();
GeocodeResponse geocodeResponse = geocodeServiceClient.Geocode(geocodeRequest);

// if more than one result available then take the top result
if (geocodeResponse.Results.Length > 0)
{
latitude = (decimal)geocodeResponse.Results[0].Locations[0].Latitude;
longitude = (decimal)geocodeResponse.Results[0].Locations[0].Longitude;
}
else
{
// try search with medium confidence
filters[0].MinimumConfidence = VEGeocodingService.Confidence.Medium;
GeocodeResponse gcrMedium = geocodeServiceClient.Geocode(geocodeRequest);
 if (gcrMedium.Results.Length > 0)
{
latitude = (decimal)gcrMedium.Results[0].Locations[0].Latitude;
longitude = (decimal)gcrMedium.Results[0].Locations[0].Longitude;
}
else
{
filters[0].MinimumConfidence = VEGeocodingService.Confidence.Low;
GeocodeResponse gcrLow = geocodeServiceClient.Geocode(geocodeRequest);
if (gcrLow.Results.Length > 0)
{
latitude = (decimal)gcrLow.Results[0].Locations[0].Latitude;
longitude = (decimal)gcrLow.Results[0].Locations[0].Longitude;
}
 else
{
// throw an exception that geocodes could not be found for this pub
throw new Exception();
}
}
}
}
#endregion
}

These are all the helper methods you would need to actually interact with the services, and use them in your code whereever you need to geocode data.

Check the article on how to use the geocoded values to calculate route from point A to point B and more. How to use Routing Service.

Advertisements
 

6 Responses to “Using Virtual Earth / Bing Geocoding Webservice”

  1. George Says:

    Hi! I tried it out and I have a few problems.. ILog and CmdLineArgs could not be found.. Am I missing anything?

  2. prazjain Says:

    For ILog : Add reference to log4net.dll (its an open source logging library). Download it from here : http://logging.apache.org/log4net/download.html

    For CmdLineArgs : Looks like I did not cleanup before posting it. You can remove that parameter from constructor, its not needed.

    I will update the post with the second change.

  3. george Says:

    Ok I got it. Thanks a lot

  4. JimmyBean Says:

    I don’t know If I said it already but …Great site…keep up the good work. 🙂 Thanks, 🙂

    A definite great read..Jim Bean

  5. […] How to use Routing Service in Virtual Earth / Bing In my previous article on using Geocoding service in Virtual Earth I gave an introduction on how to geo code the address. See here. […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s