Looking for PowerObjects? Don’t worry, you’re in the right place! We’ve been part of HCL for several years, and we’ve now taken the final step in our acquisition journey: moving our website to the HCL domain. Nothing else is changing – we are still fanatically focused on Microsoft Business Applications!

PowerObjects Blog 

for Microsoft Business Applications


Cross-Browser Solution to Replace ActiveXObject with SOAP Messaging (JavaScript)

Post Author: Joe D365 |

While Dynamics CRM is becoming cross-browser compatible, some technologies used to customize CRM are not. For example, the use of ActiveX within CRM code will never be compatible with browsers that are not Internet Explorer. The use of ActiveX within Javascript libraries is not uncommon and any code that uses it will have to be re-written before these libraries are functional within non-IE browsers.

One example is the use of ActiveXObject to “lookup” data via Soap (post Soap requests or read Soap responses). A very common usage of this can be found in code similar to this RetrieveEntityById function (usage not shown):
function RetrieveEntityById(prmEntityName, prmEntityId, prmEntityColumns) {
var resultXml, errorCount, msg, xmlHttpRequest, arrayEntityColumns, xmlEntityColumns;
arrayEntityColumns = prmEntityColumns.split(",");
for (var i = 0; i < arrayEntityColumns.length; i++) {
xmlEntityColumns += "" + arrayEntityColumns[i] + "";
}
var authenticationHeader = Xrm.Page.context.getAuthenticationHeader();

var xml = "" +
"" +
authenticationHeader +
"" +
"" +
"" + prmEntityName + "" +
"" + prmEntityId + "" +
"" +
"" +
xmlEntityColumns +
"" +
"" +
"";

xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Retrieve");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
resultXml = xmlHttpRequest.responseXML;
var errorCount = resultXml.selectNodes('//error').length;
if (errorCount != 0) {
var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
alert("Error Message : " + msg);
}
else {
return resultXml;

This code uses ActiveXObject to post a Soap request and send along the resulting XML data to be parsed as needed (to populate related fields on the form, for example). This is a very flexible, reusable function that can be added to a Javascript library and used to “lookup” any number of field values from a single record in a related entity. But, this function won’t work in non-IE browsers because of its use of the ActiveXObject.

An alternative to this is to utilize the oData endpoint to request the data and read the response as JSON (JQuery needed). In this particular example you can assume a single record is being returned as you are passing a GUID in the oData query. So, the above RetrieveEntityById() function can be replaced by:

[sourcecode language="javascript"]

function getEntityByID(theEntity, theIdFieldName, theId, theFields, theAction) {

var pagecontext = Xrm.Page.context;
var serverUrl = pagecontext.getServerUrl();
var oDataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
var oDataSelect = oDataPath + "/" + theEntity + "Set?$select=" + theFields + "&$filter=" + theIdFieldName + " eq guid'" + theId + "'";
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: oDataSelect,

beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); },

success: function (data, textStatus, XmlHttpRequest) {
if (theAction = "FirstLast") {
FirstLastAlert(data.d.results);
}
},

error: function (XmlHttpRequest, textStatus, errorThrown) { alert('OData Select Failed: ' + odataSelect); }
});
}

[/sourcecode]

Let’s say we want to utilize this function to lookup the FirstName and LastName of a Contact lookup on a CRM form, perhaps using the OnChange event of the Primary Contact field. We could call the GetEntityByID function as follows:

[sourcecode language="javascript"]
function getFirstLast() {
var primaryContact = Xrm.Page.data.entity.attributes.get("primarycontactid");
theId = primaryContact.getValue()[0].id;
if (primaryContact.getValue()[0].entityType == "contact") { // make sure this is the expected entity type
getEntityByID("Contact", "ContactId", theId, "FirstName,LastName", "FirstLast");
}
}
[/sourcecode]

And with a successful return from the oData endpoint, we can handle the response data in Javascript as shown in the FirstLastAlert() function (in this example it assumes a single record and simply uses an alert to pop up the values):

[sourcecode language="javascript"]
function FirstLastAlert(theEntityFields) {
//here is where you'd add the code to handle the data returned
alert(theEntityFields[0].FirstName);
alert(theEntityFields[0].LastName);
}
[/sourcecode]

As with the RetrieveEntityById() function, the getEntityByID() function can be used to “lookup” any number of fields from any given entity and handle the returned values as needed…a very flexible, reusable tool to have within a Javascript library.

Hopefully this post will be helpful as an example of how to address cross browser issues when using ActiveXObject and Soap.

Happy CRM'ing!

Joe CRM
By Joe D365
Joe D365 is a Microsoft Dynamics 365 superhero who runs on pure Dynamics adrenaline. As the face of PowerObjects, Joe D365’s mission is to reveal innovative ways to use Dynamics 365 and bring the application to more businesses and organizations around the world.

5 comments on “Cross-Browser Solution to Replace ActiveXObject with SOAP Messaging (JavaScript)”

  1. What about the fact that JQuery uses ActiveX also? Doesn't that defeat the purpose of switching from SOAP to JSON?

PowerObjects Recommends