Tuesday, 27 March 2012

Populate Regarding Attribute in New Email Form

When we created a new email for a record by Clicking “New Activity” button in the “Activities” associated view, it will prompt us to select the activity type.

And when the user select E-mail and click OK, the new email form will is shown with the “From” attribute populated with the current user and the “Regarding” attribute populated with the record from which we clicked “New Activity” and everything is fine.

According to the users’ requirement, there’s a case that we have to show the Subgrid of email related to the record on the form. And that’s where the problem started. When the user click “Add New E-mail” button from the Subgrid and the new Email form is loaded, the record is not populated in the regarding attribute. So, the user demands for the same functionality as the new Activity since it would be a hassle to select the Regarding attribute manually.

So, my solution was writing a JavaScript code at the onLoad of the Email form which will auto populate the “Regarding” attribute if email form is loaded from a record. In order to fill up the Regarding lookup value, we’ll need the RecordId, LogicalName of the Entity and PrimaryName (for display). The logic of the code is to check the _CreateFromId and _CreateFromType from the QueryStringParameters and fetch the required parameters using RetrieveAllEntitiesAsync from "SDK.MetaData.js" of Microsoft. First, you need to create a new JavaScript webresource, copy the code of "SDK.MetaData.js" and add it into the Form Libraries of the Email form. Then, add the following codes in the JavaScript Library of Email form and call the OnLoad function.

 function OnLoad()  
     var FORM_TYPE_CREATE = 1;  
     if (Xrm.Page.ui.getFormType() == FORM_TYPE_CREATE && Xrm.Page.context.getQueryStringParameters()["_CreateFromId"] != null && Xrm.Page.context.getQueryStringParameters()["_CreateFromType"] != null)  
         SDK.MetaData.RetrieveAllEntitiesAsync(SDK.MetaData.EntityFilters.Entity, false, successRetrieveAllEntities, errorRetrieveAllEntities);  
 function successRetrieveAllEntities(entityMetadataCollection)  
     var entityName = "";  
     var PrimaryNameAttribute = "";  
     for (var i = 0; i < entityMetadataCollection.length; i++)  
         if (entityMetadataCollection[i].ObjectTypeCode == Xrm.Page.context.getQueryStringParameters()["_CreateFromType"])  
             entityName = entityMetadataCollection[i].LogicalName;  
             PrimaryNameAttribute = entityMetadataCollection[i].PrimaryNameAttribute;  
     if (entityName != "" && PrimaryNameAttribute != "")  
         var displayValue = RetrieveMultiple(entityName, PrimaryNameAttribute, entityName + "id|Equal|" + Xrm.Page.context.getQueryStringParameters()["_CreateFromId"]);  
         Xrm.Page.getAttribute("regardingobjectid").setValue( [{id: Xrm.Page.context.getQueryStringParameters()["_CreateFromId"], name: displayValue, entityType: entityName}]);  
 function errorRetrieveAllEntities(error)  
 function RetrieveMultiple(entity, attribute, condition)  
     // Usage => RetrieveMultiple("new_entityname", "new_attribute1|new_attribute2|new_attribute3", "new_attribute1|Equal|value1||new_attribute2|Like|value2||new_attribute3|NotNull";  
     // Refer to the following link for more operators >> http://msdn.microsoft.com/en-us/library/bb959309.aspx  
     // Prepare variables to retrieve the records.  
     var attributes = attribute.split('|');  
     var authenticationHeader = GenerateAuthenticationHeader();  
     // Prepare the SOAP message.  
     var xml = "<?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'>"+   
     "<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>" + entity + "</q1:EntityName>"+   
     "<q1:ColumnSet xsi:type='q1:ColumnSet'>"+   
     for (i = 0; i < attributes.length; i++)  
         xml += "<q1:Attribute>" + attributes[i] + "</q1:Attribute>"  
     xml +=  
     var conditionDetails;  
     var conditions = condition.split('||');  
     for (i = 0; i < conditions.length; i++)  
         conditionDetails = conditions[i].split('|');  
         xml +=   
         "<q1:AttributeName>" + conditionDetails[0] + "</q1:AttributeName>"+   
         "<q1:Operator>" + conditionDetails[1] + "</q1:Operator>";  
         if (conditionDetails.length > 2)  
             xml +=   
             "<q1:Value xsi:type='xsd:string'>" + conditionDetails[2] + "</q1:Value>"+   
         xml +=   
     xml +=   
     // Prepare the xmlHttpObject and send the request.  
     var xHReq = new ActiveXObject("Msxml2.XMLHTTP");  
     xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);  
     xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");  
     xHReq.setRequestHeader("Content-Length", xml.length);  
     // Capture the result.  
     var resultXml = xHReq.responseXML;  
     // Check for errors.  
     var errorCount = resultXml.selectNodes('//error').length;  
     if (errorCount != 0)  
         var msg = resultXml.selectSingleNode('//description').nodeTypedValue;  
         return msg;  
     // Parse and display the results.  
         var results = resultXml.getElementsByTagName('BusinessEntity');  
         var msg = "";  
         if (results.length == 0)  
             //msg = "No record found with the given criteria.";  
             return null;  
             var result = "";  
             for (i = 0;i < results.length;i++)  
                 if (i != 0)  
                     result += '|';  
                 for (j = 0; j < attributes.length; j++)  
                     if (i != 0 || j != 0)  
                         result += '|';  
                     if (results[i].selectSingleNode('./q1:'+ attributes[j]) != null)  
                         result += results[i].selectSingleNode('./q1:'+ attributes[j]).nodeTypedValue;  
             return result;  

Leave me a comment if you have any problem with the above code.


  1. Tried the code, but get an error 'unable to get value of the property length'. I think I narrowed it down to the entityMetadateCollection being undefined. Any suggestions? thanks.

    1. Can you please specify which line of code is triggering that issue?