CRM 2011 Plugins – Avoiding Infinite Loops

Roshan Mehta, 28 April 2013

When developing plugins for Microsoft Dynamics CRM 2011, there are scenarios in which the execution of your custom code can result in an infinite loop. This leads to unnecessary execution of plugins and can potentially impact the performance of CRM, as well as the user experience. In this post, we will take a look at the Depth property of the IPluginExecutionContext service object and see how it can be used to eliminate the risk of infinite loops.

 CRM 2011 Plugins Avoiding Infinite Loops*

Before we see how to use the Depth property, let’s take a look at a scenario. Assume your CRM implementation consists of the Contact entity and a custom entity called Member. The requirement for the system is to keep data on the Contact and Member entities synchronised, so that the following business rules apply:

1. When a Member is created, a corresponding Contact record is created (if one does not already exist)

2. When certain details on the Member is updated, details on the corresponding Contact record must also be updated

3. When certain details on the Contact record is updated, details on the corresponding Member record must also be updated

You can see that this type of business logic will require a plugin to be registered on create of Member, and on update of both Contact and Member. You will also notice that updating a Member triggers an update of the Contact, which again triggers an update of the Member and so on.

Firstly, let’s see what happens if we deploy such a plugin without any consideration for handling infinite loops. I have updated the “Full Name” field on the Member, which should try to update the “Full Name” field on the Contact.

 CRM 2011 Plugins Avoiding Infinite Loops

The CRM platform throws an error stating that it has identified an infinite loop. This usually happens after the number of iterations reaches a maximum of 8. We can fix this by adding a depth check at the start of our plugin code, just after we initialize each of the service objects.

IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
_sdk = factory.CreateOrganizationService(context.UserId);
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

if (context.Depth > 1) { return; }

Notice that last line which checks if the plugin has run more than once, and if so, executes a return statement to cancel out of the plugin. Now when we run the plugin, we shouldn’t run into an infinite loop.

You must be careful when using the Depth property as there are more complex scenarios that you may run into. For example, a data import may trigger a workflow to update the “Full Name” of a Member, which in turn will execute our plugin. In this case, the Depth will be 3 at the first execution of the plugin. If you left the code snippet above unchanged, the plugin logic will never get executed.

*Image from http://3.bp.blogspot.com/_F7vpRIjAvYI/TIU7VpNlbzI/AAAAAAAABoI/s2clJ4LoWO0/s1600/image.png