Could somebody tell me if there is a better way to schedule a new workflow and cancel an existing workflow on record creation? In CRM Dynamics, I have a Contact with a sub-grid containing Request records. I have a plugin that runs on Request record creation (Post-Operation, Synchronous) to update Contact record and then start a workflow on Contact i.e. before new workflow is started an old workflow need to be cancelled.
This approach works most of the time, but if the Request records are added very quickly with a short gap, I usually end up with two workflows running. It looks like the plugin didn’t have time to check the existing workflow. Is there any way to ensure there is only one instance running based on the newly created record?
This is my method used to cancel a workflow:
private void CancelRunningWorkflows(EntityReference contactRef, Guid workflowId)
{
try
{
// query to find the workflow name
QueryExpression workflowQuery = new QueryExpression("workflow")
{
ColumnSet = new ColumnSet("name"),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression("workflowid", ConditionOperator.Equal, workflowId),
new ConditionExpression("type", ConditionOperator.Equal, 1), // 1 = Definition
new ConditionExpression("statecode", ConditionOperator.Equal, 1) // 1 = Activated
}
}
};
EntityCollection workflows = context.OrganizationService.RetrieveMultiple(workflowQuery);
if (workflows.Entities.Count == 0)
{
throw new InvalidPluginExecutionException("Workflow definition not found or not active.");
}
string workflowName = workflows.Entities[0].GetAttributeValue<string>("name");
QueryExpression asyncQuery = new QueryExpression("asyncoperation")
{
ColumnSet = new ColumnSet("asyncoperationid", "regardingobjectid", "name", "statecode", "statuscode"),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression("regardingobjectid", ConditionOperator.Equal, contactRef.Id),
new ConditionExpression("name", ConditionOperator.Equal, workflowName),
new ConditionExpression("statuscode", ConditionOperator.In, new int[] { 0, 10, 20 }) // 0 = Waiting for Resource, 10 = Waiting 20 = In Progress
}
}
};
EntityCollection asyncOperations = context.OrganizationService.RetrieveMultiple(asyncQuery);
foreach (Entity asyncOperation in asyncOperations.Entities)
{
Entity operation = new Entity("asyncoperation")
{
Id = asyncOperation.Id
};
operation["statecode"] = new OptionSetValue(3); // 3 = Canceled
operation["statuscode"] = new OptionSetValue(32); // 32 = Canceled
context.OrganizationService.Update(operation);
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("An error occurred while cancelling the workflow.", ex);
}
}