When recently working on a requirement to build a Custom Action that could be used across the board through Workflows, external integrations, webresources etc. I ran into a limitation for EntityReference which could possible be a bug.
The requirement was to have the logic to be written in a plugin which would get triggered on Post Operation Stage in Synchronous mode on the custom action that was registered.
The action itself would be empty and the plugin would handle setting the Output parameters.The output parameter is of type EntityReference that targets the entity Contact which is optional(could return null value) and another Boolean parameter to indicate if the EntityReference contains data as shown below.
The plugin which sets the output parameters is configured as below, which is the typical configuration we would use in most cases.
The action works as expected when calling from external applications, web resources or when calling from other plugins.
However when trying to reuse this same action by calling it through a workflow I encountered an error where the workflow does not accept a null value to be returned for the EntityReference.
Below is a test workflow to illustrate this behavior
When invoking this workflow on a record it fails after calling the action with the error.
Looking at the error it’s pretty clear that the workflow does not like null value being passed for the Contact lookup. Unlike custom workflow activity where you could set null values for output parameters, the custom action does not seem to have the same flexibility.
The workflow works fine when the Custom Action returns data for the Contact lookup. You could work around this issue by passing a valid guid (ex:- Guid.NewGuid()) for the contact even if the record does not exist but you cannot pass an empty guid.
Since passing a random guid is not good practice when the record does not exist we ended up writing a custom workflow activity which would call our custom action and return the output. This still has the benefit of leaving all our core logic within the plugin itself although we are introducing an additional layer.
This was tested on version 9 of Dynamics 365. Hope Microsoft resolves this issue in the future.