In this article, Microsoft CRM developers will make you learn about easy steps to get contact/account geocoding data from Google’s API. You will learn about this thing when you try to GEO locate an address on a custom entity or other native entity.

Dynamics CRM has native integration with Bing Maps, particularly on account, contact and lead entities.

But what happens when we are trying to GEO locate an address on a custom entity or a other native entity?And even when we already have license for Google Maps and not for Bing Maps?

Well, in this article I’ll show you a way to develop an alternative to the proposal by Microsoft.

Solution

The solution is to persist a direction on a target record and using Google´s API functions in combination of Dynamics CRM extensions, get the latitude and longitude of it and then use them where we wanted.

The architecture consist of a:

Workflow

Custom Workflow Activity

Some address fields on target entity

Customize our entity

First, we could create or add some fields to an entity (the entity to which we want to get the “latitude” and “longitude” based on an address)

For example:

Address_Street

Address_City

Address_State

Address_PostalCode

Address_Country

Create a workflow

For this example, you could create a process that is triggered to an update of any of the above fields generated. This process call to a Custom workflow activity that receives this fields as parameters and this others that will need for get data from Google´s API:

GoogleMapsGeoCodeURL

In resume, our Custom Workflow Activity interface should look as follows:

[Input("Google Maps Geocode URL: ")] [Default("http://maps.googleapis.com/maps/api/geocode/xml?address=")] publicInArgument<string>GoogleMapsGeoCodeURL { get; set; } [Input("Address Street: ")] [RequiredArgument] publicInArgument<string>Address_Street { get; set; } [Input(" Address City: ")] [RequiredArgument] publicInArgument<string>Address_City { get; set; } [Input("Address State: ")] [RequiredArgument] publicInArgument<string>Address_State { get; set; } [Input("Address PostalCode: ")] [RequiredArgument] publicInArgument<string>Address_PostalCode { get; set; } //ISO Country Code - http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 [Input("Address Country: ")] [Default("US")] [RequiredArgument] publicInArgument<string>Address_Country { get; set; } [Output("Geocode Quality (")] publicOutArgument<String>GeocodeQuality { get; set; } [Output("Latitude")] publicOutArgument<double>Address_Latitude { get; set; } [Output("Longitude")] publicOutArgument<double>Address_Longitude { get; set; } [Output("GeoCodeResult")] publicOutArgument<string>GeoCode_Result { get; set; }

In the “Latitude” and “Longitude” fields we return information consulted to persist in our organization.

The “GeoCodeResult” is a flag field to allows our workflow to understand if the callback was ok or not.

Request Google´s API to get geolocation data

So, we have our organization with new fields, we have our workflow and custom workflow activity prepared. We just need to complete a few lines of code to be responsible for calling the Google´s Maps Api, send certain parameters and process the response to obtain the latitude and longitude.

How can we do that?

Let me create some private c# methods to our Custom Workflow Activity:

BuildRequestQuery CreateRequest MakeRequest ProcessResponse

BuildRequestQuery

As you know, we perform encoding of the parameters when we want to pass through anurl. This feature will allow us to format some parameters:

private string BuildRequestQuery(string street, string city, string state, string country, string postalCode) { stringlocationQuery = string.Empty; // Check if Street address is empty if (!string.IsNullOrEmpty(street)) locationQuery += System.Uri.EscapeUriString(street) + ", "; //Check to see if City is Empty if (!string.IsNullOrEmpty(city)) locationQuery += System.Uri.EscapeUriString(city) + ", "; //Check to see if State is Empty if (!String.IsNullOrEmpty(state)) locationQuery += System.Uri.EscapeUriString(state) + ", "; //Check if PostalCode is not empty. I'm not doing a number check, since postalCode outside USA is alphanumeric. if (!string.IsNullOrEmpty(postalCode)) locationQuery += System.Uri.EscapeUriString(postalCode) + ", "; //Minimum amt of data. You need at least PostalCode to provide a lat/long. if (!string.IsNullOrEmpty(country)) locationQuery += country + ", "; returnlocationQuery; }

Create Request:

It is responsible for processing the parameters obtained from CRM (address) to prepare a string to be sent to the API. It should looks like:

private string CreateRequest(string geocodeURL, string queryString) { stringUrlRequest = geocodeURL + queryString + "&sensor=false"; return (UrlRequest); }

MakeRequest

This function shall be responsible to invoke the Google´s API by sending our request

privateXmlDocumentMakeRequest(string requestUrl) { try { HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest; HttpWebResponse response = request.GetResponse() as HttpWebResponse; XmlDocumentxmlDoc = new XmlDocument(); xmlDoc.Load(response.GetResponseStream()); return (xmlDoc); } catch (Exception e) { Console.WriteLine(e.Message); Console.Read(); return null; } }

ProcessResponse

Finally,This function interprets the response nodes of the Google´s response, parsing the XML and obtaining the latitude and longitude in order to return to CRM!

private void ProcessResponse(XmlDocumentlocationsResponse) { //initialize before the assignments latitude = 0; longitude = 0; result = string.Empty; //Get Status XmlNodegeoCodeStatus = locationsResponse.SelectSingleNode(".//GeocodeResponse/status"); //get the first Point node from GoodElements if (geoCodeStatus.InnerText == "OK") { //TODO: You can fetch the the node where you want to have a proper XmlNodelatElement = locationsResponse.SelectSingleNode(".//GeocodeResponse/result/geometry/location/lat"); XmlNodelongElement = locationsResponse.SelectSingleNode(".//GeocodeResponse/result/geometry/location/lng"); XmlNodequalityElement = locationsResponse.SelectSingleNode(".//GeocodeResponse/result/geometry/location_type"); latitude = Convert.ToDouble(latElement.InnerText); longitude = Convert.ToDouble(longElement.InnerText); geocodeQuality = qualityElement.InnerText; } }

This article resolves the purpose of getting knowledge how to source contact/account geocoding data from Google’s API. Now Microsoft CRM developers India can try and experiment leveraging this tutorial.

Conclusion

With this solution, you can get geolocated data with the Google API using custom fields to store addresses. All you have to do is a workflow process + custom workflow activity with this code. Do not forget to return and persist those fields (lat& long) in the entity then it can will be used from any application that mark these coordinates on a map!