Pages

Wednesday, November 4, 2009

Easy to use JavaScript Retrieve and RetrieveMultiple functions

function MischiefMayhemSOAP(xmlSoapBody, soapActionHeader) {
  var xmlReq = "<?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'>"
    + GenerateAuthenticationHeader()
    + "  <soap:Body>"
    + xmlSoapBody
    + "  </soap:Body>"
    + "</soap:Envelope>";

  var httpObj = new ActiveXObject("Msxml2.XMLHTTP");
    
  httpObj.open('POST', '/mscrmservices/2007/crmservice.asmx', false);

  httpObj.setRequestHeader('SOAPAction', soapActionHeader);
  httpObj.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
  httpObj.setRequestHeader('Content-Length', xmlReq.length);

  httpObj.send(xmlReq);

  var resultXml = httpObj.responseXML;

  var errorCount = resultXml.selectNodes('//error').length;
  if (errorCount != 0) {
    var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
    alert("The following error was encountered: " + msg);
    return null;
  } else {
    return resultXml;
  }
}
function RetrieveRecord(entityName, entityId, attrArray) {
  var xmlSoapBody = ""
    + "    <Retrieve xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"
    + "      <entityName>" + entityName + "</entityName>"
    + "      <id>" + entityId + "</id>"
    + "      <columnSet xmlns:q1='http://schemas.microsoft.com/crm/2006/Query' xsi:type='q1:ColumnSet'>"
    + "        <q1:Attributes>";

  for (index in attrArray) {
    xmlSoapBody += "          <q1:Attribute>" + attrArray[index] + "</q1:Attribute>";
  }

  xmlSoapBody += ""
    + "        </q1:Attributes>"
    + "      </columnSet>"
    + "    </Retrieve>";

  var resultXml = MischiefMayhemSOAP(xmlSoapBody, 'http://schemas.microsoft.com/crm/2007/WebServices/Retrieve');

  if (resultXml != null) {
    var resultArray = new Array();

    for (index in attrArray) {
      if (resultXml.selectSingleNode("//q1:" + attrArray[index]) != null) {
        resultArray[index] = resultXml.selectSingleNode("//q1:" + attrArray[index]).nodeTypedValue;
      } else {
        resultArray[index] = null;
      }
    }

    return resultArray;
  } else {
    return null;
  }
}
function RetrieveMultiple(entityName, attrArray, distinct, criteriaXml)  {
  var xmlSoapBody = ""
    + "    <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>" + entityName + "</q1:EntityName>"
    + "        <q1:ColumnSet xsi:type='q1:ColumnSet'>"
    + "          <q1:Attributes>";

  for (index in attrArray) {
    xmlSoapBody += "            <q1:Attribute>" + attrArray[index] + "</q1:Attribute>";
  }

  xmlSoapBody += ""
    + "          </q1:Attributes>"
    + "        </q1:ColumnSet>"
    + "        <q1:Distinct>" + distinct + "</q1:Distinct>"
    + criteriaXml
    + "      </query>"
    + "    </RetrieveMultiple>";

  var resultXml = MischiefMayhemSOAP(xmlSoapBody, 'http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple');

  if (resultXml != null) {
    var resultArray = new Array();
    var entityNodes = resultXml.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

    if (entityNodes.length > 0) {
        for (var index = 0; index < entityNodes.length; index++) {
          var entityNode = entityNodes[index];
          resultArray[index] = new Array();
    
          for (attrIndex in attrArray) {
            if (entityNode.selectSingleNode("q1:" + attrArray[attrIndex]) != null) {
              resultArray[index][attrIndex] = entityNode.selectSingleNode("q1:" + attrArray[attrIndex]).nodeTypedValue;
            } else {
              resultArray[index][attrIndex] = null;
            }
          }
        }
        
        return resultArray;
    } else {
      return null;
    }
  } else {
    return null;
  }
}
These functions are built around SOAP implementations of the Retrieve and RetrieveMultiple messages. I haven't annotated my code, so forgive any obvious lack of description of what the code is doing. I'll try to briefly summarize here:
MischiefMayhemSOAP
Parameters:
xmlSoapBody - (string) XML containing the body of the SOAP call
soapActionHeader - (string) The 'SOAPAction' specifying the type of SOAP call
Purpose:
Serves as a generic XMLHTTP interface to CRM's SOAP functions.
Returns:
(string) XML result from the CRM server.
RetrieveRecord
Parameters:
entityName - (string) The CRM-platform name of the desired entity
entityId - (string) The GUID of the record to retrieve
attrArray - (string[]) An Array of attributes to retrieve for the record
Purpose:
Easily retrieves a single record from CRM.
Returns:
(string[] or null) An Array of values from CRM, index-matching the attributes provided in attrArray. Returns null if there is an error with, or invalid return from, the SOAP call.
RetrieveMultiple
Parameters:
entityName - (string) The CRM-platform name of the desired entity
attrArray - (string[]) An Array of attributes to retrieve for the records
distinct - (string:"true" or "false") Directs CRM to return with or without duplicate records
criteriaXml - (string) XML containing any combination of Criteria or LinkEntities elements pertaining to the "RetrieveMultiple" SOAP message
Purpose:
Easily retrieves multiple records from CRM which match the rules defined in the criteriaXml.
Returns:
(string[n][] or null) An Array, with n matching-record elements, of an array of values from CRM, index-matching the attributes provided in attrArray. Returns null if there is an error with, or invalid return from, the SOAP call.