Wednesday, May 20, 2009

How to develop yahoo widgets for accessing MSCRM 4.0 data


In this blog, I’ll take you through the development of yahoo widget for accessing MSCRM 4.0 data for the on premise deployment of MSCRM. In my future blogs you may find the implementation for the hosted & Crm Live models as well.

The purpose of this article is to quickly access the MSCRM data & provide a quick navigation link to directly jump to the record in MSCRM using browser.So, what kind of data would be more relevant to a user in MSCRM? Well answer to this question depends on the role of the user but, MSCRM Activities are something which is relevant to all types of users. So, in this walkthrough we’ll retrieve the activity records of MSCRM 4.0 to display i.e fetching all the activities for the currently logged in user from the MSCRM server.

Audience Profile: The target audience should already be familiar with Yahoo widget’s development and should have little understanding of XML, JavaScript and webservice calls as well.

To start with prepare your layout for the widget by specifying some XML tags in the .kon file which is the main starting point for the widgets.
Below is an example for the kon file.

<?xml version="1.0" encoding="UTF-8"?>
<widget minimumVersion="4.0">
<settings>
<setting name="allowCustomObjectAttributes" value="true"/>
<setting name="debug" value="on"/>
</settings>
<window title="Sample Widget!">
<name>mainWindow</name>
<width>380</width>
<height>136</height>
<alignment>left</alignment>
<opacity>255</opacity>
<visible>1</visible>
<shadow>1</shadow>
<onFirstDisplay>
mainWindow.hOffset = (screen.width/2) - 114;
mainWindow.vOffset = screen.availHeight + 195;
</onFirstDisplay>
<!-- Specify images as part of layout you want to display-->
<image src="Topbar.png">
<name>top</name>
<hOffset>7</hOffset>
<vOffset>1</vOffset>
<onMouseUp>
openURL("http://www.Grapecity.com");
</onMouseUp>
</image>

<image src ="pagingFooter.png">
<name>pagingFooterImage</name>
<hOffset>7</hOffset>
<vOffset>45</vOffset>
<zindex>1</zindex>
<visible>false</visible>
</image>
</window>

<action trigger="onLoad">
<!--include the javascript file here containing code for web service calls-->
include("MSCRM_Activities.js");
</action>

<action trigger="onUnload" >
<!--Specify any action when disconnecting-->
play('Widget_Shut_disconnect.wav');
</action>

<!-- Specify the preference groups, displayed as tabs in the preferences window -->
<prefGroup>
<name>msCRM</name>
<title>MSCRM Settings</title>
<icon>Resources/CRM_Logo.gif</icon>
<order>1</order>
</prefGroup>

<!-- Specify the user configurable preferences -->
<preference name="OrganizationName">
<title>Organization Name</title>
<group>msCRM</group>
<type>Text</type>
<defaultValue>MicrosoftCRM</defaultValue>
<description>Organization's Name (Case Sensitive)
</description>
</preference>
<preference name="ServerName">
<title>Server</title>
<group>msCRM </group>
<type>Text</type>
<defaultValue>localhost:5555</defaultValue>
<description>With port number (if any). Example: ServerName:Port</description>
</preference>
</widget>


Note: The above declarations are just for example, you’ll need to design the layout for the widget.

We will be using web service calls to retrieve the xml data and that we can parse later on and display.

Below is the code to be included in the MSCRM_Activities.js file to call the MSCRM 4.0 webservices with active directory authentication.

//Poll for the target organization using discovery service and get the Url for the CrmService
function RetrieveOrganizationsRequest()
{
// Prepare the soap request 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>" +
" <Execute xmlns="http://schemas.microsoft.com/crm/2007/CrmDiscoveryService">" +
" <Request xsi:type="RetrieveOrganizationsRequest" />" +
" </Execute>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

xmlHttpRequest = new XMLHttpRequest();

//Event handler to monitor the status of the request, asynchronously
xmlHttpRequest.onreadystatechange = RetrieveOrgStatusProc;

//Fire the request asynchronously
xmlHttpRequest.open("POST", "http://"+ "localhost:5555"+"/MSCRMServices/2007/AD/CrmDiscoveryService.asmx", true);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/CrmDiscoveryService/Execute");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
}


// Monitor the status of the request
function RetrieveOrgStatusProc()
{

if ( this.readyState == 4 ) // request complete
{
if ( this.status == 200 ) // Success
{
var resultXml = this.responseXML;

var orgDetailNodes = resultXml.evaluate("soap:Envelope/soap:Body/ExecuteResponse/Response/OrganizationDetails/OrganizationDetail");

for( i=0 ; i < orgDetailNodes.length ;i++)
{
//Extract the single Business entity node item from the nodelist
var singleOrgDetailNode = orgDetailNodes.item(i);
var org = singleOrgDetailNode.evaluate("string(OrganizationName)");
if ( org == strOrganizationName )
{
crmServiceUrl = singleOrgDetailNode.evaluate("string(CrmServiceUrl)");
break;
}
}

if(crmServiceUrl=="")
{
alert("Organisation not found");
}
else
{
WhoAmIRequest();
}
}
}
}


