Recently in C# Category

Google driving directions in C# - Update

| 13 Comments | No TrackBacks
I've updated my GDirections C# class to allow for easier access to the actual driving directions.  The code file can be found here.  As usual, you will need your own Google Maps API key, which you can get for free at http://code.google.com/apis/maps/signup.html.  You will also need JSON.NET to parse the JSON response from Google's service.

Example code:

GDirections directions = new GDirections(startAddress, endAddress);

if (directions.IsValid)
    Response.Write(directions.RoutesHtml[0]);
else
    Response.Write("Route not valid.");


Google driving directions in C#

| No TrackBacks

ALERT! A better, more complete version of this code can be found here: http://www.sagecraft-studios.com/2008/11/google-driving-directions-in-c---update.html

This is something I've been wanting to figure out for a while. What I'll be demonstrating in this post is how to get driving directions, distances, and trip durations from Google's mapping service... without using Javascript! The demonstration code below is just that - a demonstration. It is your job, dear reader, to make a friendly, accessible interface out of the underlying code.

Note: As far as I can tell, this is undocumented. If you're using this in a production environment, I would advise writing some unit tests in case URLs change, parameters change, etc...

You will need JSON.NET referenced to deserialize the data sent from Google.

using Newtonsoft.Json;

namespace xxxx
{
    public class GDirections
    {
        private string _key = "xxxx";
        private string _output = "js";
        private string _requestFormat = "http://maps.google.com/maps/nav?key={0}&output={1}&q={2}";
        private Hashtable _data = new Hashtable();

Our underlying data. Yes, you could certainly use a generic Dictionary rather than a Hashtable. In the code above, make sure to set _key to your Google Maps API key, which can be generated here.

        /// <param name="path">A path in the format "From {a} to {b}".  Example: "From Lexington, KY to Bowling Green, KY"</param>
public GDirections(string path)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(
                string.Format(_requestFormat, _key, _output, Uri.EscapeUriString(path)));
            request.Method = "GET";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string json = reader.ReadToEnd();

            _data = readJson(new JsonReader(new StringReader(json)));
        }

In our constructor, we basically just grab the response from a web page. (or in this case, JavaScript object) Using Json.NET, we deserialize the object and somehow stick it in a Hashtable.

        private Hashtable readJson(JsonReader jreader)
        {
            Hashtable data = new Hashtable();
            while (jreader.Read() && jreader.TokenType != JsonToken.EndObject)
            {
                string key = null;
                object value = null;

                if (jreader.TokenType == JsonToken.PropertyName)
                {
                    key = (string)jreader.Value;
                    jreader.Read();
                    switch (jreader.TokenType)
                    {
                        case JsonToken.StartArray:
                            value = readJsonArray(jreader);
                            break;
                        case JsonToken.StartObject:
                            value = readJson(jreader);
                            break;
                        case JsonToken.Null:
                        case JsonToken.Undefined:
                            value = null;
                            break;
                        default:
                            value = jreader.Value;
                            break;
                    }
                }

                if (key != null)
                    data.Add(key, value);
            }
            return data;
        }

        private ArrayList readJsonArray(JsonReader jreader)
        {
            ArrayList value = new ArrayList();
            while (jreader.Read() && jreader.TokenType != JsonToken.EndArray)
            {
                switch (jreader.TokenType)
                {
                    case JsonToken.StartArray:
                        value.Add(readJsonArray(jreader));
                        break;
                    case JsonToken.StartObject:
                        value.Add(readJson(jreader));
                        break;
                    case JsonToken.Null:
                    case JsonToken.Undefined:
                        value.Add(null);
                        break;
                    default:
                        value.Add(jreader.Value);
                        break;
                }
            }
            return value;
        }
    }
}

This is the "somehow stick it in a Hashtable" (or Dictionary) part. The code really is pretty simple, but the resulting data structure is a huge mess. We end up with a nested dictionary-style object with arrays thrown in there just to keep things fun and complicated.

IDEALLY, we would want to create classes for each kind of object we get in our response. For example, Placemark, Status, Point, and Direction classes would need to be created. If even this is too much work, (which it shouldn't be if you are serious about implementing and fully using this functionality!) some more friendly accessor methods/properties shouldn't be a huge chore to do. For example, since we're using this thing just for driving time and duration, I implemented the following accessors

        public decimal DrivingMeters
        {
            get { return Convert.ToDecimal(((Hashtable)Directions["Distance"])["meters"]); }
        }

        public TimeSpan DrivingTime
        {
            get { return new TimeSpan(0, 0, Convert.ToInt32(((Hashtable)Directions["Duration"])["seconds"])); }
        }

        public decimal DrivingMiles
        {
            get { return Math.Round(DrivingMeters * (decimal)0.000621371192, 2); } // according to Google.
        }

        private Hashtable Directions
        {
            get { return (Hashtable)_data["Directions"]; }
        }

So yes, I'm basically saying take this foundation and make it your own. Make it friendly and then give it back to me. :)

Powered by Movable Type 4.21-en

Recent Comments

  • Leandro Nuñez: Hey, thanks for the great share. Is there a way read more
  • Justin: cool plugin. how would you go about creating then wiring read more
  • Anil: Nice plugin. I wanted to add some validation and stop read more
  • reigel: look cool... It would be okay if it can validate read more
  • glompix: @derby We actually do use Subverison for our version control, read more
  • derby: I use xperl, dominos, and titan bar to customize my read more
  • derby: Thanks for the script. I was looking for some AJAX read more
  • A. burton: how do you set up a search for events created read more
  • NANERPUSS: LEXINGTON GOONTUCKY :hfive: read more
  • Matt: This is a great walkthrough. I am also using the read more