|
 Monday, March 12, 2007
« aspnet_wp.exe could not be started? | Main | Notepad++ Shortcuts - Vista 64bit Update... »

C# Google Geocode (Latitude and Longitude) Class

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
#    Comments [22] |
Tuesday, July 17, 2007 4:18:26 PM (Eastern Standard Time, UTC-05:00)
Hey I'm trying to get this to work in vb.net. Can you help me convert it?
Jason
Tuesday, July 17, 2007 4:47:23 PM (Eastern Standard Time, UTC-05:00)
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. :)

Sunday, August 05, 2007 3:04:45 AM (Eastern Standard Time, UTC-05:00)
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 :-)
Monday, August 13, 2007 2:17:19 AM (Eastern Standard Time, UTC-05:00)
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???
Suman
Monday, August 20, 2007 8:46:06 PM (Eastern Standard Time, UTC-05:00)
Thank You. This was awesome!
Monday, August 27, 2007 10:22:20 AM (Eastern Standard Time, UTC-05:00)
This is awesome. Saved me so much time! Thanks dude!!!
Habib Haider
Friday, September 14, 2007 1:16:02 PM (Eastern Standard Time, UTC-05:00)
// 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
friend
Saturday, October 06, 2007 11:06:19 AM (Eastern Standard Time, UTC-05:00)
YOU'RE MY HERO!!! This class is awesome.
Janessa Allen
Wednesday, October 17, 2007 2:02:44 AM (Eastern Standard Time, UTC-05:00)
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?
prabha
Wednesday, October 17, 2007 9:56:02 AM (Eastern Standard Time, UTC-05:00)
Prabha,
It looks like your host probably has the WebPermission (http://msdn2.microsoft.com/en-us/library/system.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!
Tuesday, December 11, 2007 7:30:39 PM (Eastern Standard Time, UTC-05:00)
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
Thursday, March 13, 2008 5:57:28 PM (Eastern Standard Time, UTC-05:00)
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
Greg
Friday, March 14, 2008 12:35:43 AM (Eastern Standard Time, UTC-05:00)
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. :)

Thanks for reading!
Tuesday, April 08, 2008 3:39:55 AM (Eastern Standard Time, UTC-05:00)
Can i get List of Latitude and Longitude From List address. and just one request
son nguyen
Tuesday, April 08, 2008 8:57:05 AM (Eastern Standard Time, UTC-05:00)
@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.
Wednesday, May 07, 2008 12:14:29 PM (Eastern Standard Time, UTC-05:00)
Nice work!

I have a question, what was the reason for defining ISpatialCoordinate interface?
Thanks.
Monday, June 02, 2008 9:14:40 AM (Eastern Standard Time, UTC-05:00)
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
Samba
Tuesday, June 03, 2008 1:27:27 PM (Eastern Standard Time, UTC-05:00)
Excellent post - thank you very much!
Aaron
Friday, June 27, 2008 10:46:53 AM (Eastern Standard Time, UTC-05:00)
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.
john
Friday, June 27, 2008 10:50:15 AM (Eastern Standard Time, UTC-05:00)
@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. :) Enjoy!
Tuesday, July 15, 2008 3:53:42 PM (Eastern Standard Time, UTC-05:00)
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
etourigney
Tuesday, July 15, 2008 4:09:56 PM (Eastern Standard Time, UTC-05:00)
@Eric
You will need to set the Proxy value of the WebClient object.
http://msdn.microsoft.com/en-us/library/system.net.webclient.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
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview