Aidan Garnish

Collaboration Not Competition

Getting started with JavaScript in Dynamics CRM 4.0

This is a blog that is usually about SharePoint and SharePoint development but recently I have been starting to do some work with Microsoft Dynamics CRM 4.0. Initially this work was about integrating SharePoint document libraries with CRM but has now gone beyond that into actual customisation and development of CRM itself.

CRM 4.0 has been around for a while now and many companies who have CRM will also have a SharePoint deployment so although it is a bit off topic I'm sure there are plenty of SharePoint people who will find a bit of CRM information helpful.

As with SharePoint there are lots of options for customising CRM. The first option is customisation of existing entities and forms. This allows you to add attributes to the various objects in CRM such as customers or orders. It is also possible to add JavaScript to the forms to add logic, validation or additional calculations into the forms and this is what this post will take a look at. Finally it is possible to add aspx pages or use ashx handlers in conjunction with the CRM web services to create virtually any extra complex business logic or functionality that is required - later posts will deal with this.

When customising CRM forms it is possible to easily add JavaScript to the on load and on save events of each form or to the on change event of any field.

A few hints and tips:

  • To reference an attribute on a form use crmForm.all.attributename.
  • If the attribute is not a string use .DataValue to return the value held in the attribute. e.g. crmForm.all.attributename.DataValue.
  • DataValue should also be used when creating comparison statements. E.g. if(crmForm.all.isapproved.DataValue == true)
  • If you have a calculated field that is set to read only on the form then you will need to make sure that it is set to ForceSubmit = true otherwise it will not be saved. To do this use the following - crmForm.all.attributename.ForceSubmit = true;
  • To hide a field or menu item use crmForm.all.attributname.style.display = "none";
  • To disable a field use - crmForm.all.attributename.Disabled = false; or use true; to disable the field.

It is possible to set the default for a lookup field. The following example script sets a default price list for the price list field:
 

if(crmForm.all.pricelevelid.DataValue == null)
{
//Create an array to set as the DataValue for the price list lookup control. 
var lookupData = new Array(); 
//Create an Object add to the array. 
var lookupItem= new Object(); 
//Set the id, typename, and name properties to the object. 
lookupItem.id = '{0049EC3B-1257-DF11-8A46-00155D025108}'; 
lookupItem.typename = 'pricelevel'; 
lookupItem.name = 'Test Price List'; 
// Add the object to the array. 
lookupData[0] = lookupItem; 
// Set the value of the lookup field to the value of the array. 
crmForm.all.pricelevelid.DataValue = lookupData;
}

Use the following JavaScript to call CRM web services to return information on the current user - this is then used to set a user lookup field to be the current user:

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\">" + 
GenerateAuthenticationHeader() +
" <soap:Body>" + 
" <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>systemuser</q1:EntityName>" + 
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" + 
" <q1:Attributes>" + 
" <q1:Attribute>businessunitid</q1:Attribute>" + 
" <q1:Attribute>firstname</q1:Attribute>" + 
" <q1:Attribute>fullname</q1:Attribute>" + 
" <q1:Attribute>lastname</q1:Attribute>" + 
" <q1:Attribute>organizationid</q1:Attribute>" + 
" <q1:Attribute>systemuserid</q1:Attribute>" + 
" </q1:Attributes>" + 
" </q1:ColumnSet>" + 
" <q1:Distinct>false</q1:Distinct>" + 
" <q1:Criteria>" + 
" <q1:FilterOperator>And</q1:FilterOperator>" + 
" <q1:Conditions>" + 
" <q1:Condition>" + 
" <q1:AttributeName>systemuserid</q1:AttributeName>" + 
" <q1:Operator>EqualUserId</q1:Operator>" + 
" </q1:Condition>" + 
" </q1:Conditions>" + 
" </q1:Criteria>" + 
" </query>" + 
" </RetrieveMultiple>" + 
" </soap:Body>" + 
"</soap:Envelope>" + 
"";

var xmlHttpRequest2 = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest2.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest2 .setRequestHeader("SOAPAction", "http://schemas.microsoft.com/
crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest2.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest2.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest2.send(xml);

var resultXml = xmlHttpRequest2.responseXML;
var entityNode = resultXml.selectSingleNode("//RetrieveMultipleResult/BusinessEntities/
BusinessEntity");

var firstNameNode = entityNode.selectSingleNode("q1:firstname");
var lastNameNode = entityNode.selectSingleNode("q1:lastname");
var fullNameNode = entityNode.selectSingleNode("q1:fullname");
var systemUserIdNode = entityNode.selectSingleNode("q1:systemuserid");
var businessUnitIdNode = entityNode.selectSingleNode("q1:businessunitid");
var organizationIdNode = entityNode.selectSingleNode("q1:organizationid");

//Create an array to set as the DataValue for the the lookup control. 
var lookupData = new Array(); 
//Create an Object add to the array. 
var lookupItem= new Object(); 
//Set the id, typename, and name properties to the object. 
lookupItem.id = systemUserIdNode.text; 
lookupItem.typename = 'systemuser'; 
lookupItem.name = fullNameNode.text; 
// Add the object to the array. 
lookupData[0] = lookupItem; 
// Set the value of the lookup field to the value of the array. 
crmForm.all.approvedby.DataValue = lookupData;
crmForm.all.approvedby.ForceSubmit = true;


 

Using JavaScript is a great way to customise CRM as any script you add is saved as part of the form so when you come to deploy them they are included in the export customisations file. In my customisation of CRM I have tried to use this approach wherever possible but sometimes what you want to achieve cannot be done without cracking open Visual Studio and this is what I plan on taking a look at in my next post.

Twitter SharePoint Web Part With OAuth

As Twitter are about to stop allowing use of Basic Auth I have updated the Twitter friends timeline web part to use OAuth.

When you add the web part to the page you will be directed to the Twitter OAuth login page once. After that the authentication token and secret are persisted in the properties of the web part although only the token is browsable.

To change the account being displayed simply clear the Token property in the Miscellaneous section of the web part properties and you will be prompted for a new set of credentials.

As a bonus I have also included a Twitter search web part. This does not require authentication but does require you to provide a search term in the Miscellaneous section of the web part properties.

To download the .wsp SharePoint solution file visit this page.

Thanks to Shannon Whitley for his OAuth Twitter example