Sunday, October 27, 2013

Microsoft Dynamics CRM 2013: Actions walkthrough for .Net and JavaScript developers

I believe that almost every developer for Dynamics CRM faced with scenario when he/she had to invoke some complex logic on a server side, pass parameters and receive a response back. Before CRM 2013 we used workarounds similar to this one. Once Dynamics CRM 2013 was released we have got solution that would not require ‘magic’.
Following posts describe how to create Actions in CRM side:
http://garethtuckercrm.com/2013/10/15/crm-2013-new-features-actions/
http://inogic.blogspot.com/2013/09/introduction-to-actions-in-crm-2013.html
This is how my Custom Action look like:

Usage of Custom Actions in .Net:
1. Actions are available for Early binding. To get Early Binding classes you need to run CrmSvcUtil (you can find this utile in SDK package, bin folder) using following command line:
CrmSvcUtil.exe /url:http://crm:5555/contoso/XRMServices/2011/Organization.svc /out:Classes.cs /namespace:CustomActions /serviceContextName:CrmServiceContext /generateActions

My command sample can be used for OnPremise deployments. Detailed information regarding generating of Early Binding classes for all types of deployments you can find in this article.

Add generated Classes.cs to your project and start using it:


Sample of code that instantiates request, executes it and receives result:

slick_CustomActionsTestRequest request = new slick_CustomActionsTestRequest()
{
    BoolInArgument = true,
    DateTimeInArgument = DateTime.Now,
    DecimalInArgument = decimal.Zero
};

slick_CustomActionsTestResponse response = service.Execute(request) as slick_CustomActionsTestResponse;
//Processing of response

 2. If you don’t like or don’t want to use Early binding you case use OrganizationRequest/OrganizationResponse. Sample of code:

OrganizationRequest request = new OrganizationRequest("slick_CustomActionsTest");
request["BoolInArgument"] = true;
request["DateTimeInArgument"] = DateTime.Now;
request["DecimalInArgument"] = decimal.Zero;

OrganizationResponse response = service.Execute(request);

bool boolvalue = (bool)response.Results["BoolOutArgument"];


Usage of Actions in JavaScript:

1. Prepare Soap Xml request. The easiest way to do it is to use SoapLogger application that is the part of SDK package. Detailed information you can find here. Sample of code that captures request and response follows:

using (StreamWriter output = new StreamWriter("output.txt"))
{
    SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

    OrganizationRequest r = new OrganizationRequest("slick_CustomActionsTest");
    r["BoolInArgument"] = true;
    r["DateTimeInArgument"] = DateTime.Now;
    r["DecimalInArgument"] = decimal.Zero;
    r["EntityCollectionInArgument"] = new EntityCollection()
    {
        EntityName = "account"
    };
    r["EntityInArgument"] = new Entity("account");
    r["EntityReferenceInArgument"] = new EntityReference("account", Guid.Empty);
    r["FloatInArgument"] = double.Parse("0");
    r["IntegerInArgument"] = 0;
    r["MoneyInArgument"] = new Money(decimal.Zero);
    r["PicklistInArgument"] = new OptionSetValue(1);
    r["StringInArgument"] = "";

    slos.Execute(r);
}

In output.txt file you can find following:

<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>
  <s:Body>
    <Execute xmlns='http://schemas.microsoft.com/xrm/2011/Contracts/Services' 
        xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
      <request i:type='b:slick_CustomActionsTestRequest' 
        xmlns:a='http://schemas.microsoft.com/xrm/2011/Contracts' 
        xmlns:b='http://schemas.microsoft.com/xrm/2011/slick/'>
        <a:Parameters xmlns:c='http://schemas.datacontract.org/2004/07/System.Collections.Generic'>
          <a:KeyValuePairOfstringanyType>
            <c:key>BoolInArgument</c:key>
            <c:value i:type='d:boolean' xmlns:d='http://www.w3.org/2001/XMLSchema'>true</c:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <c:key>DateTimeInArgument</c:key>
            <c:value i:type='d:dateTime' xmlns:d='http://www.w3.org/2001/XMLSchema'>2013-10-27T01:08:29.0439804+03:00</c:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <c:key>DecimalInArgument</c:key>
            <c:value i:type='d:decimal' xmlns:d='http://www.w3.org/2001/XMLSchema'>0</c:value>
          </a:KeyValuePairOfstringanyType>
        </a:Parameters>
        <a:RequestId i:nil='true' />
        <a:RequestName>slick_CustomActionsTest</a:RequestName>
      </request>
    </Execute>
  </s:Body>
</s:Envelope>


this is the Soap Xml request you will use.

2. Use this Soap request with CustomAcionExecutor.js library I’ve developed. Sample of usage:

CustomActionExecutor.Execute(
    {
        requestXml: requestXml,
        async: true,
        successCallback: function(result){
        },
        errorCallback: function (e) {
        }
    });

 In result you will get parsed response from server:



Source code of CustomActionExecutor.js: