martes, 5 de marzo de 2013

API Google Maps y ASP.NET C#

Buen dia a todos, el dia de hoy vamos a trabajar con el API de  Google Maps utilizando los Web Services que este ofrece.

Es muy comun la utilizacion de esta Api solo con Javascript o jQuery, pero esta vez trabajaremos con ASP.NET con lenguaje C#, cabe mencionar que solo vamos a obtener datos y realizar consultas en base a la informacion enviada.

Empezamos creando una clase que contendrá los metodos para obtener Directions ó Geocoder de algun lugar sobre la faz de la tierra, pero antes listo las herramientas o tecnologias a utilizar:

- Newtonsoft.Json .- Utilizado para serializar o deserializar Objetos para este caso; la respuesta del api en formato json y asi tener mas control sobre el resultado.

- Documentacion Web Services - Api Google Maps .- Aqui pueden encontrar toda la documentacion con la que vamos a trabajar, que son: Google Directions API y Google Geocoding API

Envio de Solicitud a Google Maps
Empezamos con el método que envia la solitud a Google Maps:
    public class WebUtil
    {
        public WebUtil()
     {
      //
      // TODO: Add constructor logic here
      //
     }

        /// 
        /// Envia solicitud a Google Maps
        /// 
        /// Url
        /// Resultado de la solicitud en string
        public static string WebRequestString(string url)
        {
            string strReturn = null;
            WebResponse response = null;            
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET";
                response = request.GetResponse();
                if (response != null)
                {                   
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            strReturn = streamReader.ReadToEnd();
                        }
                    }
                }
                return strReturn;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        
        public static String Encode(string strName)
        {
            return System.Web.HttpUtility.UrlEncode(strName);
        }
    }

Google Maps Directions v3.0
Ahora seguimos con las propiedades del objeto de respuesta que recibimos de google maps.

    public class DirectionResponse
    {
        public string Status { get; set; }
        public DirectionRoute[] Routes { get; set; }
    }

    public class DirectionRoute
    {
        public string Summary { get; set; }
        public string Copyrights { get; set; }
        public DirectionLeg[] Legs { get; set; }
    }

    public class DirectionLeg
    {
        public DirectionValues Distance { get; set; }
        public DirectionValues Duration { get; set; }
        public string Start_Address { get; set; }
        public string End_Address { get; set; }
        public DirectionLocation Start_Location { get; set; }
        public DirectionLocation End_Location { get; set; }

        public DirectionStep[] Steps { get; set; }
    }

    public class DirectionStep
    {
        public string Travel_Mode { get; set; }
        public string Html_Instructions { get; set; }
        public DirectionValues Distance { get; set; }
        public DirectionValues Duration { get; set; }
        public DirectionLocation Start_Location { get; set; }
        public DirectionLocation End_Location { get; set; }
    }

    public class DirectionValues
    {
        public decimal Value { get; set; }
        public string Text { get; set; }
    }

    public class DirectionLocation
    {
        public decimal Lat { get; set; }
        public decimal Lng { get; set; }
    }

Enseguida creamos una clase con el nombre Directions, para agregar los metodos de envio de datos a google maps y obtener los resultados.
 
public class Directions
{
}

Dentro de esta clase agregamos una variable publica que contendrá la url donde esta alojada el web services para Directions:
 
public static String Google_Directions_Api_Url = "http://maps.google.com/maps/api/directions/";

Ahora agregamos dentro de la clase Directions el siguiente método que es el encargado de enviar la solicitud:
 
        /// 
        /// Envia solicitud con los datos requeridos por Google Maps.
        /// 
        /// json o xml
        /// Origen de la ruta. Ejem: Saltillo, Coahuila
        /// Destino de la ruta. Ejem: Monterrey, NL
        /// Puntos intermedios. Ejem: Santa Catarina, NL
        /// false/true
        /// resultado en string segun respuesta de google o null si hubo algun error.
        public static String SendRequest(string format, string origin, string destination, string waypoints, bool sensor)
        {
            String sendQuery = Google_Directions_Api_Url + format;

            sendQuery += "?origin=" + WebUtil.Encode(origin);
            sendQuery += "&destination=" + WebUtil.Encode(destination);
            if (waypoints != null && waypoints.Length > 0)
            {
                sendQuery += "&waypoints=" + WebUtil.Encode(waypoints);                
            }
            sendQuery += "&sensor=" + ((sensor) ? "true" : "false");            
            sendQuery += "&language=Es";

            return WebUtil.WebRequestString(sendQuery);
        }

