Click here to Skip to main content
Click here to Skip to main content

Microsoft Dynamics CRM Vista Sidebar Gadget

By , 27 Mar 2007
 
Screenshot - 2_small.jpg

Introduction

Microsoft Dynamics CRM is a powerful program, and what sets it apart from the many other choices in the CRM application space is its tight integration to the Microsoft platform. When Vista shipped, I immediately started looking for new and exciting ways to demonstrate the value of Microsoft CRM and the Microsoft platform, and the first interesting area I discovered is gadgets. Being a true propeller head, my favorite gadget is the CPU utilization meter, and I also love the pictures slideshow gadget. I decided to create a gadget that can display the accounts and contacts from Microsoft Dynamics CRM on the user desktop.

Note that this article assumes familiarity with developing gadgets for Windows Vista. If you're new to gadgets, I suggest first reading the article: http://microsoftgadgets.com/Sidebar/DevelopmentOverview.aspx

About CRM and the gadget

While a properly implemented CRM system can be a very powerful tool, a complaint heard often is that there is so much information in the system, it is impossible to make any sense of it. The tools provided with Microsoft CRM can be designed so that the users can quickly access the important information stored in the system, and the MSCRM gadget is designed to make this process even faster.

The gadget displays the list of accounts and contacts associated with the currently logged on user (made possible by MSCRM's integration with Active Directory) and then if the user clicks an item in the list, the MSCRM record will load in a browser window.

Please note that in order to use this gadget, you must have access to a functioning MSCRM installation, and you must know the URL of your MSCRM server.

Using the code

The code itself consists of three HTML files: index.htm, accounts.html, and contacts.html. The working machinery is all JavaScript, made possible by JavaScript's ability to instantiate and access ActiveX objects. The index.html file uses JavaScript to implement a tabbed interface, one tab for Accounts, one tab for Contacts.

// Index.html
// The JavaScript for the tabs
<script type="text/javascript">
var stl=""
var bChecked=false
function handlelink(aobject)
{
  stl=aobject.href
  bChecked=(document.tabcontrol && document.tabcontrol.tabcheck.checked)? true : false
  if (document.getElementById && !bChecked)
  {
    var theTab=document.getElementById("tablist")
    var theTablinks=theTab.getElementsByTagName("A")
    for (i=0; i<theTablinks.length; i++)
      theTablinks[i].className=""
    aobject.className="current"
    document.getElementById("tabiframe").src=stl
    return false
  }
  else
    return true
}
</script>

Microsoft Dynamics CRM provides a very powerful web services API which provides access to the underlying system. So the basic idea behind this gadget was to instantiate a Microsoft.XMLHTTP ActiveX object, and then use that object to call into the MSCRM web services to retrieve the account and contact information. The challenge is that the call is not as simple as a SQL query like "select * from Accounts". We need to build an actual SOAP message. In order to do this I cheated a bit and enabled logging on my MSCRM server, made a call to the web services to retrieve the accounts and contacts, and then parsed the resulting log file to find the call I needed. For those interested, the log file is included with the downloadable source files for this project.

I then built the message thus:

// Accounts.html
// The JavaScript to build the SOAP message

// The following line must be changed to match the users MSCRM server URL
var serverUrl = "http://danubecrm:5555/mscrmservices/2006";

var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST", serverUrl + "/crmservice.asmx", false);
xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8")
xmlhttp.setRequestHeader("SOAPAction", 
    "http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple")
xmlhttp.send("<?xml version='1.0' encoding='utf-8'?>"+"\n\n"+"<soap:Envelope"+
' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"'+
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'+
' xmlns:xsd="http://www.w3.org/2001/XMLSchema">'+
' <soap:Body>' +
' <query xmlns:q1=http://schemas.microsoft.com/crm/2006/Query 
' xsi:type="q1:QueryExpression" xmlns="http://schemas.microsoft.com/crm/2006/WebServices">'+
' <q1:EntityName>account</q1:EntityName>' +
' <q1:ColumnSet xsi:type="q1:ColumnSet">' +
' <q1:Attributes>' +
' <q1:Attribute>accountid</q1:Attribute>' +
' <q1:Attribute>name</q1:Attribute>' +
' </q1:Attributes>' +
' </q1:ColumnSet>' +
' <q1:Distinct>false</q1:Distinct>' +
' </query>'+
' </soap:Body>'+
' </soap:Envelope>')

The next step is to parse the XML returned by the CRM web services call and separate the returned entities. The code below also prints out the returned entities inside HTML anchors so they are clickable.

var result = xmlhttp.responseXML.xml;
var BEs= result.split("<BusinessEntities>");
var BE = BEs[1].split("<BusinessEntity");
for (i = 0; i < BE.length; i++)
{
firstname = BE[i].indexOf("<name>")+6;
secondname = BE[i].indexOf("</name>");
firstid = BE[i].indexOf("<accountid>")+11;
secondid = BE[i].indexOf("</accountid>");
  if (BE[i].substring(firstid,secondid).length > 0 )
  {
    // The URL below must also be changed to the users MSACRM server URL
    document.writeln("<a href=\"http://danubecrm:5555/sfa/accts/edit.aspx?id=" + 
    BE[i].substring(firstid,secondid) + "\" target=\"new\"><font size=\"2px\"" +
    "name=\"verdana\">" + BE[i].substring(firstname,secondname) + "</font></a><BR>");
  }
} 

The body of the Accounts.html file is straightforward, we must call the JavaScript function we created. I called my function AccessCrmWebServices() but of course the name does not matter.

<body bgcolor="#eff3f7">
<script language="JavaScript" type="text/javascript">
AccessCRMWebServices() ;
</script>
</body> 

And that's pretty much it! Now we just deploy the gadget files to the Vista machine as described in the overview article referenced in the beginning of this article, and the gadget will be available.

History

  • v1: March 26, 2007

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

John Straumann
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralHelp with Access Denied messagemembercenvia200223 Mar '09 - 9:17 
Hi everyone,
I am trying this gadget out and I really enjoy the straight forward approach. However when I run the Open function for the ActiveXObject, it gives me the Access Denied Message. I remembered doing the same thing in some javascript customs for CRM 4. I referred to that, updated my instance to use Msxml2.XMLHTTP.
 
here is my line below:
xmlhttp.open("POST", "http://server:port/orgname/mscrmservices/2007/CrmService.asmx", false);
 
I forgot to mention this is for 4.0. I fail everytime I get to this line.
The only difference between my jscript in CRM and this is that the jscript looks like this:
 
xmlhttp.open("POST", "/mscrmservices/2007/CrmService.asmx", false);
 
Any and all help is appreciated!
 
Thanks in advance.
 
A man is remembered more for his wise words than his perverse actions.

GeneralRe: Help with Access Denied messagemembercenvia200223 Mar '09 - 9:35 
Also I have tried removing the orgname, as a bunch of examples say to do this. When I rtry to run the URL without the orgname in IE, it comes back with a CrmServiceWsdl.aspx page.
 
A man is remembered more for his wise words than his perverse actions.

GeneralMentioned in the bookmemberDeepWaters17 Dec '08 - 8:59 
Thanks for sharing, I saw your article was mentioned in the Book Creating Vista Gadgets.
 

Generalaccess problem in sidebar (msxml3.dll)membermrv7927 Oct '08 - 6:54 
Hi John,
 
very nice article and the only one that i could find to this interesting theme. i try to create an own gadget for crm and your article give me some helpful hints. But when i try to open your gadget in my sidebar, i get a access denied hint on my screen. when i open the html in my browser it works but in the sidebar it doesn't. maybe you have some ideas for this... thanks
QuestionCRM 4.0 changes?memberMember 36421128 May '08 - 6:49 
Anyone know what needs to be tweaked to make it work with CRM 4.0? haven't had any luck with changing the service calls and i'm looking for a little guidance.
 
Thanks!
AnswerRe: CRM 4.0 changes?memberJohn.Straumann31 May '08 - 12:01 
I just updated the files here:
 
http://mscrmguy.blogspot.com/
 
John.
AnswerRe: CRM 4.0 changes?memberMember 32068271 Dec '08 - 4:12 
I tried it on my machine its not working when added it in gadgets, but when I acess it through IE its working but asking me for user credentials. Do any one have the solution.
GeneralVery nice articlememberQuartz.3 Sep '07 - 9:36 
and a perfect implementation of sidebar gadget in an enterprise level application.
 
cheers.
Raj
 

Omit Needless Words - Strunk, William, Jr.

Vista? Photoshop Preview Handler

GeneralHelp for CRM Vista Gadget installmemberHans Veldman28 Jun '07 - 20:43 
Thanks for this nice gadget. I tried to install this on my vista client, however I see no contact or account information in my Gadget. Who can help me please?????? I adjusted the url's of my CRM server in the code, but nothing. Hope to hear from you soon.
 
With kind regard,
 
veldmanhans@hotmail.com
General0x80040216 soap:Server Server was unable to process requestmemberinferano22 Jun '07 - 0:16 
<b></b>I'm trying to execute the same example.
I'm using the <b>new ActiveXObject("Msxml2.XMLHTTP");</b>.
The output of the same is a Soap Error.
 
My Xml String is as
 
<code>var xml = ''+
'<? xml version=\"1.0\" encoding=\"utf-8\" ?> '+
'<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"   '+
' xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" '+
' xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> '+
' <soap:Body>'+
' <query xmlns:q1 = \"http://schemas.microsoft.com/crm/2006/Query\" '+
' xsi:type=\"q1:QueryExpression\" '+
' xmlns=\"http://schemas.microsoft.com/crm/2006/WebServices\" > '+
' <q1:EntityName>account</q1:EntityName>' +
' <q1:ColumnSet xsi:type="q1:ColumnSet">' +
' <q1:Attributes>' +
' <q1:Attribute>accountid</q1:Attribute>' +
' <q1:Attribute>name</q1:Attribute>' +
' </q1:Attributes>' +
' </q1:ColumnSet>' +
' <q1:Distinct>false</q1:Distinct>' +
' </query>'+
'</soap:Body>'+
'</soap:Envelope>';</code>
 
Then I call the open() method of the XMLHTTP object as...
 
var xmlReq = new ActiveXObject("Msxml2.XMLHTTP");
 
<code>xmlReq.Open("POST","http://10.10.10.1:5555/mscrmservices/2006/CrmService.asmx",false);
xmlReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple");
xmlReq.setRequestHeader("Content-Type","text/xml; charset=utf-8");
xmlReq.setRequestHeader("Content-Length",xml.length);
xmlReq.send(xml);</code>
 
But the result that I keep getting is a Soap Error as
 
<b>0x80040216   soap:Server Server was unable to process request</b>
 
What may be the problem???
 

 
And God said "Let there be light." [Gen 1:3]
QuestionWhat about operatorsmemberGorillaman3 Apr '07 - 14:27 
Excellent article. I've done a lot of programming through C# & .NET but javascript is a little harder.
 
What if I wanted to add in a 'like' operator to the search. You are searching for for state that is equal to WA. What if we wanted to search for states that start with W?
 
How can this be accomplished?
 
Thanks
AnswerRe: What about operatorsmemberJohn Straumann3 Apr '07 - 14:45 
Hi:
 
Thanks for the note. Where do you see the search for "WA"? I did not put any attribute search criteria in the code, it simply returns ALL the accounts and contacts owned by the currently logged on user.
 
I am not aware of a like operator in JavaScript...of course that doesn't mean it doesn't exist! Smile | :)
 
