2011-05-16 73 views
6

在Microsoft Dynamics CRM 4.0中创建插件时,可以使用以下内容来检查导致插件触发的事件的来源。如何防止Microsoft Dynamics CRM 2011中没有ExecutionContext.CallerOrigin的无限循环?

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

这将允许你检查行动是由一个形式的用户引起的,通过Web服务或工作流程等..

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

IExecutionContext.CallerOrigin已在MS Dynamics CRM 2011,中删除,那么采用什么新方法可以做到这一点?

我在想,可能有办法在WCF调用中设置IExecutionContext.CorrelationId,然后检查它在插件中的具体GUID,但我还没有任何运气。

回答

2

你看过IPluginExecutionContext.InputParameters吗?

另一种选择是修改插件,如果没有任何更改,就不会更新任何内容,这将防止无限循环的可能性。

+0

我可能有,如果变化是由指定的用户发起的,不更新,因为会被同步工具的变化。我真的想避免双重同步,而不是无限循环:)我可以在同步工具 – csjohnst 2011-05-19 06:16:59

+0

context.InitiatingUserId给你的GUID ID停止循环。在我的情况下,我想排除单个用户从解雇插件,这就做到了。 – kmria 2015-03-18 10:21:52

11

虽然这似乎已经问过一段时间了(我认为OP已经找到他的解决方案了!)我碰到它最近寻找类似的答案。为了找到我需要的东西,我花了进一步的研究,因此我也将其添加到其他任何碰到它的人。如果你正在寻找它,这个属性已经过时了。据说这是因为它不可靠,但为什么我们需要MSCRM 4.0中的CallerOrigin有几个原因。在另一方面,也有解决这个过时太方式:

防止无限循环(超过2插件)

这就是我一直在寻找的CallerOrigin的原因,我碰到这个问题怎么来的。如果插件来自表单上的用户,而不是其他插件(即asyc process/webservice),我只希望该插件能够触发。在我的情况下,“超过2个插件”的区别非常重要,因为我无法使用InputParameters来解决问题。我的例子类似于以下内容:

  • 更新“父”实体的插件。如果在父实体上将称为“状态”的选项集设置为“已批准”,我随后希望将所有子实体的状态设置为“已批准”。

  • “儿童”实体更新插件。如果子实体上名为“状态”的选项集已设置为“已批准”,并且同一父级的所有其他子级都将此设置为“已批准”,则需要更新父级上的状态以进行批准。

这会导致如果不保护自己免受它的无限循环。您也不能使用InputParameters来解决它。一个基本的解决方案是使用深度检查:

context.PluginExecutionContext.Depth 

如果它大于1,它会被另一个插件/工作流调用。注意:如果您的工作流正在触发初始更新,则可能需要小心检查的是什么值。从脱机客户

防止同步问题

我们已经被赋予不同的属性,以帮助我们区分这些人。使用这些来代替:

context.PluginExecutionContext.IsExecutingOffline 
context.PluginExecutionContext.IsOfflinePlayback 

起反应不同,具体取决于原产地是

好了,所以这是我们确实需要CallerOrigin的唯一方案。我认为你能做到这一点的唯一方法是检查PluginExecutionContext本身的类型。我知道异步它的类型:

Microsoft.Crm.Asynchronous.AsyncExecutionContext 

和插件这似乎是:

Microsoft.Crm.Extensibility.PipelineExecutionContext 

不知道它是从外部来的时候,我很遗憾没有任何代码目前可用于测试并计算出结果。外面所有的话你可能要检查的:

PluginExecutionContext.ParentContext 

唯一的其他方法,我已经遇到,用于检测更新从使用自定义标记的形式来了。所以,你可以创建一个名为 “OriginOfChange”(或类似的东西)与选项的OptionSet

  • CRM表(使用Javascript的OnSave)
  • 工作流程
  • 插件

然后在更新过程中什么都会更新实体。通过这种方式,您可以每次检查输入参数以查看更新来自哪里。

如果您需要根据来源采取不同的反应,则最后这种方法最可能最安全。

+2

这是这里最好的答案,但你的时候,你断言,如果深度大于一,这个插件是由另外一个插件叫做在技术上是不正确。如果工作流会导致一个插件火,那将具有深度2,如果一系列链接在一​​起的工作流程造成火灾插件,深度将等于链流程的号码一起+ 1 – 2015-08-31 16:12:35

+0

@JosephDuty谢谢反馈,优点。我会更新这个问题来反映这一点。 – 2015-09-01 11:17:20

+0

要添加到最后2点,我添加了一些额外的细节周围的插件/工作流程和深度检查。事后看来(还有几年的经验!)我认为在为此目的使用深度检查时可能需要小心。我建议的最后一个方法是最好的(在我看来)使用。我已经将原始答案的症结留在原地,因为我认为它不应该被编辑太多。 – 2015-09-08 10:31:19

3

This线程的解决方案是“只要检查context.depth财产,如果是大于1倍的回报”

它的工作对我在那里更新其内的实体我更新的插件完全正常,导致插件被解雇了两次,但第二次,它检查了深度并退出。

更新

迄今为止最安全的方法是使用shared parameters而非虽然插件深度。如果唯一被检查的是插件深度,那么随着另一个插件触发另一个插件,它将不会执行,因为它的深度为2,即使插件第一次为Update事件触发。

+0

我一直的印象,这成为在你有,例如,工作流程或插件更新实体并触发代码的情况下不可靠。例如。如果您的插件设计为将new_fieldA添加到new_fieldB并填充new_fieldTotal,并且它应该在new_fieldA或new_fieldB更改时触发,则在运行时通过UI更改的Depth是1.我认为如果另一个插件或工作流更改new_fieldA或new_fieldB触发你的插件,然后'深度'> 1.我应该测试这个,但我在这里评论,以防其他人已经有... :) – 2012-09-10 16:18:29

-3

深度执行,而不是递归。您的插件第一次执行时,您可以获得Depth> 1。认为它是在执行流水线(实际上是执行堆栈深度)一个级别,有一个人得到了它第一,当执行传递深度增加1,因此在线路旁边做一些其他的操作,并再次传递之前,到管道增加+1深度,现在Dynamics执行你的插件,你的深度将是3(初始1 [+1 | +1])。 CRM 2011内部部署默认限制为8,联机限制为16深度。

因此,通过使用Depth进行递归预防,您只是假设它,您无法断言它。

MSDN IExecutionContext.Depth Property

我的2美分, 问候 埃里克Arean

+0

尽管我同意你在技术上是正确的,但你的答案不符合上下文关于所问的问题。如果这是对先前答案的评论,那么我可能会将其改为upvoted。 – 2014-02-27 10:04:52