Click here to Skip to main content
15,884,991 members
Articles / Desktop Programming / WPF
Tip/Trick

How to Open a Place in Google Maps Without a Dev. Key

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
21 Apr 2016CPOL3 min read 9.1K   10   1
I am going to demonstrate how to convert an address to a latitude and longitude using Google Maps Geocode. Then take the latitude and longitude and build a Uri that opens that place in Google Maps.

Introduction

Developers looking to use some of the advanced features of Google Maps must use the SDK and obtain a Developers key. You can do that here. In my case, all I would like to do is take an address and let a user open that address in Google Maps in either street or earth view.

Background

I started researching what it would take to incorporate Google Maps into existing software. After looking into what I needed and what options are available, I found that the SDK was overkill for what I'm trying to do. So here is a simple approach.

Using the Code

I was able to get the code to work in Visual Studio 2010, so any version later than that will work. I created my new project as a WPF but that was just a personal preference. A major time saver was this class for GoogleGeoCodeResponse found here that I will use to deserialize a Json response into. So let's start by opening a new WPF project in Visual Studio and add the following classes to your project.

public class GoogleGeoCodeResponse
{

    public string status { get; set; }
    public results[] results { get; set; }

}

public class results
{
    public string formatted_address { get; set; }
    public geometry geometry { get; set; }
    public string[] types { get; set; }
    public address_component[] address_components { get; set; }
}

public class geometry
{
    public string location_type { get; set; }
    public location location { get; set; }
}

public class location
{
    public string lat { get; set; }
    public string lng { get; set; }
}

public class address_component
{
    public string long_name { get; set; }
    public string short_name { get; set; }
    public string[] types { get; set; }
}

Now we need some way to feed in our address we would like to search for. If you created a WPF project, add a textbox and a button to your main window. Then add a click event to the button. Now you can just type your address into the textbox and use the click event of the button to feed that text into our method that will query Google Maps Geocode API. We do need to replace two spaces in our address with the "+" char, so change the click event to the following:

C#
private void button1_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text = textBox1.Text.Trim();
            var searchString = textBox1.Text.Replace(" ", "+");
            GetGeoCords(searchString);
        }

GetGeoCords(string) is the method we'll deploy next. So let's add the empty method now like below:

C#
public void GetGeoCords(string searchString)
        {

        }

For the purpose of this article, I've kept all my code in one place, MainWindow.xaml.cs. This is not how I would do it in a real world scenario. I would suggest separating your code following the MVVM pattern you can find here.

Now add these using statements

C#
using System.Net;
using System.IO;
using System.Diagnostics; 

Now your MainWindow.xaml.cs should look like the following:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net;
using System.IO;
using System.Diagnostics;

namespace WpfApplication7
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        public void GetGeoCords(string searchString)
        {
           
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text = textBox1.Text.Trim();
            var searchString = textBox1.Text.Replace(" ", "+");
            GetGeoCords(searchString);
        }
    }

    public class GoogleGeoCodeResponse
    {
        public string status { get; set; }
        public results[] results { get; set; }
    }

    public class results
    {
        public string formatted_address { get; set; }
        public geometry geometry { get; set; }
        public string[] types { get; set; }
        public address_component[] address_components { get; set; }
    }

    public class geometry
    {
        public string location_type { get; set; }
        public location location { get; set; }
    }

    public class location
    {
        public string lat { get; set; }
        public string lng { get; set; }
    }

    public class address_component
    {
        public string long_name { get; set; }
        public string short_name { get; set; }
        public string[] types { get; set; }
    }
}

At this point, we have not used our classes. If we run the project, the rest of our code works as follows.

First, we get our Main Window with an empty textbox and a button. I made no changes other than adding the textbox and button, so mine looks like this:

Image 1

Adding the address "101 sw 3rd st MyTown FL 34970" and clicking the button formats the text to "101+sw+3rd+st+MyTown+FL+34970" and passes it to our GetGeoCords method.

Getting geocode via json

Now that our address is in a Uri friendly format, change our GetGeoCords method to the following:

C#
public void GetGeoCords(string searchString)
        {
            var request = WebRequest.Create(new Uri
		("http://maps.google.com/maps/api/geocode/json?address=" + 
		searchString + "=false")) as HttpWebRequest;
            request.Headers.Clear();
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";

            using (var response = request.GetResponse() as HttpWebResponse)
            {
                var reader = new StreamReader(response.GetResponseStream());
                var output = reader.ReadToEnd();
            }           
        }

The preceeding change to the GetGeoCords method creates a HttpWebRequest to the Uri that corresponds to our address. Then, use a Get request to receive a Json response containing our search results. Now the variable output contains that response but in string format. The next step is to Json deserialize output in the format of GoogleGeoCodeResponse class.

From the Package Manager Console, run the following command:

Install-Package Newtonsoft.Json 

Then, add using Newtonsoft.Json; And then, let's change the GetGeoCords method again to the following:

