Thursday, September 26, 2013

Introduction to Actions in CRM 2013

Until CRM 4 there were Workflows that could be used for asynchronous processing of business logic, generally used for setting up automated actions and defining sales process in Dynamics CRM.

Since CRM 2011, the workflows became a category under Processes and there was another category Dialogs introduced. Dialogs provided for execution of Dialog scripts to set up process flows for the Salesforce. These could be used to guide the sales people through the sales process using a question/answer format. The Dialog included execution of automated steps like the workflows.

With CRM 2013, the Processes have been extended to now include Business Process Flow and Actions in addition to the categories from the previous versions. In our earlier blog we have discussed the concept of Business Process Flow. This article will concentrate on Actions.

What are Actions?

Actions are messages that can defined for an entity. Existing examples messages include Create, Update, Set State, Assign etc. With Actions, the CRM platform has enabled the creation of custom actions for entities to extend the XRM platform.

Where to use Actions?

An example of a custom action could be “Approve”. Often times we have to design an approval process for Dynamics CRM. Once the item is approved, certain actions need to be performed. In previous versions it would either be implemented as a Workflow that is manually executed from the Workflows Dialog or it involved added of a custom attribute that when checked would imply the item is approved and then the workflow would capture the update of this field to process any automated actions defined.

How to setup an Action?

Let us take an example of an approval process. When an item is “Approved”, we want to send email notifying the concerned parties of the approval. 



Here is an action created for “Approve”

It accepts an input parameter for the ApprovedBy User. You can specify parameters of any of the following data types

 
These parameters could be defined as input/output parameter.
 
In the workflow actions, it sends a mail from the ApprovedBy user to the Owner of the Order notifying them of the order being approved. You can also call custom workflow assemblies here.

Note the schema name generated “new_Approve”. This is the name of the new message that will not be available for the Order entity.

These actions are available for further implementation of custom business logic through the use of plugins. In some scenarios, say we need to validate certain conditions are met before the item can be approved. In this case we can register a plugin in the Pre-Stage of the Approve Message. The plugin could validate the conditions and throw an exception to abort the processing of the Approve Message.

How to use Actions?

Since Actions are implemented as custom messages/requests, they can be implemented similar to any other OOB messages like Create or Update.

Using C# code, you can invoke the Approve request using the following code                 

                    //get current user details
                    WhoAmIRequest userReq = new WhoAmIRequest();

                    WhoAmIResponse resp = (WhoAmIResponse) proxy.Execute(userReq);

         OrganizationRequest req = new OrganizationRequest("new_Approve");
                    req["ApprovedBy"] = new EntityReference("systemuser", resp.UserId);
                    req["Target"] = new EntityReference("salesorder",orderid);

                    //execute the request
                    OrganizationResponse response = proxy.Execute(req);
 

Through jscript it can be invoked as follows.
 
if (typeof (SDK) == "undefined")
{ SDK = { __namespace: true }; }

SDK.Action = {

    _getClientUrl: function () {      

        var ServicePath = "/XRMServices/2011/Organization.svc/web";

        var clientUrl = "";
        if (typeof GetGlobalContext == "function") {
            var context = GetGlobalContext();
            clientUrl = context.getClientUrl();
        }
        else {
            if (typeof Xrm.Page.context == "object") {
                clientUrl = Xrm.Page.context.getClientUrl();
            }
            else
            { throw new Error("Unable to access the server URL"); }
        }
        if (clientUrl.match(/\/$/)) {
            clientUrl = clientUrl.substring(0, clientUrl.length - 1);
        }
        return clientUrl + ServicePath;
    },
    ApproveRequest : function (salesOrderId, approvedById) {
        var requestMain = ""
        requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
        requestMain += "  <s:Body>";
        requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
        requestMain += "      <request xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
        requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        requestMain += "          <a:KeyValuePairOfstringanyType>";
        requestMain += "            <b:key>Target</b:key>";
        requestMain += "            <b:value i:type=\"a:EntityReference\">";
        requestMain += "              <a:Id>" + salesOrderId + "</a:Id>";
        requestMain += "              <a:LogicalName>salesorder</a:LogicalName>";
        requestMain += "              <a:Name i:nil=\"true\" />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "          <a:KeyValuePairOfstringanyType>";
        requestMain += "            <b:key>ApprovedBy</b:key>";
        requestMain += "            <b:value i:type=\"a:EntityReference\">";
        requestMain += "              <a:Id>" + approvedById + "</a:Id>";
        requestMain += "              <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "              <a:Name i:nil=\"true\" />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>new_Approve</a:RequestName>";
        requestMain += "      </request>";
        requestMain += "    </Execute>";
        requestMain += "  </s:Body>";
        requestMain += "</s:Envelope>";
        var req = new XMLHttpRequest();
        req.open("POST", SDK.Action._getClientUrl(), false)
        req.setRequestHeader("Accept", "application/xml, text/xml, */*");
        req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        req.send(requestMain);
        //work with the response here
        //var strResponse = req.responseXML.xml;       

    },
    __namespace: true
};
  

