I created a custom entity City.
City has 3 fields - the built-in new_name field, new_value (int), new_description (string).
I created a WF (async) that runs when a new record is being created, or when either description or value change. The WF simply concatenates value and description and updates the name (e.g. new_name = new_value new_description)
Now, I also created a Plugin with the following step (step also contains both pre and post images) :
- Message: Update
- Filtering Attributes: new_description, new_name
- Stage: Post-Operation
- Mode: Synchronous
The plugin simply updates the value if either description or name have really changed, similar to the WF. (e.g. new_value = new_name new_description)
Questions:
- In theory, will this cause an infinite loop? If I change the new_value of the record, the WF runs and updates the new_name which then triggers the plugin to run and update the value, which then triggers the WF to run and so on.
- How will this affect context.Depth? will it always be equal to 1? Does the depth increase only when the plugin gets triggered from within itself?
For testing purposes, I have disabled the WF and currently trying to understand why the above described plugin still goes into an infinite loop (triggered multiple times when record is being saved)
This is my code:
public void Execute(IServiceProvider serviceProvider) { // Obtain the tracing service ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); // Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // The InputParameters collection contains all the data passed in the message request. if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; // Obtain the organization service reference which you will need for // web service calls. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); try { if (context.Depth > 1) return; if (context.PreEntityImages.Contains("PreImage") && context.PreEntityImages["PreImage"] is Entity && context.PostEntityImages.Contains("PostImage") && context.PostEntityImages["PostImage"] is Entity) { Entity preImage = context.PreEntityImages["PreImage"]; string preName = preImage.GetAttributeValue("cre9f_name"); string preDesc = preImage.GetAttributeValue("cre9f_s_description"); Entity postImage = context.PostEntityImages["PostImage"]; string postName = postImage.GetAttributeValue("cre9f_name"); string postDesc = postImage.GetAttributeValue("cre9f_s_description"); if ((!String.IsNullOrEmpty(preName) || !String.IsNullOrEmpty(preDesc)) && (!String.IsNullOrEmpty(postName) || !String.IsNullOrEmpty(postDesc))) { tracingService.Trace("Pre Name: {0}, Post Name: {1}, Pre Desc: {2}, Post Desc: {3}", preName, postName, preDesc, postDesc); Entity update = new Entity(entity.LogicalName); update.Id = entity.Id; tracingService.Trace("Updating entity {0} with GUID {1}", update.LogicalName, update.Id); if (preName != postName && preDesc == postDesc) update["cre9f_s_value"] = postName " - " preDesc; else if(preName == postName && preDesc != postDesc) update["cre9f_s_value"] = preName " - " postDesc; else if(preName != postName && preDesc != postDesc) update["cre9f_s_value"] = postName " - " postDesc; else update["cre9f_s_value"] = preName " - " preDesc; tracingService.Trace("Updating field {0}", update["cre9f_s_value"].ToString()); service.Update(update); // throws error here tracingService.Trace("Update succeeded"); } } } catch (FaultException ex) { throw new InvalidPluginExecutionException("An error occurred.", ex); } catch (Exception ex) { tracingService.Trace("An error occurred: {0}", ex.ToString()); throw; } } }
P.S. I'm using the Sales Trial version, if that matters.