Friday, September 07, 2012

Fetch XML and Javascript

I had a requirement to show the financial summary of the customers.

I tried different options and ended up using Javascript.

I created an new button in the ribbon and then called the javascript to update the values using fetchxml.
Call the "GetOverview" function in the ssb_contact_links.js file.


Upload the below Javascript as webresources and then link these libraries to the form so that we can call those functions.


// JScript source code
//===============================================================================================
//ssb_FetchXmlLib.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 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: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;
                            case "a:AliasedValue":
                                var entAV = new jsAliasedValue();
                                //entAV.type = sType;
                                entAV.name = attr.childNodes[k].childNodes[1].childNodes[0].text;
                                entAV.logicalName = attr.childNodes[k].childNodes[1].childNodes[1].text;
                                entAV.value = attr.childNodes[k].childNodes[1].childNodes[2].text;
                                obj[sKey] = entAV;
                                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 jsAliasedValue(sLogicalName, sName, sValue, sFormattedValue) {
    this.value = sValue;
    this.logicalName = sLogicalName;
    this.name = sName;
    this.type = 'AliasedValue';
    this.formattedValue = sFormattedValue;
}
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';
}

//===============================================================================================
//ssb_fetchXml.js

// JScript source code
function fetchOnLoadSync() {
    var _oService;
    var _sOrgName = "OrgName";
    var _sServerUrl = Xrm.Page.context.getServerUrl();
    // Get the ID of the Customer
    var sCustGUID = Xrm.Page.data.entity.getId();
    var entityName = Xrm.Page.data.entity.getEntityName();
    var linkEntity = "";

    if (entityName == "contact") linkEntity = "ssb_contact";
    if (entityName == "account") linkEntity = "ssb_account";
    var msg = "";
    msg += "Logical Entity Name = " + entityName + "\n";
    msg += "Guid of the current record = " + sCustGUID + "\n";
    msg += "Link Entity Name = " + linkEntity + "\n";
    //alert(sCustGUID);
    var sFetch =    "<fetch version='1.0' mapping='logical' distinct='false' aggregate='true'>"+
                      "<entity name='ssb_stock'>"+
                        "<attribute name='ssb_market_value' aggregate='SUM' alias='sum_market_value'/>" +
                        "<attribute name='ssb_cost_value' aggregate='SUM' alias='sum_cost_value'/>" +
                        "<attribute name='ssb_stock_name' aggregate='count' alias='count_of_stock'/>" +
                        "<filter>"+
                          "<condition attribute='" + linkEntity + "' operator='eq' value='"+ sCustGUID + "' />"+
                        "</filter>"+
                      "</entity>"+
                    "</fetch>";
    _oService = new FetchUtil(_sOrgName, _sServerUrl);
    var res = _oService.Fetch(sFetch);
    //for (x in res) {
    // for (y in res[x]) {
            //alert("Type = " + res[0].attributes["sum_market_value"].type);
           // alert("Value = " + res[0].attributes["sum_market_value"].value);
            //alert("Formatted Value = " + res[0].attributes["sum_market_value"].formattedValue);
         //   alert(res[x].attributes[y].value);
     //   }
    // }
    msg += "Type = " + res[0].attributes["sum_market_value"].type + "\n";
    msg += "Market Value = " + res[0].attributes["sum_market_value"].value + "\n";
    msg += "Market Value Formatted = " + res[0].attributes["sum_market_value"].formattedValue;
    msg += "Cost Value = " + res[0].attributes["sum_cost_value"].value + "\n";
    msg += "Cost Value Formatted = " + res[0].attributes["sum_cost_value"].formattedValue;
    msg += "Count of Records = " + res[0].attributes["count_of_stock"].value + "\n";
    //alert(msg);
   return (res[0].attributes["sum_market_value"].value );
}

//=======================================================================
//ssb_contact_links.js

function GetOverview()
{
//<script src="ssb_FetchXml.js"></script>
//alert("Overview Start");
//var fetch: ScriptName;
//fetch = this.GetComponent("ssb_FetchXml");
//alert (Xrm.Page.getAttribute("ssb_sum_of_stocks").getValue());
var marketValue =Number( fetchOnLoadSync());
//alert (marketValue )
Xrm.Page.getAttribute("ssb_sum_of_stocks").setValue(marketValue);
var idag = new Date();
//alert (idag);
Xrm.Page.getAttribute("ssb_overview_updated_date").setValue(idag);
//alert("Overview Refreshed");
Xrm.Page.data.entity.save();

}






No comments: