How to prevent endless loop without ExecutionContext.CallerOrigin in Microsoft Dynamics CRM 2011?

When creating a plugin in Microsoft Dynamics CRM 4.0, you can use the following to check the origin of the event that caused the plugin.

public void Execute(IPluginExecutionContext context) { if (context.CallerOrigin.GetType() == CallerOrigin.WebServiceApi.GetType()) { return; } plugin code here... } 

This will let you check if the action was triggered by the user in the form, web service or workflow, etc.

I have a synchronization application that creates and updates objects via WCF and does not want the plugin to be executed when this happens, only when users edit entities (to prevent endless loops in the synchronization process).

IExecutionContext.CallerOrigin was removed in MS Dynamics CRM 2011 , so what is the new way to do this?

I thought there might be a way to set IExecutionContext.CorrelationId in WCF calls and then check for a specific Guid for it in the plugin, but I haven't had any luck with that yet.

+6
source share
4 answers

Have you looked inside IPluginExecutionContext.InputParameters?

Another option is to change your plugin so that nothing is updated if there were no changes, which would prevent the possibility of an endless loop.

+2
source

Although it seems like this was asked some time ago (and I believe that OP has already found its solution!) I stumbled upon this, looking for a similar answer recently. Further research was required to find out what I needed, so for this reason I will add it here also for everyone who comes across this.

Initially, if you are looking for it, this property is deprecated. Presumably because it was unreliable, but there were several reasons why we needed CallerOrigin in MSCRM 4.0. On the other hand, there are ways to get around this and obsolete:

Preventing endless loops (more than 2 plugins)

It is for this reason that I was looking for CallerOrigin and how I came across this question. I just wanted the plugin to work if it came from the user in the form, and not from another plugin (i.e.Asyc process / webservice). In my case, the difference is that it is "more than two plugins", it is very important because I can not use InputParameters to solve the problem. My example looked like the following:

  • Update plugin for parent object. If the Status parameter on the parent object was set to Approved, I later wanted to set the status on all child objects to Approved.

  • Update plugin for child object. If a set of parameters called "Status" on a child has been set to "approved" and all other children of the same parent set this parameter to "Approved". I also needed to update the status on parent and approved.

This causes an endless cycle if you are not protecting yourself from it. You also cannot use InputParameters to solve it. One of the main solutions is to use a depth check:

 context.PluginExecutionContext.Depth 

If it is more than 1, it was called by another plugin / workflow. Note. If you have a workflow that starts the initial update, you can be careful what value you check.

Preventing synchronization with a standalone client

We were given various properties to help us distinguish them. Use them instead:

 context.PluginExecutionContext.IsExecutingOffline context.PluginExecutionContext.IsOfflinePlayback 

The response is different depending on what happened.

Okay, so this is the only scenario when we really need CallerOrigin. The only way I think you can do this is by checking the type of the PluginExecutionContext itself. I know that for async this is type:

 Microsoft.Crm.Asynchronous.AsyncExecutionContext 

and for plugins it looks like this:

 Microsoft.Crm.Extensibility.PipelineExecutionContext 

Not sure what it is when you come from an external source, unfortunately, I don’t have the code yet to check and understand this. Outside of all this, you probably have to check:

 PluginExecutionContext.ParentContext 

The only other method I came across to detect where the update came from was using a special flag in the form. So you can create an OptionSet called "OriginOfChange" (or something similar) with parameters

  • CRM Form (Javascript onsave)
  • Workflow
  • Plugin
  • and etc.

Then, what ever updates, the object sets this field during the update. Thus, you can check the input parameters each time to find out where the update came from.

This last method is most likely the safest to use if you need to respond differently depending on the source.

+11
source

This is a streaming solution: "Just check the context.depth property if it is more than 1 return"

It worked great for my update plugin, where I updated the object inside it, as a result of which the plugin was launched twice, but the second time it checked the depth and exited.

Update

The safest way is to use common parameters , not the depth of the plugin. If the only thing checked is the depth of the plugin, then at any time another plugin launches another plugin, it will not be executed because its depth is 2, even if this is the first time the plugin has raised the Update event.

+3
source

Depth of execution, not recursion. You can get a depth of> 1 the first time you run the plugin. Think of it as a level in the execution pipeline (in fact, this is the depth of the execution stack), someone got it first, when the execution is passed, the depth increases by 1, so the next line performs some other operation and before it starts again to the depth level +1 to the depth, Dynamics is now executing your plugin, your depth will be 3 (Initial 1 [+1 | +1]). CRM 2011 by default is limited to 8 by default, and online is limited to a depth of 16.

So, preventing recursion using the depth that you simply ACCEPTS, you cannot claim it.

MSX Property IExecutionContext.Depth

My 2 cents, best regards Eric Ryan

-3
source

Source: https://habr.com/ru/post/888183/


All Articles