The Microsoft Dynamics CRM Blog
News and views from the Microsoft Dynamics CRM Team

Microsoft Dynamics CRM: Workflow Authoring Best Practices

Microsoft Dynamics CRM: Workflow Authoring Best Practices

  • Comments 2

The Microsoft Dynamics CRM workflow engine provides powerful functionality for implementing custom business logic in a CRM deployment. However, it also lends itself to complex problems and design mistakes which can result in expensive maintenance and confused users. This article explains in detail a few important considerations when implementing workflows and custom workflow activities in CRM.

1. Composition with child workflows.

The workflow pattern is in general one of composition of smaller steps. Therefore, when creating a workflow, think about which parts of the workflow can be generalized as a "sub-process" and be reused in multiple workflow definitions. By isolating these smaller processes, one can define child workflows which can then be called from multiple workflow definitions. The advantage is that the child workflow can be easily modified as opposed to modifying multiple workflow definitions. It will also make it simpler to define future workflows that might be a composition of smaller processes or business logic. One important consideration is that child workflows are executed asynchronously with respect to the parent workflow. Therefore, you should not make use of child workflows for sub-processes which require sequential execution.

2. Awareness of persistence points in workflow definitions.

If you have a long workflow that might take a long time to execute you will need to consider whether the workflow will persist and what that implies. A workflow can be persisted because of multiple reasons: The workflow instance is waiting for some event to occur, the CrmAsyncService is stopped or the workflow instance explicitly requests to be persisted by executing an activity with the PersistOnCloseAttribute. In any case, the workflow engine unloads the workflow instance and persists it to the database until a user manually resumes the workflow or an event occurs which resumes the workflow automatically. The important considerations are

1) At what point does the workflow persist? The workflow will persist up to the step when the last activity is marked as a persistence point. Therefore, when it resumes, it will re-execute all the steps after the last persistence point. This is important if you have logic in your workflow which you want to guarantee does not execute more than once. Note that workflow instances are automatically persisted after the following CRM steps: create, update, send email, send email from template, assign, change status, child workflow and stage. For custom activities you can add [PersistOnClose] attribute to the activity class. (see http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.persistoncloseattribute.aspx).

2) When is the workflow going to resume? If the workflow will wait on an event that might never happen or take years to occur, then the database will soon contain thousands of waiting workflows which could affect performance. You should consider a design in which this situation is minimized. For example a workflow that waits on an opportunity to be marked as “won” can wait forever and the condition never meets. Instead wait on the opportunity to be closed and then check the status reason once it is marked as closed; if it was not marked as “won” you might want to add a Stop Workflow step at that point.

3. Write "atomic" custom activities.

Custom workflow activities should not implement the entire logic of the workflow, they are ideally small "atomic" steps that will make part of larger workflows. Because custom activities don't have the ability to control persistence, they should never cause the workflow to go idle or persist in the middle of a custom activity. Generally, it is better to have multiple custom activities that are called in sequence from a parent workflow than one large custom activity that implements all the logic in sequence. This also follows from the principle of workflow as a composition pattern. For example if your process is to take custom actions A, B and C when an account is opened, it is generally better to write a custom activity for each A, B and C separately and add a step for each activity in your workflow as opposed to writing a custom activity that implements A, B and C sequentially and then add a single step to the workflow to include this custom activity.

4. Correct use of "Execution Time".

The CRM workflow designer provides a property called "Execution Time" which can be used in dynamic expressions such as "if Account(CreatedOn) + 10 days < workflow(ExecutionTime)". The meaning of this property is neither the time at which the workflow is published nor the time the workflow instance starts. The actual value of this property is the real time when the workflow evaluates an expression that contains this property. Therefore, expressions such as "Wait until 1 day after workflow(ExecutionTime)" will never succeed and the workflow will wait and resume once a day forever causing performance problems. If you want your workflow to wait for a specific amount of time you should use the wait step and configure the condition as: workflow – timeout – equals – {Duation}. This will unload the workflow and resume execution after the specified time duration has passed.

5. Plugins Vs. Workflows.

This is a common dilemma in CRM and there is no exact formula to find the best implementation method for a specific situation. However, this article provides some general rules of thumb that can be used to decide whether to use a plugin or a workflow: http://blogs.msdn.com/lezamax/archive/2008/04/02/plug-in-or-workflow.aspx

Cheers,

Gonzalo Ruiz



  • Your example of incorrect use of Execution Time is very helpful.  

    Can you possibly elaborate or provide an example of how you could correctly use "Execution Time" as part of a workflow?  

    Thanks!

    Linda.

  • Consider a scenario in which you have a workflow that creates a task and then sends you an email when the task is completed and informs you of the exact time when the task was completed.

    You would define a workflow like:

    - Create task X

    - Wait until task X is completed

    - Send email to you with subject = "Task completed on: " {workflow(ExecutionTime)}.

    In the above example, even though the workflow started before the task was even created, the email sent to you will have the time at which the workflow was resumed (the task was completed).

    I hope this answers your question.

Page 1 of 1 (2 items)
Leave a Comment
  • Please add 2 and 8 and type the answer here:
  • Post