Dynamics 365中CodeActivity与Plugin通过SharedVariables传值失效问题咨询
问题分析与解决方案
首先得明确你遇到的核心问题:你在CodeActivity里把MyUniqueKey加到了工作流的执行上下文里,但当你通过组织服务创建Quote时,这个Create操作会触发一个完全独立的插件执行上下文——它和工作流的上下文没有父子层级关系,所以你遍历ParentContext根本找不到那个SharedVariable,这就是foundKey一直为false的原因。
下面给你几个可行的解决思路,按推荐程度排序:
方案一:给Quote添加自定义标记字段(最可靠、灵活)
这是最通用的解决方案,原理是直接在你创建的Quote实体上打上标记,插件通过检查这个标记来决定是否执行:
- 先在Dynamics 365中给Quote实体新建一个布尔类型的自定义字段,比如
new_createdbycodeactivity(显示名可以叫“由代码活动创建”),设置默认值为false。 - 修改你的CodeActivity,在创建Quote的时候把这个字段设为
true:
protected override void Execute(CodeActivityContext executionContext) { var workflowContext = executionContext.GetExtension<IWorkflowContext>(); var serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>(); var service = serviceFactory.CreateOrganizationService(workflowContext.UserId); // 创建Quote实体 var newQuote = new Entity("quote"); // 其他必填字段赋值... newQuote["new_createdbycodeactivity"] = true; // 打上标记 service.Create(newQuote); }
- 在你的插件里检查这个标记,满足条件就跳过执行:
public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); if (context.MessageName == "Create") { var quoteTarget = (Entity)context.InputParameters["Target"]; // 检查标记字段,如果存在且为true,就跳过插件逻辑 if (quoteTarget.Contains("new_createdbycodeactivity") && (bool)quoteTarget["new_createdbycodeactivity"]) { // 可选:如果不需要保留标记,可以在这里把字段改回false // quoteTarget["new_createdbycodeactivity"] = false; return; } // 你的正常插件逻辑... } }
方案二:利用插件上下文的Depth属性(适合简单场景)
如果你的场景中,只有这个CodeActivity会通过嵌套调用创建Quote,那么可以通过Depth属性判断:
- 工作流的执行上下文Depth是1,它调用Create Quote生成的插件上下文Depth是2
- 手动创建Quote时,插件上下文Depth是1
修改插件代码:
public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); if (context.MessageName == "Create") { // 如果是嵌套调用(Depth>1),就跳过执行 if (context.Depth > 1) { return; } // 你的正常插件逻辑... } }
⚠️ 注意:这个方法有局限性,如果其他业务场景也会有嵌套创建Quote的情况(比如另一个插件创建Quote),会误阻止那些场景的插件执行。
方案三:通过自定义请求头部传递标记(进阶方案)
如果你不想修改实体结构,可以通过组织服务的自定义头部传递标记:
- 修改CodeActivity,创建组织服务时添加自定义头部:
protected override void Execute(CodeActivityContext executionContext) { var workflowContext = executionContext.GetExtension<IWorkflowContext>(); var serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>(); var service = (OrganizationServiceProxy)serviceFactory.CreateOrganizationService(workflowContext.UserId); // 添加自定义头部 service.HeaderToken["MyUniqueKey"] = "MyValue"; // 创建Quote实体 var newQuote = new Entity("quote"); // 其他字段赋值... service.Create(newQuote); }
- 在插件里读取这个自定义头部:
public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); var service = (OrganizationServiceProxy)serviceFactory.CreateOrganizationService(context.UserId); if (context.MessageName == "Create") { // 检查自定义头部 if (service.HeaderToken.ContainsKey("MyUniqueKey") && service.HeaderToken["MyUniqueKey"].ToString() == "MyValue") { return; } // 你的正常插件逻辑... } }
⚠️ 注意:这个方法需要确保组织服务的代理类型正确,而且头部只在当前服务实例的请求中有效,适合复杂但不想修改实体的场景。
内容的提问来源于stack exchange,提问作者Equalsk
相关产品推荐
相关产品推荐

