Monday, March 14, 2016

How to set EntityCollection output parameters in custom actions

One of the greatest things about custom actions is that they support defining input and output arguments of type EntityCollection. However, because the process designer does not support UI for consuming this type then we have to do it via code. This article explains some tips if you think that could be useful for you.

If you are familiar with custom actions introduced in CRM 2013, you might have noticed that they have input and out parameters. What is interesting is that a data type “EntityCollection” is supported which means your action can take as input a number of entities or it can produce a number of entities as the result (like RetrieveMultiple). The first thing you might wonder is why the heck would you want to use EntityCollection as output arguments, it if can’t even be consumed from the workflow designer. But if you are reading this post chances are you have a scenario in mind. In many cases you might want EntityCollection as input parameters, but is more unusual to need an output of EntityCollection. I can think of a few scenarios, and most recently I had to use this for encapsulating a set of business logic in a custom action which would then return a set of entities. This custom action might be consumed from external systems and makes it simple to implement all the business logic in a custom action so from the external clients it will be straight-forward to consume this action without having to call various SDK operations and implementing the logic at the client.

Once you have identified the scenario you need to keep in mind that the result (output) of your custom action will need to be consumed only from code (external client, JavaScript, plugins, etc.) because unfortunately the CRM native process designer is still incapable of understanding entity collections. Now, how can you set an output parameter in your custom action that is type of EntityCollection if you cannot do that via the process designer?

My first instinct was to implement a custom workflow activity and then insert it in the action definition as a custom process step:

Inside the custom workflow activity, you have full access to the IExecutionContext, including the InputParameters and OutputParameters collections. Therefore, I assumed I you could set your EntityCollection output parameter via code as seen below:

While technically this compiles and executes fine, I was surprised to see that when calling my action, the output parameter was blank, even though I was setting the value from the custom workflow activity. I imagine this might be due to the fact that output parameters are only set after the main pipeline operation and perhaps the custom workflow activity is executing a little bit before that thus all output parameters get wiped after the main operation but before the value is returned to the client.

Therefore, I had to change my approach. I implemented the exact same code, but this time I used a plugin registered on the PostOperation of my custom action, this way I can make sure that the main operation has already passed and whatever I store in the output parameters collection will be returned to the calling client. This finally worked!

So the lesson here is that setting output parameters (in general) must be done in the PostOperation part of the pipeline, therefore it can only be done via plugins!

Keep in mind that setting input parameters as EntityCollection is more trivial because it is up to the calling client to pass those parameters, and in this case, although you cannot consume those input parameters inside the action process designer, you will be able to access them from either a custom workflow activity inside your action or from plugins. I tend to prefer custom workflow activities because this way your entire logic is defined inside the action itself and there is no additional logic running in plugins, but it depends on the scenario and complexity too.