C#
public void GetGeoCords(string searchString)
        {
            var request = WebRequest.Create(new Uri("http://maps.google.com/maps/api/geocode/json?address=" + searchString + "=false")) as HttpWebRequest;
            request.Headers.Clear();
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";

            using (var response = request.GetResponse() as HttpWebResponse)
            {
                var reader = new StreamReader(response.GetResponseStream());
                var output = reader.ReadToEnd();
                var GetString = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(output);
                if (GetString.status == "OK")
                {                                        
                    //  Earth View
                    Process.Start("http://www.google.com/maps/place/" + 
                    GetString.results[0].geometry.location.lat + "," + 
                    GetString.results[0].geometry.location.lng + "/@" + 
                    GetString.results[0].geometry.location.lat + "," + 
                    GetString.results[0].geometry.location.lng + "," + 
                    "143m/data=!3m1!1e3!4m2!3m1!1s0x0:0x0");

                    //  Street View
                    Process.Start("http://www.google.com/maps/place/" + 
                    GetString.results[0].geometry.location.lat + "," + 
                    GetString.results[0].geometry.location.lng + "/@" +
                    GetString.results[0].geometry.location.lat + "," + 
                    GetString.results[0].geometry.location.lng + "," +
                    "19z/data=!4m2!3m1!1s0x0:0x0");
                }
                else MessageBox.Show(GetString.status);
            }           
        }

Now, we have deserialized output into GetString as type GoogleGeoCodeResponse. If the status is "OK", we open a Earth View and Street View in the default browser. If the status is anything other than "OK", we raise a MessageBox with the status code.

Improving the Code

There's lots of room to improve on this project but this accomplishes what we set out to do. In my production code, I allow the user to select which address to use when there are multiple search returns. I have included below a class for converting the lat. and long. from decimal to degrees minutes seconds, and also auto generate the Street and Earth View Uris automatically.

C#
public class MapCoordinate
   {
       public MapCoordinate()
       {

       }
       public MapCoordinate(GoogleGeoCodeResponse responseCode)
       {
           LatitudeDecimal = double.Parse(responseCode.results[0].geometry.location.lat);
           LongitudeDecimal = double.Parse(responseCode.results[0].geometry.location.lng);
       }

       public Uri EarthViewUri
       {
           get
           {
               return new Uri("http://www.google.com/maps/place/" +
               LatitudeDecimal + "," + LongitudeDecimal + "/@" +
               LatitudeDecimal + "," + LongitudeDecimal + "," +
               "143m/data=!3m1!1e3!4m2!3m1!1s0x0:0x0");
           }
           private set { throw new Exception(); }
       }

       public Uri StreetViewUri
       {
           get
           {
               return new Uri("http://www.google.com/maps/place/" +
               LatitudeDecimal + "," + LongitudeDecimal + "/@" +
               LatitudeDecimal + "," + LongitudeDecimal +
               "," + "19z/data=!4m2!3m1!1s0x0:0x0");
           }
           private set { throw new Exception(); }
       }

       private double _LatitudeDecimal;
       public double LatitudeDecimal
       {
           get { return _LatitudeDecimal; }
           set
           {
               if (_LatitudeDecimal != value)
               {
                   _LatitudeDecimal = value;
                   SetLatitude(value);
               }
           }
       }
       private double _LongitudeDecimal;
       public double LongitudeDecimal
       {
           get { return _LongitudeDecimal; }
           set
           {
               if (_LongitudeDecimal != value)
               {
                   _LongitudeDecimal = value;
                   SetLongitude(value);
               }
           }
       }

       public int LatitudeDegrees { get; private set; }
       public int LatitudeMinutes { get; private set; }
       public double LatitudeSeconds { get; private set; }

       public int LongitudeDegrees { get; private set; }
       public int LongitudeMinutes { get; private set; }
       public double LongitudeSeconds { get; private set; }

       private void SetLongitude(double longitude)
       {
           LongitudeDecimal = longitude;
           LongitudeDegrees = (int)LongitudeDecimal;
           LongitudeMinutes = (int)((LongitudeDecimal - LongitudeDegrees) * 60);
           LongitudeSeconds = Math.Round(((((LongitudeDecimal - LongitudeDegrees) * 60) -
           LongitudeMinutes) * 60), 2);
       }
       private void SetLatitude(double latitude)
       {
           LatitudeDecimal = latitude;
           LatitudeDegrees = (int)LatitudeDecimal;
           LatitudeMinutes = (int)((LatitudeDecimal - LatitudeDegrees) * 60);
           LatitudeSeconds = Math.Round(((((LatitudeDecimal - LatitudeDegrees) * 60) -
           LatitudeMinutes) * 60), 2);
       }
   }

If you add the preceeding class to your project, you can modify the GetGeoCords method to the following.

C#
var request = WebRequest.Create
(new Uri("http://maps.google.com/maps/api/geocode/json?address=" +
searchString + "=false")) as HttpWebRequest;
        request.Headers.Clear();
        request.Method = "GET";
        request.ContentType = "application/x-www-form-urlencoded";

        using (var response = request.GetResponse() as HttpWebResponse)
        {
            var reader = new StreamReader(response.GetResponseStream());
            var output = reader.ReadToEnd();
            var GetString = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(output);
            if (GetString.status == "OK")
            {
                var MapCords = new MapCoordinate(GetString);

                //MainBrowser.Navigate(nUri);
                Process.Start(MapCords.StreetViewUri.ToString());
                Process.Start(MapCords.EarthViewUri.ToString());
            }
            else MessageBox.Show(GetString.status);
        }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionstrange request Pin
Thornik25-Apr-16 9:53
Thornik25-Apr-16 9:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.