I'm a beginner at writing D365CE Plugins and have a question regarding plugins that run synchronously, post operation and creates recursion.

I understand that it's the use of the IOrganizationService update in the code below that's causing the recursion when ran during the update event. But is it possible to create a plugin that runs synchronously and gets a post operation value from the record and updates another field on the same record without causing recursion? I've looked at checking context.depth but it seems to not be recommended due to possible data inconsistencies.

PluginRegistrationTool info:
Message: Update
Primary Entity: quote
Filtering attribute: statecode
Pipeline: PostOperation
Execution Mode: Synchronous

Example code:

public class Quote_SetEffectiveDates : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(null);

                try
                {
                    if (context.PrimaryEntityId != null)
                    {
                        ColumnSet quote_Col = new ColumnSet("statecode");
                        Entity quote = service.Retrieve("quote", context.PrimaryEntityId, quote_Col);
                        int statecode = quote.GetAttributeValue<OptionSetValue>("statecode").Value;
                      
                        if (statecode  == 1)
                        {
                            DateTime currentDate = DateTime.UtcNow.Date;

                            Entity quote_Update = new Entity
                            {
                                LogicalName = quote.LogicalName,
                                Id = quote.Id,
                            };
                            quote_Update["effectivefrom"] = currentDate;
                            quote_Update["effectiveto"] = currentDate.AddDays(30);

                            service.Update(quote_Update);
                        }
                    }
                }

                catch (FaultException<OrganizationServiceFault> ex)
                {
                    throw new InvalidPluginExecutionException("An error occured in Quote_SetEffectiveDates plugin", ex);
                }

                catch (Exception ex)
                {
                    tracingService.Trace("Quote_SetEffectiveDates; {0}", ex.ToString());
                    throw;
                }
            }
        }
    }

I've tried:

  1. Registering on Pre Operation, results in not getting Post Operation value (obviously).
  2. Running the plugin Asynchronously solves the issue (since it creates a new update event after the main operation?), but would strongly prefer to have it synchronously if possible.
1

There are 1 answers

3
Henk van Boeijen On

Since the filtering attribute is statecode your plugin is only triggered when that field is modified. It will not be triggered on an update of the effectivefrom and effectiveto fields.

Therefore it is safe to register the step on the post operation stage, in synchronous mode.

In other scenarios, where a field is modified that is actually part of the filtering attributes collection, the IPluginExecutionContext.Depth property can be checked to determine if a recursive update is encountered.