Enseguida dentro de la misma clase, agregamos el siguiente método que es el encargado de recibir la respuesta y convertirlo al objeto DirectionResponse, la clase JsonConvert se obtiene agregando como referencia Newtonsoft.Json
 
        /// 
        /// Recibe y Convierte respuesta de google maps de string a DirectionResponse, que contiene las propiedades solo para formato json.
        /// 
        /// Origen de la ruta. Ejem: Saltillo, Coahuila
        /// Destino de la ruta. Ejem: Monterrey, NL
        /// Puntos intermedios. Ejem: Santa Catarina, NL
        /// false/true
        /// DirectionResponse
        public static DirectionResponse GetDirectionResponseJson(string origin, string destination, string waypoints, bool sensor)
        {
            string strResult = SendRequest("json", origin, destination, waypoints, sensor);

            DirectionResponse drDirections = null;
            try
            {
                if (strResult != null)
                {
                    drDirections = JsonConvert.DeserializeObject(strResult);
                }
                return drDirections;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

Ahora viene lo bueno, trabajando de antemano en un proyecto ASP.NET en Visual Studio agregamos un control aspx (Directions.aspx); dentro de este aspx agregamos Origen y Destino para este caso utilizo 4 dropdowlist, 2 para estado y municipio origen y 2 para estado y municipio destino, y un label para mostrar el resultado, quedando el diseño como se muestra en la imagen:
Tambien pueden utilizar solo 2 textbox que es mas facil, capturando en ellas el origen y destino de la ruta, y un label para mostrar el resultado, como se muestra en la siguiente imagen:
Ahora en el evento onclick del boton Obtener Ruta agregamos el siguiente código:

 
        protected void btnObtenerRuta_Click(object sender, EventArgs e)
        {
            string strResult = string.Empty;

            string strOrigen = txtOrigen.Text;
            string strDestino = txtDestino.Text;

            //Enviamos solicitud para obtener el objeto DirectionResponse. 
            GoogleMapsApi.DirectionResponse directionsResponse = GoogleMapsApi.Directions.GetDirectionResponseJson(strOrigen, strDestino, null, false);

            if (directionsResponse != null)
            {
                if (directionsResponse.Status == "OK")
                {
                    if (directionsResponse.Routes.Length > 0)
                    {
                        for (int i = 0; i < directionsResponse.Routes[0].Legs.Length; i++)
                        {
                            GoogleMapsApi.DirectionLeg directionLegItem = directionsResponse.Routes[0].Legs[i];

                            //Obtenemos datos generales de la ruta trazada por el Api de Google Maps.
                            strResult += "Ruta de: " + directionLegItem.Start_Address + " a " + directionLegItem.End_Address
                                + " Distancia: " + directionLegItem.Distance.Text + " Duración: " + directionLegItem.Duration.Text;

                            //Obtenemos las intrsucciones para mostrar en pantalla.
                            strResult += "

Instrucciones:";
                            for (int c = 0; c < directionLegItem.Steps.Length; c++)
                            {
                                GoogleMapsApi.DirectionStep directionStepItem = directionLegItem.Steps[c];
                                strResult += "
" + (c + 1).ToString() + " .- " + directionStepItem.Html_Instructions;
                            }
                        }
                    }
                }
                else
                {
                    strResult += "
JSON response failed, status is " + directionsResponse.Status;
                }
            }
            lbResult.Text = strResult;
        }

Cabe mencionar que el resultado devuelto por la clase DirectionResponse puede ser tratada de la forma que gusten, pueden agregar los registros (Routes, Legs y Steps) a un datatable para mostrarlos en un gridview o cualquier control que soporte datos.

Una vez grabado el proyecto lo ejecutamos, capturamos o seleccionamos el origen y destino como se muestra en las siguientes imagenes:


Enseguida damos clic en Obtener Ruta y obtendremos el resultado como se muestra en la imagen:
El Api de Google Maps tiene muchas funcionalidades que se pueden adaptar a cualquier lenguaje de programación, se pueden documentar en la liga que les dejé al principio. Mas adelante veremos el código para utilizar el web service Geocoding de Google Maps.

Ah sido todo por hoy, espero les haya servido, cualquier duda o comentario, es bien recibido.

Saludos a todos, Dios los bendiga!

1 comentario:

  1. Hola amigo, Gracias por el aporte; Crees que puedas subir el proyecto completo, hay unas cosas que las entiendo, por favor, gracias.
    Saludos, hugo

    ResponderEliminar