Note: Some supported methods listed in konfabulator reference (SDK for yahoo widgets) have been used for xml document parsing. Please refer to SDK for more information.


// Retreive the MSCRM userid for the currently logged in user
function WhoAmIRequest()
{
//Prepare the xml soap request to be fired
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">" +

// This is the soap header containing your authentication information uses windows authentication in this case.
" <soap:Header>" +
" <CrmAuthenticationToken xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
" <AuthenticationType xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">0</AuthenticationType>" +
" <OrganizationName xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">"+"MicrosoftCRM" +"</OrganizationName>" +
" <CallerId xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">00000000-0000-0000-0000-000000000000</CallerId>" + " </CrmAuthenticationToken>" +
" </soap:Header>" +

//Soap body starts here
" <soap:Body>" +
" <Execute xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
" <Request xsi:type="WhoAmIRequest" />" +
" </Execute>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

xmlHttpRequest = new XMLHttpRequest();

// Event handler to monitor the status of the request, asynchronously
xmlHttpRequest.onreadystatechange = WhoAmIStatusProc;

//Fire the request asynchronously
xmlHttpRequest.open("POST", "http://" + "localhost:5555" + crmServiceUrl.substring(7).substring(crmServiceUrl.substring(7).search("/")), true);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);

// Send the request
xmlHttpRequest.send(xml);
}


// Monitor the status of the request
function WhoAmIStatusProc()
{
if ( this.readyState == 4 ) // request complete
{
if ( this.status == 200 ) // Success
{
var resultXml = this.responseXML;

// retrieve userId
UserId = resultXml.evaluate("string(soap:Envelope/soap:Body/ExecuteResponse/Response[@xsi:type='WhoAmIResponse']/UserId)");

if(UserId==null UserId=="" )
{
throw "UserId is Null";
}
// Reteive the activities for the UserId Passed
GetActivitiesRequest(UserId);

}

}

}


// Now retreive all activities for the user
function GetActivitiesRequest(UserId)
{
// Prepare the soap request
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:Header>" +
" <CrmAuthenticationToken xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
" <AuthenticationType xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">0</AuthenticationType>" +
" <OrganizationName xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">"+"MicrosoftCRM"+"</OrganizationName>" +
" <CallerId xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">00000000-0000-0000-0000-000000000000</CallerId>" +
" </CrmAuthenticationToken>" +
" </soap:Header>" +
" <soap:Body>" +
" <RetrieveMultiple xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
" <query xmlns:q1="http://schemas.microsoft.com/crm/2006/Query" xsi:type="q1:QueryExpression">" +
" <q1:EntityName>activitypointer</q1:EntityName>" +
" <q1:ColumnSet xsi:type="q1:ColumnSet">" +
" <q1:Attributes>" +
" <q1:Attribute>activityid</q1:Attribute>" +
" <q1:Attribute>activitytypecode</q1:Attribute>" +
" <q1:Attribute>prioritycode</q1:Attribute>" +
" <q1:Attribute>scheduledend</q1:Attribute>" +
" <q1:Attribute>subject</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" <q1:PageInfo>" +
" <q1:PageNumber>"+"1"+"</q1:PageNumber>" +
" <q1:Count>"+"10"+"</q1:Count>" +
" </q1:PageInfo>" +
" <q1:Criteria>" +
" <q1:FilterOperator>And</q1:FilterOperator>" +
" <q1:Conditions>" +
" <q1:Condition>" +
" <q1:AttributeName>ownerid</q1:AttributeName>" +
" <q1:Operator>Equal</q1:Operator>" +
" <q1:Values>" +
" <q1:Value xsi:type="xsd:string">"+ UserId + "</q1:Value>" +
" </q1:Values>" +
" </q1:Condition>" +
" </q1:Conditions>" +
" </q1:Criteria>" +
" </query>" +
" </RetrieveMultiple>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";
xmlHttpRequest = new XMLHttpRequest();

// Event to monitor the status of the request, asynchronously
xmlHttpRequest.onreadystatechange = ActivitiesRequestStatusProc;
//Fire the request asynchronously
xmlHttpRequest.open("POST","http://"+"localhost:5555"+crmServiceUrl.substring(7).substring(crmServiceUrl.substring(7).search("/")), true);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);

// Send the soap request
xmlHttpRequest.send(xml);

}


// Monitor the status of the request
function ActivitiesRequestStatusProc()
{

if ( this.readyState == 4 ) // completed
{
if ( this.status == 200 ) // success
{
try
{
//This is the final XML data retreived as a result of the webservice call
var resultXml = this.responseXML;

}

}
}

}


You can download the GrapeCity widget’s accessing the MSCRM 4.0 data from here
http://www.grapecity.com/india/widgets

No comments:

Post a Comment