Here in this above script RequestName indicates the Unique Name of Action and Parameters contains collection of key value pairs that can be passed to Action. In above script We can use below function using below syntax.
SDK.Action.ApproveRequest(salesOrderId, approvedById);

You can register plugin on the Approve message. The input parameters of the Approve message will receive the input parameters as defined in the Approve Action.

The plugin registration tool will start showing this message for the Order entity to register plugin against.





Once the plugin is registered, in the code you can access the input parameters just like you do for other messages as shown below


To get access to the image of the Order record



EntityReference entityRef = localContext.PluginExecutionContext.InputParameters["Target"] as EntityReference;



To read the ApprovedBy input parameter



EntityReference approvedBy = localContext.PluginExecutionContext.InputParameters["ApprovedBy"] as EntityReference;



In the pre-stage, you can throw an InvalidPluginExecution error to abort the Approve operation.



Conclusion:

 Actions is a powerful tool in the hands of the developer to truly extend the CRM platform for XRM implementations.
 


Friday, September 20, 2013

Business Process Flow in CRM 2013

The December 2012 Update of Microsoft Dynamic CRM Online introduced Business Process Flow for the OOB Lead, Opportunity and Case entities. With CRM 2013 Microsoft has extended this feature further and allowed creating of business process flows for any entity including custom entities.

Enabling Business Process Flow for an entity:
  
The first step to creating a process flow for an entity requires enabling the Business Process Flow for the entity. This can be done by checking the option for Business Process Flows on the Entity definition form



Enabling this option on an entity would add two new fields called Process Id and Stage Id. Process Id holds the id of the process associated with that record and Stage Id stores the id of the current stage of the record in the process.



Creating Business Process Flow:

Business Process Flow has been included as a part of the Processes and these can be managed from the Processes section of CRM. Now when creating a new Process, you find a new Category option Business Process Flow which should be selected for designing a new Business Process.


Choose the primary entity for which the process needs to be designed.
 
Next add Stages and Steps in the Process flow.


 
You can add multiple stages in the Process flow and each stage can have multiple steps. You can use the Required field to ensure that one can move to the next stage only if the required step is completed. Here is an example of an existing process flow provided for Phone to Case



Apart from adding Stages and Steps for a single entity. You can also design the process to include multiple entities like the Lead to Opportunity Sales Process. Using the +/- options next to the primary entity you can go ahead and include another entity and make sure the next steps and stages are based on the other entity selected. 



    
Role-based Processes: 

Just like we can design role based forms in CRM, the Business Process flows also provide the option of designing different processes for different kinds of users. You can assign roles to the Processes using the Enable Security Roles option
 


Switching Processes: 

You are allowed to create multiple processes per entity and therefore you do have an option to switch the process for a record mid-way. You can start using a particular process for a record and then if you would like switch the record to another process if you find that more appropriate for the record. To switch process you should have access to that process through security roles.


You can change process using the option called “Switch Process” in the ribbon menu as highlighted below.




As soon as you click this button below window will appear and list all the business processes created for that entity.




You can select the process to which you would like to switch and the page will get refreshed with the new selected process flow.

With the Business Process flows now open for designing by end users, we can now truly welcome Process-Driven UI for Dynamics CRM.