C# Google Geocode (Latitude and Longitude) Class

By admin on Mar 13 2007 | 47 Comments

Update 2007/05/07: There is also a Microsoft MapPoint v4.5 project I've written that does the same thing. Click here to go to that post.


Retrieve the Latitude and Longitude of any addresses in the United States, Canada, France, Germany, Italy, Spain and Japan (link) with this class. View the class below and download the class at the bottom of this post.

Code


using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Net;
using System.Web.UI;


namespace GoogleGeocoder
{
   public interface ISpatialCoordinate
   {
      decimal Latitude {get; set; } 
      decimal Longitude {get; set; } 
   }

   /// <summary>
   /// Coordiate structure. Holds Latitude and Longitude.
   /// </summary>
   public struct Coordinate : ISpatialCoordinate
   {
      private decimal _latitude; 
      private decimal _longitude;

      public Coordinate(decimal latitude, decimal longitude)
      {
         _latitude = latitude;
         _longitude = longitude; 
      }

      #region ISpatialCoordinate Members

      public decimal Latitude
      {
        get 
        { 
            return _latitude; 
        }
        set 
        { 
            this._latitude = value; 
        }
      }

      public decimal Longitude
      {
        get 
        { 
            return _longitude; 
        }
        set 
        { 
            this._longitude = value;
        }
      }

   #endregion
   }

   public class Geocode
   {
      private const string _googleUri = "http://maps.google.com/maps/geo?q=";
      private const string _googleKey = "yourkey";
      private const string _outputType = "csv"; // Available options: csv, xml, kml, json

      private static Uri GetGeocodeUri(string address)
      {
         address = HttpUtility.UrlEncode(address);
         return new Uri(String.Format("{0}{1}&output={2}&key={3}", _googleUri, address, _outputType, _googleKey));
      }

      /// <summary>
      /// Gets a Coordinate from a address.
      /// </summary>
      /// <param name="address">An address.
      /// <remarks>
      /// <example>1600 Amphitheatre Parkway Mountain View, CA 94043</example>
      /// </remarks>
      /// </param>
      /// <returns>A spatial coordinate that contains the latitude and longitude of the address.</returns>
      public static Coordinate GetCoordinates(string address)
      {
         WebClient client = new WebClient();
         Uri uri = GetGeocodeUri(address);


         /* The first number is the status code, 
         * the second is the accuracy, 
         * the third is the latitude, 
         * the fourth one is the longitude.
         */

         string[] geocodeInfo = client.DownloadString(uri).Split(',');

         return new Coordinate(Convert.ToDecimal(geocodeInfo[2]), Convert.ToDecimal(geocodeInfo[3]));
      }

   }
}


How To Use


  1. Replace "yourkey" with your google api key. Get one here.
  2. Include in your project, reference the class through a using directive.
  3. Call get the coordinates like this:
    1. Coordinate coordinate = Geocode.GetCoordinates("1600 Amphitheatre Parkway Mountain View, CA 94043");
      decimal latitude = coordinate.Latitude;
      decimal longitude = coordinate.Longitude;

Uses


For each record in your system, get the lat/long and save it to the database. This can be used for calculating distances. e.g.: "Find all stores within ___ miles of this zip code.

 

***Notes***


The maximum # of Geocode requests that can be completed in one day are 50,000 (details).

 

Download
Geocode.zip (1.05 KB)

kick it on DotNetKicks.com

Post info

Tags:
Categories: .NET , GIS

Comments

Jason
Jason on 7/17/2007 8:18 PM Hey I'm trying to get this to work in vb.net.  Can you help me convert it?
Donn
Donn on 7/17/2007 8:47 PM I'd try running it through a converter if you have the ability to: Here is one: http://www.kamalpatel.net/ConvertCSharp2VB.aspx

If I get time later this week i'll conver it over for you.

Or, you could always take it, then compile it into a dll, and then use Reflector to reflect into it and copy the code that way.

That would work. Smile