John.
GeneralRe: What about operatorsmemberGorillaman3 Apr '07 - 14:52 
My appologies, it was from a similar example.
 
If you add:
 
' '+
' name'+
'
'+
' '+
' Banks Ltd.'+
'
'+

after the you can specify only those contacts with the name Banks Ltd. I was wondering if you knew how to search for '%Bank%' and have all the names with bank come up by using a like operator?
 
Thanks
GeneralRe: What about operatorsmemberGorillaman3 Apr '07 - 14:54 
' <q1:Attributes>'+
' <q1:Attribute>name</q1:Attribute>'+
' </q1:Attributes>'+
' <q1:Values>'+
' <q1:Value xsi:type="xsd:string">Banks Ltd.</q1:Value>'+
' </q1:Values>'+
Generalsystem is undefinedmemberphgordon28 Mar '07 - 5:28 
I get an error with the crm info that says
line:46
error: 'System' is undefined
 
if I say no to the debug option it will then display the data, however the options menu is not available, I persume this is the line that sets this info.
AnswerRe: system is undefinedmemberJohn Straumann28 Mar '07 - 7:44 
Try commenting out the following lines in both Accounts.html and Contacts.html:
 
System.Gadget.settingsUI = "Settings.html";
System.Gadget.onSettingsClosed = SettingsClosed;
function SettingsClosed()
{
variableName = System.Gadget.Settings.read("variableName");
setContentText();
}
 
I was messing around with accepting a search variable...
GeneralRe: system is undefinedmembertwinsen8321 May '07 - 4:44 
Thanks for the info, did the trick for me Wink | ;-)
Any more CRM gadgets you'd recommend? I need to implement some for a demo presentation..
 
Kind regards,
Frederik
GeneralRe: system is undefinedmemberJohn Straumann21 May '07 - 8:34 
Hi Frederik:
 
If you drop me a line at jstraumann@cogeco.ca and let me know what you are tyring to demo, to whom, the business issues, etc. I will give you some pointers.
 
JS

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 27 Mar 2007
Article Copyright 2007 by John Straumann
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid