CRM 2011 – How to execute Fetch XML in Javascript

[tweetmeme source=”BenHosk” only_single=false]

The chaps over at Customer Effective blog have written a really interesting blog post this week.  It’s called

Execute Fetch from Javascript in CRM 2011

They actually also wrote an interesting article about why Microsoft buying skype made sense, which you can read here, I found this interesting because I was thinking Microsoft had completely overpaid but then the article  mentions skype have 636 million users, Microsoft paid $8.6 billion and that works out at $14.70 per/user price.  Now that’s not much for each users and you would probably think that skype is going to grow the number of users it has.  You can see Microsoft bundling skype in with Xbox, CRM and office etc.  The last thought I had was Microsoft has money burning a hole in it’s pocket.  The only danger is that someone else/Google could create a skype competitor but then I thought the same about youtube when google brought that and it seems to be working out ok.

Anyway I’m here to talk about Javascript running fetch xml.  The article has some neat javascript, so neat that I read it about 4 times, thinking that is nice and simple (like all good code).

below is the code from the blog.   Brilliant blog entry and if you are interesting in CRM 2011 then you really should subscribe to the Customer Effective Blog because it is one of the best CRM blogs out there, go on go and subscribe here.

FetchUtil.js

var XMLHTTPSUCCESS = 200;
var XMLHTTPREADY = 4;

function FetchUtil(sOrg,sServer)
{
this.org = sOrg;
this.server = sServer;

if (sOrg == null) {
if (typeof(ORG_UNIQUE_NAME) != “undefined”) {
this.org = ORG_UNIQUE_NAME;
}
}

if (sServer == null){
this.server = window.location.protocol + “//” + window.location.host;
}
}

FetchUtil.prototype._ExecuteRequest = function(sXml, sMessage, fInternalCallback, fUserCallback)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open(“POST”, this.server + “/XRMServices/2011/Organization.svc/web”,(fUserCallback!=null));
xmlhttp.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
xmlhttp.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
xmlhttp.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute“);

if (fUserCallback!=null)
{
//asynchronous: register callback function, then send the request.
var crmServiceObject = this;
xmlhttp.onreadystatechange = function(){ fInternalCallback.call(crmServiceObject,xmlhttp,fUserCallback) };
xmlhttp.send(sXml);
}
else
{
//synchronous: send request, then call the callback function directly
xmlhttp.send(sXml);
return fInternalCallback.call(this,xmlhttp,null);
}
}

FetchUtil.prototype._HandleErrors = function(xmlhttp)
{
/// <summary>(private) Handles xmlhttp errors</summary>
if (xmlhttp.status != XMLHTTPSUCCESS) {
var sError = “Error: ” + xmlhttp.responseText + ” ” + xmlhttp.statusText;
alert(sError);
return true;
} else {
return false;
}
}

FetchUtil.prototype.Fetch = function(sFetchXml, fCallback)
{
/// <summary>Execute a FetchXml request. (result is the response XML)</summary>
/// <param name=”sFetchXml”>fetchxml string</param>
/// <param name=”fCallback” optional=”true” type=”function”>(Optional) Async callback function if specified. If left null, function is synchronous </param>
var request = “<s:Envelope xmlns:s=\”http://schemas.xmlsoap.org/soap/envelope/\“>”;
request += “<s:Body>”;

request += ‘<Execute xmlns=”http://schemas.microsoft.com/xrm/2011/Contracts/Services“>’ +
‘<request i:type=”b:RetrieveMultipleRequest” ‘ +
‘ xmlns:b=”http://schemas.microsoft.com/xrm/2011/Contracts“‘ +
‘ xmlns:i=”http://www.w3.org/2001/XMLSchema-instance“>’ +
‘<b:Parameters xmlns:c=”http://schemas.datacontract.org/2004/07/System.Collections.Generic“>’ +
‘<b:KeyValuePairOfstringanyType>’ +
‘<c:key>Query</c:key>’ +
‘<c:value i:type=”b:FetchExpression”>’ +
‘<b:Query>’;

request += CrmEncodeDecode.CrmXmlEncode(sFetchXml);

request += ‘</b:Query>’ +
‘</c:value>’ +
‘</b:KeyValuePairOfstringanyType>’ +
‘</b:Parameters>’ +
‘<b:RequestId i:nil=”true”/>’ +
‘<b:RequestName>RetrieveMultiple</b:RequestName>’ +
‘</request>’ +
‘</Execute>’;

request += ‘</s:Body></s:Envelope>’;

return this._ExecuteRequest(request,”Fetch”, this._FetchCallback, fCallback);
}