Kathy
Kathy on 8/5/2007 7:04 AM Your Google Geocode Class has been the best, easiest class I have ever seen. Saved me a lot of time and it works like a charm.
thanks a million Smile
Suman
Suman on 8/13/2007 6:17 AM Thanks for providing store locator, its really great. I just want to know can we display the distance between, if yes how can we do this???
Brian Sobel
Brian Sobel on 8/21/2007 12:46 AM Thank You.  This was awesome!
Habib Haider
Habib Haider on 8/27/2007 2:22 PM This is awesome. Saved me so much time! Thanks dude!!!
friend
friend on 9/14/2007 5:16 PM // Uses PHP to query a website which gets latitude and longitude info from Google Maps Geocode; without needed an API code
$zip = 94043; // your input zipcode; but if you want to do an entire address, get the possible inputs from the queried website
$site = file_get_contents('http://geocoder.ca/?postal='.$zip, false, NULL, 1000, 1000); // get a large chunk of the output string that will contain the coordinates
$goods = strstr($site, 'GPoint('); // cut off the first part up until the coordinates are provided
$end = strpos($goods, ')'); // the ending parenthesis of the coordinate string
$cords = substr($goods, 7, $end - 7); // returns string with only the coordinates as 'latitude, longitude' (can stop here if string wanted)
$array = explode(', ',$cords); // convert string into array(0 => $latitude, 1 => $longitude)
print_r($array); // output the array to verify
Janessa Allen
Janessa Allen on 10/6/2007 3:06 PM YOU'RE MY HERO!!! This class is awesome.
prabha
prabha on 10/17/2007 6:02 AM This code is working fine in local machine.When i work in remote server it produce the Security Exception error.
ie.System.Net.Web permissions is denied.How to solve this?
Donn
Donn on 10/17/2007 1:56 PM Prabha,
  It looks like your host probably has the WebPermission (msdn2.microsoft.com/.../...net.webpermission.aspx) locked down. To use the WebClient.DownloadString it requires access to the WebPermission to operate. They probably have it locked down in medium trust. Ask your host if they can open it up for you, if they cannot, its time to find a new host! Good luck!
garo on 12/11/2007 11:30 PM Really nice code but, there's a point that you should correct.
When converting to decimal if the localization is different than en-US, it produces wrong results.
Therefore a more correct version could be:

string[] geocodeInfo = client.DownloadString(uri).Split(',');
return new Coordinate(Convert.ToDecimal(geocodeInfo[2], System.Globalization.CultureInfo.InvariantCulture),
            Convert.ToDecimal(geocodeInfo[3], System.Globalization.CultureInfo.InvariantCulture));

So the convertion is done independent of the current thread.

Thanks for the class again...
Garo
Greg
Greg on 3/13/2008 9:57 PM Hi Donn -

Thanks for sharing this. I, as well, am trying to convert this to VB. After converting the Geocode.cs file (tried two different converters), I get a ASP compilation error when trying to run the store locator zip code lookup:

BC30154: Structure 'Coordinate' must implement 'Property Latitude() As Decimal' for interface 'ISpatialCoordinate'. Implementing property must have matching 'ReadOnly' or 'WriteOnly' specifiers.

Have you successfully gotten this to work in VB?

Man thanks!

: Greg
Donn Felker
Donn Felker on 3/14/2008 4:35 AM Greg,
  I never got a chance to covert it to VB.NEt. If you can zip up the files and email them to me donn [at] donnfelker [dot] com I will take a look and try to see what's going on. Smile

Thanks for reading!
son nguyen
son nguyen on 4/8/2008 7:39 AM Can i get List of Latitude and Longitude From List address. and just one request
Donn Felker
Donn Felker on 4/8/2008 12:57 PM @Son,
From my understanding of the API at the time I wrote this, no you cannot. I'd just throw a loop around the address list and get the coordinates that way.
  
Steam O
Steam O on 5/7/2008 4:14 PM Nice work!

I have a question, what was the reason for defining ISpatialCoordinate interface?
Thanks.
Samba
Samba on 6/2/2008 1:14 PM Here is the class in VB.Net, a little bit modified tough.

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Web
Imports System.Net
Imports System.Web.UI
Imports System.Configuration

