I recently needed to add a button to the toolbar on the details form for the Case entity on Dynamics CRM 4.0. This was much easier than I had expected.
I will be assuming your workflow has already been created and installed. First, you need to export your current configuration file.
- In CRM, click the Settings tab in the bottom left.
- Select Customization - Export Customizations.
- Select ISV Config.
- Click Export Selected Customizations.
This will download a zip file containing the current file. Extract the file, and keep the zip file as a backup in case you break something :)
A typical node for an entity will look like the following:
<Entity name="incident">
<ToolBar>
<ToolBarSpacer />
<Button>
<Titles>
<Title/>
</Titles>
<ToolTips>
<ToolTip/>
</ToolTips>
</Button>
</ToolBar>
</Entity>
Note that "incident" is the data type for Case objects in CRM.
I saw that I already had an entry for incident, so I needed only to add the new <button> subnode. That gave me the following:
<Button Icon="/_imgs/ico/16_send.gif" JavaScript="window.confirm('Are you sure you want email notify the Owner?');" ValidForCreate="0">
<Titles>
<Title LCID="1033" Text="Email Owner" />
</Titles>
<ToolTips>
<ToolTip LCID="1033" Text="Send an automated email notification to the owner" />
</ToolTips>
</Button>
As you can see, clicking this button will ask a question and will do nothing useful. But what we want to do is execute a workflow when it is clicked. To execute a workflow from javascript, CRM uses SOAP requests. Below is a nicely formatted version of the code I needed in the Javascript property of the button node I just added.
var _return = window.confirm('Are you sure you want to send email to the owner?');
if(_return)
{
var caseid = crmForm.ObjectId;
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'>"+
authenticationHeader+
"<soap:Body>"+
"<Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"
"<Request xsi:type='ExecuteWorkflowRequest'>" +
"<EntityId>" + caseid + "</EntityId>" +
"<WorkflowId>79dae421-e144-466c-9cf7-951528a7cb9f</WorkflowId>" +
"</Request>" +
"</Execute>" +
"</soap:Body>" +
"</soap:Envelope>"
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
window.alert('Email has been sent.');
}
This javascript figures out the guid id of the entity to perform the workflow against, and has hardcoded the workflow guid id you wish to execute. Simple enough. But looking in that file at another example, I noticed the javascript had encoded characters. I'm not sure if that is necessary, but not wanting to mess with success, I decided to do the same for my new button.
The following is what I ended up with:
<Button Icon="/_imgs/ico/16_send.gif" JavaScript="
var _return = window.confirm('Are you sure you want email notify the Owner?');
if(_return)
{
var caseid = crmForm.ObjectId;
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'>"+ 
authenticationHeader+ 
"<soap:Body>"+ 
"<Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
"<Request xsi:type='ExecuteWorkflowRequest'>" +
"<EntityId>" + caseid + "</EntityId>" +
"<WorkflowId>E0AE00CD-F794-47F3-9103-C315D8049549</WorkflowId>" +
"</Request>" +
"</Execute>" +
"</soap:Body>" + 
"</soap:Envelope>"
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
window.alert('Email has been sent.');
}
" ValidForCreate="0">
<Titles>
<Title LCID="1033" Text="Email Owner" />
</Titles>
<ToolTips>
<ToolTip LCID="1033" Text="Send an automated email notification to the owner" />
</ToolTips>
</Button>
After saving this file (remember - keep your original as a backup!), you are ready to import the modified config into CRM:
- Click Settings.
- Click Customization.
- Click Import Customizations
- Click browse and select your file.
- Click upload.
CRM is able to automatically determine which file you have uploaded. It should say ISV Config. Highlight it and click Import Selected Customizations.
Test your newly added button. Should there be a problem, re-import the original unmodified config and go back to the drawing board with the javascript you wrote.
If this ends up helping someone, I will be happy to write more CRM posts in the future. Please let me know by commenting or rating this post.