FetchUtil.prototype._FetchCallback = function(xmlhttp,callback)
{
///<summary>(private) Fetch message callback.</summary>
//xmlhttp must be completed
if (xmlhttp.readyState != XMLHTTPREADY)
{
return;
}

//check for server errors
if (this._HandleErrors(xmlhttp))
{
return;
}

var xmlReturn = xmlhttp.responseXML.xml;
xmlReturn = xmlReturn.replace(/</g, ‘&lt;’);
xmlReturn = xmlReturn.replace(/>/g, ‘&gt;’);

results = xmlReturn;

//return entity id if sync, or call user callback func if async
if (callback != null)
{
callback(results);
}
else
{
return results;
}
}

fetchExample.htm

<html>
<head>
<title>Fetch 2011 JavaScript Example</title>
<link rel=”stylesheet” type=”text/css” href=”/_common/styles/theme.css.aspx” />
<link rel=”stylesheet” type=”text/css” href=”/_common/styles/global.css.aspx” />
<link rel=”stylesheet” type=”text/css” href=”/_common/styles/fonts.css.aspx” />
<link rel=”stylesheet” type=”text/css” href=”/_common/styles/Dialogs.css.aspx” />

<script src=”ClientGlobalContext.js.aspx”></script>
<script src=”{pub}_FetchUtil.js”></script>

<script type=”text/javascript”>

var _oService;
var _sOrgName = “”;
var _sServerUrl = “https://{org}.api.crm.dynamics.com”;
function executeFetchCommand()
{

var sFetch = document.getElementById(‘txtFetch’).value;
_oService = new FetchUtil(_sOrgName, _sServerUrl);
var oEntity = _oService.Fetch(sFetch, myCallBack);
}

function myCallBack(results){
var sOut = “”;
sOut += “<b>XML Response</b><br />”;
sOut += results;
document.getElementById(‘dvData’).innerHTML = sOut;
}

</script>

</head>
<body>
<table style=”width: 100%; height: 100%;” cellspacing=”0″ cellpadding=”0″ border=”0″>
<tr>
<td id=”tdDialogHeader”>
<div id=”divTitle”>Executing Fetch from JavaScript in CRM 2011</div>
<div id=”divInstructions”>Enter some FetchXML to be executed against your CRM environment</div>
</td>
</tr>
<tr>
<td style=”height: 100%;”>
<div style=”padding: 14px;”>
<label>Fetch Command</label><br />
<textarea id=”txtFetch” rows=”8″ width=”100%” cols=”100″ ></textarea><br />
<input type=”Submit” value=”Fetch” onClick=”javascript:executeFetchCommand();” style=”width:100px;height:24px;”>
<div id=’dvData’ style=”width: 100%; height: 100%;”></div>
</div>
</td>
</tr>
<tr>
<td id=”tdDialogFooter”>
<table cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”100%”></td>
<td>&nbsp;<button onclick=”window.close();”>Done</button></td>
</tr>
</table>
</td>
</tr>
</table>

</body>
</html>

Now that we have our JavaScript utility and our Fetch example, we need to do a few things.

  1. We need a solution to put these two files into (feel free to add it to an existing solution or create one named whatever you like).
  2. Let’s now import the FetchUtil.js file and publish. Take note of the Publisher Prefix (the letters in front of the name).
  3. We now need to modify the fetchExample.htm file to point to this FetchUtil.js by replacing the {pub} with your Publisher Prefix (ex. “new_FetchUtil.js”).
  4. We also need to modify the _sServerUrl and change the {org} to the appropriate organization abbreviation. If you are using the onsite, you will need to change the entire URL to match accordingly.
  5. Finally, let’s upload the fetchExample.htm file and publish.

This should now bring you to a super fancy screen to paste some Fetch into.

image

Well there you have it. The next step is to parse the XML with jQuery, RegEx, traversing the nodes, or however you prefer. Hope you enjoy!

Advertisement

2 thoughts on “CRM 2011 – How to execute Fetch XML in Javascript

  1. Srikanth November 3, 2011 / 11:31 pm

    I am new to CRM 2011 and tying to get this working but blocked due to an error CrmEncodeDecode is undefined, do i need to added references to any other script where this is defined? I have IE 9, i have enabled debug scripts etc.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.