1) Create an account in Bing map
2) Download the SDK
3) Understand the REST architecture
4) Integrate the MAP using the REST architecture
Understanding the basics of REST architecture:
What is Rest?
Representational State Transfer : REST is a way to access documents and resources using a simple remote software architecture, represented by an API. The Web (World Wide Web) is an application of the REST architecture.
This architecture is defined as follows:
- States and functions of a remote application are considered as resources.
- Each resource is only accessible using a standard address. These are hyper links. Under HTTP these are URIs.
- Resources have a standard interface in which the transactions and data types are precisely defined. XML or JSON for example, or HTML.
RESTful web services:
A RESTful web service (also called a RESTful web API) is a simple web service implemented using HTTP and the principles of REST. It is a collection of resources, with three defined aspects:
1. the base URI for the web service, such as http://example.com/resources/
2. the Internet media type of the data supported by the web service. This is often JSON, XML or YAML but can be any other valid Internet media type.
3. the set of operations supported by the web service using HTTP methods (e.g., POST, GET, PUT or DELETE).
What is JSON?
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write.
JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
These are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangable with programming languages also be based on these structures.
Ah lots of theory!, Lets start in action.Integrating the Map in CRM 2011.
1) Create a HTML resource file like the one below.(the goal is to show the Account (In CRM terms) on the map)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8" />
<title>Bing Maps REST with Jquery</title>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>
<script type="text/javascript">
/**************************************************************************
This Function is for getting an object Id from the CRM
IMP: Pass record object-type code and unique identifier as parameter
option is selected in the CRM.
By doing this you will get the context obj ID from the CRM.
Parse the URL to retrieve the GUID as in the below code.
**************************************************************************/
var objId;
function getParameters(values, unescapeValues) {
var objArr;
var parameters = new Array();
var vals = ('?' == values.charAt(0) ? values.substr(1) : values).split("&");
for (var i in vals) {
var entityIdArr;
objArr = vals[i].split("=");
if (objArr[0] == 'id') {
objId = objArr[1].substr(3, 36);
}
}
}
/**************************************************************************
This Function is for constructing the JSON object and
retrieve the result from the web service
**************************************************************************/
var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
var context = Xrm.Page.context || GetGlobalContext();
var serverUrl = context.getServerUrl();
/**************************************************************************
Constructing the JSON object and query
**************************************************************************/
function loadMapfromCRM() {
getParameters(location.search, true);
if (objId != null) {
retrieveAccountRecord(objId);
}
}
function retrieveAccountRecord(Id) {
var retrieveAccountReq = new XMLHttpRequest();
retrieveAccountReq.open("GET", ODATA_ENDPOINT + "/AccountSet(guid'" + Id + "')", true);
retrieveAccountReq.setRequestHeader("Accept", "application/json");
retrieveAccountReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveAccountReq.onreadystatechange = function () {
retrieveAccountReqCallBack(this);
};
retrieveAccountReq.send();
}
function retrieveAccountReqCallBack(retrieveAccountReq) {
if (retrieveAccountReq.readyState == 4 /* complete */) {
if (retrieveAccountReq.status == 200) {
//Success
var retrievedAccount = JSON.parse(retrieveAccountReq.responseText).d;
address = retrievedAccount.Address1_City + "," + retrievedAccount.Address1_StateOrProvince;
map.Find(null, address, null, null, 0, 1, false, false, false, false,
function (shapeLayer, results, places, moreResults, error) {
var place = places[0];
var pushpin = new VEPushpin('1', place.LatLong, //latitude, longitude
'you can place your icon resource url as you see in the webresource',
retrievedAccount.Name, //Title
address //Notes
);
//For adding the pushpins
map.AddPushpin(pushpin);
//For setting the Zoom level
map.SetCenterAndZoom(place.LatLong, 7);
});
}
else {
errorHandler(retrieveAccountReq);
alert("retrieveAccountReqCallBack function failure END");
}
}
}
</script>
</head>
<body>
<div id="map" style="position:absolute; top:0px; left:0px; width:100%; height:100%;"/>
</body>
</html>
<script type="text/javascript">
//Load the map
var map = new VEMap("map");
map.SetCredentials("YOUR CREDENTIALS<KEY>");
map.LoadMap();
//Resize the map
window.onresize = function (event) { map.Resize(document.body.clientHeight); };
window.onresize(null);
loadMapfromCRM();
</script>
2) Go to Customizations -> Web Resources -> Add a HTML new web resource and choose the one you created as above
3) Create a tab in one of the entity forms and add the Web Resource and *IMPORTANT* select an option "Pass record object-type code and unique identifier as parameter"
4) Thats all yours! you can test the MAP.
41 comments:
Thanks --- cool it worked well
Hi Chaitanya
Can you please elaborate on step 3.this is the scenerio,I want to display all my active contacts on map on the dashboard. (eventually I would like to display all the leads on the map on the dashboard.
can you please help me out . I created a HTML file with all the code. then I added it to the webresources.after that what do I do?
also is it the same procedure for displaying leads/opportunities/accounts in the map on the dashboard. and How do I test it?
THANKS
pfranklin@stueve.com
IN CONTINUATION TO THE PREVIOUS COMMENT ,I COULD GET THE MAP DISPLAYED ON THE DASHBOARD,BUT IT IS AN EMPTY MAP WITH NO ACCOUNTS PLOTTED ON IT. DO i HAVE TO ENTER THE BING MAP KEY? . I tried on line 99 in map.SetCredentials("mybingkey").IS IT RIGHT?.Also it shows 2 errors on my script. error- xrm is undefined in line 38 and error ' VE Map' is undefined
Thanks
Hey Pearse,
There are couple things you need to keep in mind.
1) As you have indicated you need to register for a developer account to get a key. Once, you have the key you need to insert in the line number 99.
2) While adding the pushpins you can even include the resource image file, which you would have added in the Web Resource.
Thanks Chaitanya. It works fine. Now I am Trying to plot the leads on a map and display it on the dashboard. Thanks Again.
Pearse
guys am trying to play around but am also getting the error VEMAP is undefined.
Pearse / Chaitanya how to resolve this.
what do i have to do with the SDK that you say to download.
please help, am not a programmer
thanks
Sebastien
Hey Sebastien,
Those are the complete steps to follow it technically.
But, you can skip that and directly use the code as is.
Quick Steps:
1) Create a bing Map Account
2) In the code replace the 'KEY' with the actual key that you have received on registration.
3) Create a resource file
4) Create a section in the form
5) Add the resource file in to the section. Keep in mind to fallow last points as discussed in the blog (#3).
Let me know if you have any issues?
Thanks,
Chaitanya...
var retrievedAccount = JSON.parse(retrieveAccountReq.responseText).d;
After this statement, if i try to display retrievedAccount.Name,
it is coming as undefined. Does anyone know why?
Couple of things that I can think of.
1) Make sure your JSON object is not null. If null, you need to download the JSON file and add the contents of the file at the top in the script section.
2) Try alerting other properties of the account like Addess, city etc...
Let me know, if you still have a problem?
Thanks,
Chaitanya...
Can u elaborate on the 1st point? what exactly should i do?
And i tried alerting other fields, it still says undefined. For some reason, JSON.parse is not working..
Please help me.. Have to submit this today.
Please, fallow the link to copy the JSON.JS contents and paste the whole thing with in the script tag.
URL: http://devpro.it/code/149.html
Thanks,
Chaitanya...
How do you go about putting the pushpin in? Also, how can you zoom the map into the location more?
HI Chaitanya,
I have been trying to work your code on contacts entity but i am only getting black map without any address. so can you guide me where i may have gone wrong here. Thanks
Hello,
There are couple of places where you need to modify the code.
1) While, building the ODATA query you need to use the right Entity name. Like, right now, you see the "accountSet" in the sample code above. you, got to change this to the entity you are referring to.
2) Second point being, you need to use the right SCHEMA NAME after retrieving result from the ODATA request.
Let me know if you need any further assitence on this?
Thanks,
Chaitanya...
HI,
Thanks for the reply, Yes from the beginning i have given my entity name what i have on my form so as well schema name, However still got the same problem as it's not showing those data on map just a blank map.Can you think of anything else??
Thanks
Webpage error details
Message: HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)
Line: 0
Char: 0
Code: 0
Hi Chaitanya.
I am getting the above error on my page on dashboard so it is displaying just blank map i suppose. can you look on this please?
Thanks
I think this link might be useful for you.
http://stackoverflow.com/questions/301484/problem-with-html-parser-in-ie
Let, me know, if this is some thing useful.
Thanks,
Chaitanya...
Hi Thanks, I have sorted out the problem for the above issue but still having the same problem with displaying all the contacts push pins on the map as it still is showing blank map. I have been trying to show contacts on the form for that i am using contact as entity name instead of AccountSet and address1_city and address1_country as the schema name what i have on my contact Form. I entered the developer key as well from my bing map account. Do i need to change anything else?? Thanks
Ok, Here are couple of check points:
1) Make sure you enter the correct Entity Name like, in your case it is contactSet (You have to use the Set word after the entity name)
2) Schema names are not same as the Name field, meaning, Name is always in lowercase but, usually schema names are Camel Case. In your case, it should be address1_City, address1_County.
Let, me know if this solves your problem.
Thanks,
Chaitanya...
HI
I have checked with the different entity and schema name but getting a blank map only/ The main thing is that it does not show any error on page so cant tell you about what;s going wrong. I think i am unable to get the records coz it;s not all showing any alert i have given in the code/
Hi one more thing wanted to ask you in relation to the above queries. Does this code work for crm 2011 online or it is for on premise version???
Thanks
Yes, It works well with the 2011 Online. Having said that, you have a new version released to work on Maps v7.0. That is pretty much similer to this.
In anycase, if you need further help on this, I need to see your code to provide you any insight on the development.
Thanks,
Chaitanya...
Hi,
For the characters limitation i cant not post the whole core here so just posted the one in which i have made changes for the entity. Please have a look. Thanks
function retrieveAccountRecord(Id) {
var retrieveAccountReq = new XMLHttpRequest();
retrieveAccountReq.open("GET", ODATA_ENDPOINT + "/contactSet(guid'" + Id + "')", true);
retrieveAccountReq.setRequestHeader("Accept", "application/json");
retrieveAccountReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveAccountReq.onreadystatechange = function () {
retrieveAccountReqCallBack(this);
};
retrieveAccountReq.send();
}
function retrieveAccountReqCallBack(retrieveAccountReq) {
if (retrieveAccountReq.readyState == 4 /* complete */) {
if (retrieveAccountReq.status == 200) {
//Success
var retrievedAccount = JSON.parse(retrieveAccountReq.responseText).d;
address = retrievedAccount.address1_City + "," + retrievedAccount.address1_Country;
alert("address");
map.Find(null, address, null, null, 0, 1, false, false, false, false,
function (shapeLayer, results, places, moreResults, error) {
var place = places[0];
var pushpin = new VEPushpin('1', place.LatLong, //latitude, longitude
'you can place your icon resource url as you see in the webresource',
retrievedAccount.Name, //Title
address //Notes
);
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Timestamp: Sat, 1 Oct 2011 14:12:28 UTC
Message: Object expected
Line: 84
Char: 26
Code: 0
URI: https://crm4.dynamics.com/%7B634530750560000000%7D/WebResources/ut_MultipleRecords?id=%7b7C938AEA-69E4-E011-860E-1CC1DE089875%7d&orglcid=1033&orgname=37ecc6d4b2134f52afbb4d81ffec1248&type=2&typename=contact&userlcid=1033
Hi Chaitanya,
I am getting the above error recently. Please have a look.
Thanks
Hello,
I have added my sample code in the contact and it started working.
Fallowing are things I did.
1) Entity Name: ContactSet (In your case it is spelled contactSet)
2) In my code, if you see the line number 72, you need to set your custom icon to show it as a pushpin. for example 'https://XXXXX.crm.dynamics.com//WebResources/expert_company.png' [NOTE: you should copy this url from the web resource, also, replace the XXXXX with your org name].
3) Setting Zoom Level: look at my code, line number 80. I have provided 7 you can replace that with 15 to view a zoomed map.
I was able to get that working.
If you still have nay issues, please send me your email, I will pass you on the web resource file.
Thanks,
Chaitanya...
Couple of more things to note:
1) I am using IE 9, When I open a contact form with map, It asks me for Show Content dialog at the bottom. I click on it view the map.
2) Name your map resource with out any root folder structure, meaning HTML/contactmap.html (If you name it like this, you need to change ClientGlobalContext.js.aspx to the same notation). I would suggest you name your map file as contactmap.html.
Thanks,
Chaitanya...
Hi Chitanya,
Thanks i have applied all the changes you have mentioned above but i presume there is something wrong in my code, coz still i am getting the above stated error of Object expected. Do i have to include any script file also like jquery.min.js and ClientGlobalContext.js.aspx as a webresource ??? It wud be a really great help if you can send your code on the following email id tandel.p86@gmail.com
Thanks
Hi Chaitanya,
I have figured out the problem and it;s working fine with the particular contact form. Thanks a million for Helping,It's the code for showing only one contact info on form. It;s not for showing all the contact records. is it??? Thanks again chaitanya
Hey No problems, I am happy that you got it working.
Yes, the sample that I have shown, is only for one contact. That being aid, we can tune our ODTAA quefry to retrieve all the Account/Contact records, by NOT specifying the GUID of an entity record.Please, refer the sample as in the below code.
retrieveAccountReq.open("GET", ODATA_ENDPOINT + "/AccountSet", true);
Let me know, if you have any questions?
Thanks,
Chaitanya...
Hello Chaitanya,
Yes i have made it changes in the line you have specified above and put it on the Dashboard to show the map but i guess there is some problem on displaying on dashboard for all records? Do we need to make changes anywhere else on the code to display on the dashboard??
Thanks
Hi, Chaitanya
How do I add fields to the code? EX: Add zipcode, address so i can pull back all the info, also how to plot all accounts on the map?
Hello,
Here is the solution,
1) To pull back all the attributes:
By default, the retrieved record should contain all the attributes, you need to access them by their SCHEMA NAME(Very important, usually these are in Camel Case).
If you want to select only few fields and do some sort of filtering, fallow the below sample query(Please change the ORGNAME to your organization name and change the ENTITYNAME to the entity you are requesting, example: AccountSet and add the appropriate fields in the select statement).
https://ORGNAME.crm.dynamics.com//XRMServices/2011/OrganizationData.svc/ENTITYNAMESet/$top=1&$filter=statecode/Value eq 0 &$select=zipcode,statuscode, address1_line1,telephone&$orderby=name desc
2) If you do not pass the entity GUID to an ODATA Query, you can retrieve all the accounts. I think, I have already explained in one of the converzation above.
Let me know, if you still need any help on this?
Thanks,
Chaitanya...
I am getting map correctly but it is always pointed to specific location in United states. I am using exact same code as mentioned in the blog.
WHen i put in Account form City, State as = Dublin and Country=Ireland
Nothing changes in the map even I save the form.
Any idea why i am getting same map?
Thanks in advance
You can probably have a look at the list on the Geographical coverage.
Bing Maps Geographic Coverage
http://msdn.microsoft.com/en-us/library/dd435699.aspx
Thanks,
Chaitanya...
Thanks Chaitanya for coming back on my query.
I am in middle of dublin, Ireland, I do not think I should have issue with the coverage.I am using Dynamics CRM 2011.
Also few things to mention:
1. When i use the code in the web resourcde and try to click Ok I get an error about 'VEMap' is undefined.
2. I used address = retrievedAccount.address1_City + "," + retrievedAccount.address1_Country; alert(address);
a
My alert never appears though?
Any help please?
Ok, there are two ways I look at this issue,
1) The "VEMap" is not getting loaded, as a result the further code is not getting executed and for the same reason you are not getting any alert windows appearing.
2) Do you have the Bing map Key set in the code? also, try to put a debugger and you could basically debug the JavaScript code to identify the real cause for it, I think, I have it in one of my blog on client side debugging.
Thanks,
Chaitanya...
thanks for coming back.
I have used the key in:
map.SetCredentials("aaaa");
and i generated the bing key using:
Trial / Not-for-profit
Can you point me to the debugger link if you have somewhere in ur blog if possible please?
Originally i remember i just changed following line as i was getting error on Xrm so just added following to it:
var context = Xrm.Page.context || GetGlobalContext();
to
var context = window.parent.Xrm.Page.context || GetGlobalContext();
Here is a link that you can make use of:
http://chaitanyaprasadtk.blogspot.in/2013/01/javascript-debugging.html
Thanks,
Chaitanya...
Thanks Chaitanya - i was on some other project and never debugged it. Ok so finally i debugged it and it appears at 'VEMap' is undefined.
I am not sure what to do now :(
I checked all browser scripting and all are enabled.
Any help?
Post a Comment