Friday, 5 July 2013

CRM 2011 Javascript Fetch XML synchronous or asynchronous using FetchUtil


Using helper function to execute FetchXML request is great.

FetchUtil.js:

/// <summary>FetchUtil.js</summary>
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");
    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" ' +
'<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 sFetchResult = xmlhttp.responseXML.selectSingleNode("//a:Entities").xml;
    var resultDoc = new ActiveXObject("Microsoft.XMLDOM");
    resultDoc.async = false;
    resultDoc.loadXML(sFetchResult);
    //parse result xml into array of jsDynamicEntity objects
    var results = new Array(resultDoc.firstChild.childNodes.length);
    for (var i = 0; i < resultDoc.firstChild.childNodes.length; i++) {
        var oResultNode = resultDoc.firstChild.childNodes[i];
        var jDE = new jsDynamicEntity();
        var obj = new Object();
        for (var j = 0; j < oResultNode.childNodes.length; j++) {
            switch (oResultNode.childNodes[j].baseName) {
                case "Attributes":
                    var attr = oResultNode.childNodes[j];
                    for (var k = 0; k < attr.childNodes.length; k++) {
                        // Establish the Key for the Attribute
                        var sKey = attr.childNodes[k].firstChild.text;
                        var sType = '';
                        // Determine the Type of Attribute value we should expect
                        for (var l = 0; l < attr.childNodes[k].childNodes[1].attributes.length; l++) {
                            if (attr.childNodes[k].childNodes[1].attributes[l].baseName == 'type') {
                                sType = attr.childNodes[k].childNodes[1].attributes[l].text;
                            }
                        }
                        switch (sType) {
                            case "a:OptionSetValue":
                                var entOSV = new jsOptionSetValue();
                                entOSV.type = sType;
                                entOSV.value = attr.childNodes[k].childNodes[1].text;
                                obj[sKey] = entOSV;
                                break;
                            case "a:AliasedValue":
                                var entRef = new jsEntityReference();
                                entRef.guid = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[0].text;
                                entRef.logicalName = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[1].text;
                                entRef.name = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[2].text;
                                obj[attr.childNodes[k].childNodes[1].childNodes[0].text] = entRef;
                                break;
                            case "a:EntityReference":
                                var entRef = new jsEntityReference();
                                entRef.type = sType;
                                entRef.guid = attr.childNodes[k].childNodes[1].childNodes[0].text;
                                entRef.logicalName = attr.childNodes[k].childNodes[1].childNodes[1].text;
                                entRef.name = attr.childNodes[k].childNodes[1].childNodes[2].text;
                                obj[sKey] = entRef;
                                break;
                            default:
                                var entCV = new jsCrmValue();
                                entCV.type = sType;
                                entCV.value = attr.childNodes[k].childNodes[1].text;
                                obj[sKey] = entCV;
                                break;
                        }
                    }
                    jDE.attributes = obj;
                    break;
                case "Id":
                    jDE.guid = oResultNode.childNodes[j].text;
                    break;
                case "LogicalName":
                    jDE.logicalName = oResultNode.childNodes[j].text;
                    break;
                case "FormattedValues":
                    var foVal = oResultNode.childNodes[j];
                    for (var k = 0; k < foVal.childNodes.length; k++) {
                        // Establish the Key, we are going to fill in the formatted value of the already found attribute
                        var sKey = foVal.childNodes[k].firstChild.text;
                        jDE.attributes[sKey].formattedValue = foVal.childNodes[k].childNodes[1].text;
                    }
                    break;
            }
        }
        results[i] = jDE;
    }
    //return entities
    if (callback != null) callback(results);
    else return results;
}
function jsDynamicEntity(gID, sLogicalName) {
    this.guid = gID;
    this.logicalName = sLogicalName;
    this.attributes = new Object();
}
function jsCrmValue(sType, sValue) {
    this.type = sType;
    this.value = sValue;
}
function jsEntityReference(gID, sLogicalName, sName) {
    this.guid = gID;
    this.logicalName = sLogicalName;
    this.name = sName;
    this.type = 'EntityReference';
}
function jsOptionSetValue(iValue, sFormattedValue) {
    this.value = iValue;
    this.formattedValue = sFormattedValue;
    this.type = 'OptionSetValue';
}
//setting CRM fields
function SetLookupField(res, fieldName) {
    if (res[0].attributes[fieldName] != null) {
        SetLookupValue(fieldName, res[0].attributes[fieldName].id, res[0].attributes[fieldName].name, res[0].attributes[fieldName].logicalName);
    }
}
function SetNumberField(res, fieldName) {
    if (res[0].attributes[fieldName] != null) {
        Xrm.Page.getAttribute(fieldName).setValue(parseFloat(res[0].attributes[fieldName].value));
    }
}
function SetLookupValue(fieldName, id, name, entityType) {
    if (fieldName != null) {
        var lookupValue = new Array();
        lookupValue[0] = new Object();
        lookupValue[0].id = id;
        lookupValue[0].name = name;
        lookupValue[0].entityType = entityType;
        Xrm.Page.getAttribute(fieldName).setValue(lookupValue);
    }
}





Synchronous Call Sample :


function FetchData(contactid) {
    var _oService;
    var _sOrgName = "";
    var _sServerUrl = Xrm.Page.context.getServerUrl();
    var sFetch = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
  "<entity name='contact'>" +
  "<attribute name='fullname' />" +
   "<filter type='and'>" +
  "<condition attribute='contactid' operator='eq'   value='" + contactid+ "' />" +
  "</filter>" +
  "</entity>" +
  "</fetch>"
    _oService = new FetchUtil(_sOrgName, _sServerUrl);
    var res = _oService.Fetch(sFetch);

var fullName=res[0].attributes["fullname"].value;
}



Asynchronous Call Sample :


function FetchData(contactid) {
    var _oService;
    var _sOrgName = "";
    var _sServerUrl = Xrm.Page.context.getServerUrl();
    var sFetch = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
  "<entity name='contact'>" +
  "<attribute name='fullname' />" +
   "<filter type='and'>" +
  "<condition attribute='contactid' operator='eq'   value='" + contactid+ "' />" +
  "</filter>" +
  "</entity>" +
  "</fetch>"
    _oService = new FetchUtil(_sOrgName, _sServerUrl);

//The below line will be difference
    var res = _oService.Fetch(sFetch,callBack);


}

function callBack(results){

var fullName=results[0].attributes["fullname"].value;
}




No comments:

Post a Comment