Actions

ACTION-iStock_000018662891Small

In Microsoft Dynamics CRM 2013 new exciting feature for developers was added to the list of transactional-aware processes (additional to workflows, dialogues and business process flows) name Actions .
As you probably know Microsoft Dynamics CRM provide us with OOTB messages for entities such as the CRUD related messages however there are times when the supplied message are not quite fits for your needs.
Actions open a range of possibilities for composing business logic and treat is as single transactional unit, for instance ,after every case creation you want to assign it to some user.

The biggest advantage of custom Actions is giving system administrators the ability to build automated processes, which can be trigger by developers using a single command which in prior CRM version such scenario could only be achieved by code or workflow that triggers after a save operation.
Creating actions is basically creating a new synchronous custom messages that act like the standard system messages and can be triggered based on actions taken on an entity record.
It can be defined for a specific entity or for all entities.
When you create an action, the associated synchronized workflow is registered to execute in core operation stage of the execution pipeline(stage 30).
Actions which runs under the security context of the calling user and can return easy maintainable response.
Actions can be invoked from server-side code such as plug-in or custom workflow.
It can also be invoked from a JavaScript code directly in our forms or even by any source code that uses the Microsoft Dynamics CRM web services.
Since update 1 you can execute an action from workflows, dialogs, or other process actions by selecting the Perform Action item in the Add Step drop down of the Web application process form.
AC1
AC2

Let’s take a scenario where you want to assign a case to specific user,send an email and change the status to “Waiting for details” whenever the case subject is information.
Lets First define the action from the Solution Processes section.
ac1

ac2

In the action form
you can choose whether you would like to enable rollback or not which means rollback ,or undo the entire operation when any part failed (besides steps that were done beyond the scope of the transaction or messages that does not support transaction).
You can also define input or output arguments.
Input arguments which can be defined as optional or required are arguments that can or need to be passed during an action call (from code).
and can be used by different stages in our action.
Output arguments are values which can also be optional or mandatory that returned from an action execution.
So for instance,if in our scenario we would like to set the email title according to some specific logic determined in code so we will first need to set an string type input argument and later on we will see when and how we’ll use it.
ac3

Next lets define the steps that need to be taken (send email ,assign and set status),which are same as defining steps in workflow

ac4

we will also use the email title argument we defined earlier.
Open the email settings and get it from the form assistant menu

ac5

that’s it, setting up the action is done,we just need to activate it in order to execute it in our code.

How to execute Actions?
Since Actions are basically custom messages , they can be executed similarly as system messages.
Once created and activated they are also available to use through the developer toolkit
ac6

Sample of Late Binding action execution from Server-side

var request = new OrganizationRequest("new_emailanddelegate");
request["emailTitle"] = "Hello , email from me!";
OrganizationResponse response = service.Execute(request);

Actions are available for Early binding by running CrmSvcUtil (see my post on how to use the tool) with the following command as example

CrmSvcUtil.exe /url:http:///Organization.svc /out:DataModel.cs 
/namespace:CrmActions /serviceContextName:ServiceContext /generateActions

Sample of Late Binding action execution from Server-side

var request = new new_emailanddelegateRequest()
{
    emailTitle = "Hello , email from me!",
};
 var response = service.Execute(request) as  new_emailanddelegateRequest;

Sample of action execution from client-side

function ExecuteAction() {
    var xmlRequest = getSoapReuqest()
    var req = new XMLHttpRequest();
    req.open("POST", GetClientUrl(), false)
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");

    req.send(xmlRequest); 
    var response = req.responseXML.xml;
}

function getSoapReuqest(entityId, entityName, actionName,emailTitle) {
 // Creating SOAP request for calling the Action
    var entityId = Xrm.Page.data.entity.getId();
    var entityName = "case";
    var actionName = "new_emailanddelegate";
    var emailTitle = "Hello , email from me!";

    requestXML += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
    requestXML += "  <s:Body>";
    requestXML += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
    requestXML += "      <request xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
    requestXML += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
    requestXML += "          <a:KeyValuePairOfstringanyType>";
    requestXML += "            <b:key>Target</b:key>";
    requestXML += "            <b:value i:type=\"a:EntityReference\">";
    requestXML += "              <a:Id>" + entityId + "</a:Id>";
    requestXML += "              <a:LogicalName>" + entityName + "</a:LogicalName>";
    requestXML += "              <a:Name i:nil=\"true\" />";
    requestXML += "            </b:value>";
    requestXML += "          </a:KeyValuePairOfstringanyType>";
    requestXML += "          <a:KeyValuePairOfstringanyType>";
    requestXML += "            <b:key>emailTitle</b:key>";
    requestXML += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + emailTitle  + "</b:value>";
    requestXML += "          </a:KeyValuePairOfstringanyType>";
    requestXML += "        </a:Parameters>";
    requestXML += "        <a:RequestId i:nil=\"true\" />";
    requestXML += "        <a:RequestName>" + actionName + "</a:RequestName>";
    requestXML += "      </request>";
    requestXML += "    </Execute>";
    requestXML += "  </s:Body>";
    requestXML += "</s:Envelope>";
}

function GetClientUrl() {
    if (typeof Xrm.Page.context == "object") {
        clientUrl = Xrm.Page.context.getClientUrl();
    }
    var ServicePath = "/XRMServices/2011/Organization.svc/web";
    return clientUrl + ServicePath;
}

Published by Yaniv Shoval

.Net developer who takes interest in various technologies but specialized in .NET and Microsoft Dynamics CRM development

Leave a comment