Namespace GoogleGeoCoder
    Public Interface ISpatialCoordinate
        Property latitude() As Double
        Property longitude() As Double
    End Interface

    ''' <summary>
    ''' Coordiate structure. Holds Latitude and Longitude.
    ''' </summary>
    Public Structure Coordinate
        Implements ISpatialCoordinate

        Private _latitude As Double
        Private _longitude As Double

        Public Sub New(ByVal lattitude As Double, ByVal longitude As Double)
            _latitude = lattitude
            _longitude = longitude
        End Sub

        Public Property latitude() As Double Implements ISpatialCoordinate.latitude
            Get
                Return _latitude
            End Get
            Set(ByVal value As Double)
                _latitude = value
            End Set
        End Property

        Public Property longitude() As Double Implements ISpatialCoordinate.longitude
            Get
                Return _longitude
            End Get
            Set(ByVal value As Double)
                _longitude = value
            End Set
        End Property
    End Structure

    Public Class GeoCode
        Const _googleUri As String = "http://maps.google.com/maps/geo?q="
        Const _googleKey As String = "ABQIAAAAo2IA2cVAlIlCYUDAzZp7xRSgqHK7--hlh5V3mDs919jumqTYpBSWjH2x8r8skFMvCG1-iwYPpbNFSg"
        Const _outputType As String = "csv"

        Private Shared Function GetGeoCodeUri(ByVal address As String) As Uri
            address = HttpUtility.UrlEncode(address)
            Return New Uri(String.Format("{0}{1}&output={2}&key={3}", _googleUri, address, _outputType, _googleKey))
        End Function

        ''' <summary>
        ''' Gets a Coordinate from a address.
        ''' </summary>
        ''' <param name="address">An address.
        ''' <remarks>
        ''' <example>1600 Amphitheatre Parkway Mountain View, CA 94043</example>
        ''' </remarks>
        ''' </param>
        ''' <returns>A spatial coordinate that contains the latitude and longitude of the address.</returns>
        Public Shared Function GetCoordinates(ByVal address As String) As Coordinate
            Dim client As WebClient = New WebClient()
            Dim uri As Uri = GetGeoCodeUri(address)
            Dim geoCodeInfo As String()
            'The first number is the status code,
            'the second is the accuracy,
            'the third is the latitude,
            'the fourth one is the longitude.

            Try
                geoCodeInfo = client.DownloadString(uri).Split(",")
                Return New Coordinate(Convert.ToDouble(geoCodeInfo(2)), Convert.ToDouble(geoCodeInfo(3)))
            Catch ex As Exception
                Return New Coordinate(0.0, 0.0)
            End Try
        End Function
    End Class

End Namespace
Aaron
Aaron on 6/3/2008 5:27 PM Excellent post - thank you very much!
john
john on 6/27/2008 2:46 PM Just learning and a general question.  Why did you create the interface?  What is the purpose of it?  What would happen if you didn't have it?

Thank you for your class and answer.
Donn
Donn on 6/27/2008 2:50 PM @John,

The reason for the interface is simply just in case someone needs to implement the same members in a differnt class, they can. I've worked at insurance companies, real estate comopanies and many other verticals that have different usages for the same members. This allows you to extract out the info. It also allows you to unit test any class that utilzes an ISpatialCoordinate without having Google Maps up and running. It serves many purposes, mainly loosley coupled reasons though.  Smile Enjoy!
etourigney
etourigney on 7/15/2008 7:53 PM I keep running into a WebException "The remote server returned an error: (407) Proxy Authentication Required." Is there some credentials that need to be past? Or is this problem with my network?

Thanks,
Eric
Donn Felker
Donn Felker on 7/15/2008 8:09 PM @Eric
You will need to set the Proxy value of the WebClient object.
msdn.microsoft.com/.../...client.proxy(VS.80).aspx

Once that is set to your your network's proxy, you should be good to go.  (that is, as long as you authenticate with the app).

Donn
Manuel
Manuel Indonesia on 9/9/2008 2:13 PM Hello, podrian mandarme un ejemplo ya desarrollado
Mono...
Mono... United States on 9/13/2008 4:21 PM Thanks for the post. It seems to be stable and i guess , you don't need a google key to run .....
Kaushik Shah
Kaushik Shah United States on 9/26/2008 5:28 PM I get the following error message when I try to build the application

