6

在 Microsoft Dynamics CRM 4.0 中创建插件时,您可以使用以下内容检查导致插件触发的事件的来源。

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

这将允许您检查该操作是否由表单中的用户、Web 服务或工作流等引起...

我有一个通过 WCF 创建和更新实体的同步应用程序,并且不希望插件在发生这种情况时执行,仅在用户编辑实体时执行(以防止同步过程中的无限循环)。

IExecutionContext.CallerOrigin已在 MS Dynamics CRM 2011 中删除,那么执行此操作的新方法是什么?

我在想可能有一种方法可以设置IExecutionContext.CorrelationIdWCF 调用,然后检查插件中的特定 Guid,但我还没有运气。

4

4 回答 4

12

虽然这似乎已经被问过一段时间了(我认为 OP 现在已经找到了他的解决方案!)我最近遇到了它,正在寻找类似的答案。需要进一步研究才能找到我需要的东西,因此我也会在这里为遇到它的其他人添加它。

Firstly, if you are looking for it, this property has been made obsolete. Supposedly because it was unreliable, but there were a few reasons why we needed the CallerOrigin in MSCRM 4.0. On the other hand, there are ways around this becoming obsolete too:

Prevent infinite loops (over 2 plugins)

This was the reason I was looking for the CallerOrigin and how I came across this question. I only wanted the plugin to fire if it came from a user on the form, not from another plugin (i.e. asyc process/webservice). In my case the distinction of it being "over 2 plugins" is quite important, because I cannot use InputParameters to solve the problem. My example was similar to the following:

  • Update Plugin for "Parent" Entity. If optionset called "Status" on the parent entity was set to "Approved" I subsequently wanted to set a status on all the child entities to "Approved" as well.

  • Update Plugin for "Child" Entity. If the optionset called "Status" on the child entity was set to "approved", and all other children of the same parent has this set to "Approved" I needed to update the Status on the parent to approved as well.

This causes an infinite loop if you don't protect yourself against it. You also cannot use the InputParameters to solve it. One basic solution is to use depth checking:

context.PluginExecutionContext.Depth

If this is greater than 1 it has been called by another plugin/workflow. Note: If you have a workflow that is triggering the initial update you might want to be careful with what value you are checking for.

Prevent syncing issues from an offline client

We've been given different properties to help us distinguish these ones. Use these instead:

context.PluginExecutionContext.IsExecutingOffline
context.PluginExecutionContext.IsOfflinePlayback

Reacting differently depending on what the origin is

OK, so this is the only scenario where we really do need the CallerOrigin. The only way I think you'd be able to do this is by checking the type of the PluginExecutionContext itself. I know for async it's the type:

Microsoft.Crm.Asynchronous.AsyncExecutionContext

and for plugins it seems to be:

Microsoft.Crm.Extensibility.PipelineExecutionContext

Not sure what it is when coming from an external source, I unfortunately don't have any code available at the moment to test and figure this out. Outside of all that you would probably have to check:

PluginExecutionContext.ParentContext

The only other method I've come across for detecting where the update came from is using a custom flag on the form. So you could create an OptionSet called "OriginOfChange" (or something similar) with the options

  • CRM Form (JavaScript onsave)
  • Workflow
  • Plugin
  • etc.

Then what ever updates the entity sets this field during the update. In this way you could check the Input Parameters each time to see where the update has come from.

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

于 2012-03-13T16:16:12.517 回答
3

This thread's solution is to "Just check for context.depth property, if it's greater then 1 return"

It worked perfectly fine for my update plugin where I was updating the entity within it, causing the plugin to get fired twice, but on the second time, it checked for the depth and exited.

Update

By far the safest method is to use the shared variables rather than plugin depth though. If the only thing that is checked is the plugin depth, then anytime another plugin triggers another plugin, it won't execute because it's depth is 2, even though it is the first time the plugin has fired for the Update event.

于 2012-08-02T15:13:10.210 回答
2

您是否查看过 IPluginExecutionContext.InputParameters 内部?

另一种选择是修改您的插件以在没有更改的情况下不更新任何内容,这将防止无限循环的可能性。

于 2011-05-17T16:31:18.317 回答
-3

The Depth is of execution, not recursion. You can recieve a Depth > 1 the first time your plugin got executed. Think of it as a Level in the execution pipeline (actually is the execution stack depth), some one got it first, when execution is passed the Depth is increased by 1, so the next in line do some other operation and before passing it again to the pipe increments +1 depth, now Dynamics executes your plugin, your depth would be 3 (Initial 1 [+1|+1]). CRM 2011 on-premise is limited by default to 8 and on-line is limited to a depth of 16.

So, recursion prevention by using the Depth you are just ASSUMING it, you can not assert it.

MSDN IExecutionContext.Depth Property

My 2 Cents, Best Regards Eric Arean

于 2013-11-05T14:41:59.883 回答