Address Geocoding in .NET using the Bing Maps REST Services API

I came across this excellent post by Jatin Kacha on how to call the Google Map WebService API from asp.net and though to change it slightly to instead call the Bing Maps REST service.

The main changes made on Jatin’s code is the calling URL and the way the returned XML is handled due to the differences between Google’s and Bing’s services plus a small change when retrieving the Lat/Lon values to cater for non-english number formats.

All you need to do is create a class file and copy/paste the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;
using System.Configuration;

namespace Gaiocorp.Geocoding
{
    /// Resolve addresses into latitude/longitude coordinates using Google MAP API webservices
    public static class BingGeocoder
    {
        private static string _BingMapsKey = ConfigurationManager.AppSettings["BingMapsKey"];
        /// Bing Maps Geocoder
        /// Url request to
        ///http://dev.virtualearth.net/REST/v1/Locations?countryRegion=countryRegion&adminDistrict=adminDistrict&locality=locality&postalCode=postalCode&addressLine=addressLine&key=BingMapsKey;
        public static BingGeolocation? ResolveAddress(string query)
        {
            if (string.IsNullOrEmpty(_BingMapsKey))
            {
                _BingMapsKey = System.Configuration.ConfigurationManager.AppSettings["BingMapsKey"];
            }
            string url = "http://dev.virtualearth.net/REST/v1/Locations?o=xml&q={0}&key=" + _BingMapsKey;
            url = String.Format(url, query);
            XmlNode coords = null;
            try
            {
                string xmlString = GetUrl(url);
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(xmlString);
                XmlNamespaceManager xnm = new XmlNamespaceManager(xd.NameTable);
                coords = xd.GetElementsByTagName("Point")[0];
             }

             catch { }
             BingGeolocation? gl = null;
             if (coords != null & coords.HasChildNodes)
             {
                string Lat = coords.ChildNodes[0].InnerText;
                string Lon = coords.ChildNodes[1].InnerText;
                gl = new BingGeolocation(Convert.ToDecimal(Lat, System.Globalization.CultureInfo.InvariantCulture), Convert.ToDecimal(Lon, System.Globalization.CultureInfo.InvariantCulture));
             }
             return gl;
         }

        ///<summary>
        /// Retrieve a Url via WebClient
        /// 
        public static string GetUrl(string url)
        {
            string result = string.Empty;
            System.Net.WebClient Client = new WebClient();
            using (Stream strm = Client.OpenRead(url))
            {
                StreamReader sr = new StreamReader(strm);
                result = sr.ReadToEnd();
            }

            return result;
        }

        /// <summary>
        /// Returns the Lat
        /// </summary>
        /// <param name="address"></param>
        /// <param name="city"></param>
        /// <param name="state"></param>
        /// <param name="postcode"></param>
        /// <param name="country"></param>
        /// <returns></returns>
        public static BingGeolocation? ResolveAddress(string address, string city, string state, string postcode, string country)
        {
            return ResolveAddress("&addressLine=" + address + "&locality=" + city + "&adminDistrict=" + state + "&postalCode=" + postcode + "&countryRegion=" + country);
        }

    }

    public struct BingGeolocation
    {
        public decimal Lat;

        public decimal Lon;

        public BingGeolocation(decimal lat, decimal lon)
        {
            Lat = lat;
            Lon = lon;
        }

        public override string ToString()
        {
            return "Latitude: " + Lat.ToString() + " Longitude: " + Lon.ToString();
        }
        public string ToQueryString()
        {
            return "+to:" + Lat + "%2B" + Lon;
        }
    }
}

And there you have it. You could then call the function in the following manner, say from a button click. The only potential problem may be to parse correctly the input address since the Bing Maps API requires all address components (street, city,zip etc) to be provided separately.

protected void Button4_Click(object sender, EventArgs e) //Get latlon using Bing
        {
            if (txbAddress.Text.Trim() != string.Empty)
            {
               BingGeolocation? bl= BingGeocoder.ResolveAddress(txbAddress.Text.Split(',')[0].Trim(), txbAddress.Text.Split(',')[1].Trim(), string.Empty, string.Empty, string.Empty);
               if (bl != null)
               {
                   txbBing.Text = "Lat: " + bl.Value.Lat.ToString() + " Lon:" + bl.Value.Lon;
               }
            }
        }

You could also easily extend it to also add reverse address geocoding or routing. For more information you can check the Bing Maps REST Services API Reference.

Enjoy!

One thought on “Address Geocoding in .NET using the Bing Maps REST Services API

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