The type or namespace name 'Generic' does not exist in the class or namespace 'System.Collections' (are you missing an assembly reference?)
David Bytheway
David Bytheway Netherlands on 9/29/2008 9:15 AM
If you are processing several addresses in a loop and start get error status codes, try introducing a short delay between geo-code calls in the loop (around 300ms was OK for me). This prevents the Google service getting all upset at how quickly you're asking it to work Smile.
Donn Felker
Donn Felker United States on 9/30/2008 1:13 PM @Kaushik add a reference to your project.
James
James United States on 10/8/2008 2:54 PM Thank you for great post.
I am working with a .aspx website with google maps api in it. I'm trying to load an xml file using GDownloadUrl with physical addresses without lat/lng. My xml file has records something like..
<markers>
  <dbo name="james" address1="123 ABC street, city, state, zipcode" />
</markers>
Do you think it's possible to use your geocode and convert the address into lat/lng, then put them in my GDownloadUrl so that the marker points to that address?
if so, could you please give me any idea how to approach it? I'm kinda new to C# and XML so having some problems here..
Donn Felker
Donn Felker United States on 10/17/2008 7:14 AM @James - Are you wanting to add attributes to your XML file with the lat/lon?

Therefore it would look like this:
<markers>
<dbo name="james" address1="123 ABC street, city, state, zipcode" lat="123.2112134" lon="123.455566" />
</markers>

?
Pearl
Pearl India on 10/25/2008 1:52 PM Hi,

This is an  awesome post, can I use your code on one of my work?

Thanks
Muthu
Webnomad
Webnomad Canada on 12/1/2008 3:15 PM this class is simply awesome, easy, straightforward and inspired c# developer. one of the greatest class I have seen.

thanks Donn for your great contribution.
Donn Felker
Donn Felker United States on 12/2/2008 10:37 AM @Muthu - feel free to use it.
hipero
hipero Poland on 12/3/2008 4:04 AM Thanks man!

Just joining regards by others! Great job!

I'll do some class of mine to deal with google maps Smile - now I now how.
jen
jen on 12/6/2008 7:05 AM Really cool, I'm using this for a school project!
Kevin
Kevin Canada on 2/15/2009 11:04 AM Let me add my thanks to everyone else's for this great piece of code.  Truly fantastic, Thank you very much!
Girish
Girish India on 3/5/2009 9:11 AM Dear Donn Felker,

Thanks a lot. It’s very simple code to retrieve Latitude and Longitude value.

Regards,
Girish Sarvaiya
TechIT
TechIT United States on 3/25/2009 2:51 AM Donn,
This is an awesome code.

Do you have a similar code for reverse geocoding as well?

Thanks.
trackback
blog.TBODA.com on 4/19/2009 3:56 AM Trackback from blog.TBODA.com

7 Great Free ASP.NET Controls and Libraries
Chris Paul
Chris Paul United States on 5/14/2009 12:14 PM Thank you for this!
tukang nggame
tukang nggame United States on 5/15/2009 2:20 AM woow amazing code, thanks for share this code
reena jain
reena jain India on 6/10/2009 2:16 AM hi,

greate code but it gives me an error, can you please given me some hit about this error

The remote server returned an error: (403) Forbidden.
at the line
string[] geocodeInfo = client.DownloadString(uri).Split(',');

Thanks in advance
free guitar lessons
free guitar lessons United States on 6/11/2009 6:13 PM I got same problem too.
create your own ring
create your own ring United States on 6/11/2009 6:14 PM That was good.
jayne
jayne Kenya on 6/16/2009 6:49 AM Thanks Donn.I initially had the error:"proxy authentification required" which prompted to modify getCoordinates to:
WebClient client = new WebClient();
            Uri uri = GetGeocodeUri(address);
            WebProxy wp=new WebProxy();
            wp.UseDefaultCredentials=true;
            client.Proxy=wp;
string[] geocodeInfo = client.DownloadString(uri).Split(',');
I now get the error "unable to connect to remote server". I will really appreciate your guidance.The google API key is already stored in web.config as well as test web page.Thanks
Donn
Donn United States on 6/16/2009 9:33 AM From looking at your code, I'd have to say that it still looks like a proxy issue. :\ Sorry I cant be of more assistance.
jayne
jayne Kenya on 6/18/2009 3:26 AM thanks your response Donn, i will try from my home PC(non-proxied)
Income protection
Income protection United Kingdom on 6/25/2009 11:35 AM Script doesn't seem to work in the UK

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading