Tip #730: Turn your CRM into API machine

Locked black boxWhen people ask me to describe the differences between custom workflow activities and custom actions, I always use the following definitions:

  • Custom workflow activities. A functional blackbox created by the developers to be consumed by the business
  • Custom activity. A functional blackbox created by the business to be consumed by the developers

There is more to the story, of course. As a developer, I always wanted to have the ability to extend server-side of CRM with custom API that I could call from all places code: javascript, custom utilities, plugins. For business users: nothing to see here, move along. Custom actions are the perfect mechanism to add this extensibility to CRM organization.

  1. Create custom action in CRM for the entity of your choice.Define custom action
  2. Don’t add any steps, simply activate the action.
  3. You now have a custom message. Don’t believe me? Open [your_org_url]/api/data/v8.1/$metadata and search for your action name. Hint: use Chrome and stock up some patience.
<Action Name="georged_NormalizeCustomer" IsBound="true">
   <Parameter Name="entity" Type="mscrm.contact" 
      Nullable="false"/>
</Action>
  1. Create a plugin using your action name as a message, entity contact, synchronous pre-operation.Register plugin
  2. Write some wicked code in plugin (I chose to swap first and last names without telling the business):
var orgSvc = localContext.OrganizationService;
var contactId = localContext.PluginExecutionContext
                .PrimaryEntityId;

var contact = orgSvc.Retrieve(
    "contact", contactId,
    new ColumnSet("firstname", "lastname"));

var temp = contact["firstname"];
contact["firstname"] = contact["lastname"];
contact["lastname"] = temp;

orgSvc.Update(contact);
  1. You now have a custom API that you can call wrap up and call like this:
public static class Extensions
{
  public static void NormalizeCustomer(
       this IOrganizationService service, 
       Guid contactid)
  {
    var request = new OrganizationRequest
      ("georged_NormalizeCustomer");

    request.Parameters.Add("Target", 
      new EntityReference("contact", contactid));

    var response = service.Execute(request);
  }
}
...
IOrganizationService svc = getityourself;
Guid contactid = whatever;

// call our "API"
svc.NormalizeCustomer(contactid);

Why is it better than simple client-side code? Because I can call this API from various places using various languages and then change the implementation on the backend (e.g. swap first and middle names instead) and I wouldn’t have to change anything on the caller side.

Leave a Reply

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