Development, Howto

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

I believe that almost every developer for Dynamics CRM has faced a scenario where 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. When Dynamics CRM 2013 was released, we got a solution that would not require ‘magic’.
The 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 what my Custom Action looks 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 the SDK package, bin folder) using the 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 also be used for OnPremise deployments. Detailed information regarding generating Early Binding classes for all types of deployments are covered in this article.

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

Here is a 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 can 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 the SoapLogger application that is the part of the SDK package. Detailed information you can find here. A 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 the 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. Here’s a sample of usage:

CustomActionExecutor.Execute(
    {
        requestXml: requestXml,
        async: true,
        successCallback: function(result){
        },
        errorCallback: function (e) {
        }
    });
When you do, you will get a parsed response from the server:

 

 

Source code of CustomActionExecutor.js:

UPD For visitors who don’t see download url on top of this message.

Alternative CustomActionExecutor.js download URL.

5 Comments

  1. Hello,

    I do not see a link to download the source of your library. I’m trying to do precisely what you’ve outlined.

    Thanks in advance,
    Hany

    1. That’s weird. I will upload file directly inside blog and leave download Url inside this post.

  2. Hello,

    Why is that my code for example required

    request[“Target”] = new EntityReference(“account”, entity.Id);
    before I can execute the request?

    1. Cyrus,
      I believe that you created Entity – Related action. In my example I used Global action.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.