【问题标题】:Exception thrown when programmatically finishing conditional business process flow以编程方式完成条件业务流程时抛出异常
【发布时间】:2019-03-04 16:05:12
【问题描述】:

以下是商机实体上的业务流程 (BPF)。我创建了一个插件,可以自动将此 BPF 推进到更新机会上的字段的最后阶段。

当为满足上图条件(并因此利用 BPF 的所有阶段)的机会发送 RetrieveActivePathRequest 消息时,我收到 RetrieveActivePathResponse 并且我的插件按预期工作:

        // Retrieve the process stages in the active path of the current process instance
        RetrieveActivePathRequest activePathRequest = new RetrieveActivePathRequest
        {
            ProcessInstanceId = activeProcessId
        };

        RetrieveActivePathResponse activePathResponse = (RetrieveActivePathResponse)service.Execute(activePathRequest);

但是,为不满足条件的机会(因此仅利用 BPF 的前三个阶段)发送 RetrieveActivePathRequest 消息会导致 System.ServiceModel.FaultException

我怀疑这可能是由于 BPF 中的“else”条件没有分支到某个阶段。我添加了一个共享阶段并将其与“其他”条件和上图所示的最后一个阶段连接起来,不再遇到异常。我的插件按预期工作并自动推进了 BPF。

两个问题:

  1. 为什么会这样?在任一场景中,我都可以手动推进每个阶段并完成 BPF,那为什么我不能以编程方式做同样的事情呢?

  2. 是否有替代方法来处理这种情况,以便我可以使用我的插件自动推进 BPF(原样)?如果可能的话,我宁愿不创建共享阶段或两个单独的 BPF。

编辑:

如果有人好奇,这就是我用来自动推进 BPF 的全部功能。

    private static void AdvanceBusinessProcessFlow(IOrganizationService service, ExtendedPluginContext context, Guid opportunityId)
    {
        // Retrieve all process instances
        RetrieveProcessInstancesRequest instanceRequest = new RetrieveProcessInstancesRequest
        {
            EntityId = opportunityId,
            EntityLogicalName = XrmOpportunity.EntityLogicalName
        };
        RetrieveProcessInstancesResponse instanceResponse = (RetrieveProcessInstancesResponse)service.Execute(instanceRequest);

        // First record is the active process instance
        Entity activeProcessInstance = instanceResponse.Processes.Entities[0];
        var activeProcessId = activeProcessInstance.Id;
        var activeStageId = new Guid(activeProcessInstance.Attributes["processstageid"].ToString());

        // Retrieve the process stages in the active path of the current process instance
        RetrieveActivePathRequest activePathRequest = new RetrieveActivePathRequest
        {
            ProcessInstanceId = activeProcessId
        };

        // System.ServiceModel.FaultException exception occurs here
        RetrieveActivePathResponse activePathResponse = (RetrieveActivePathResponse)service.Execute(activePathRequest);

        string activeStageName;
        int? activeStagePosition = null;
        int stageCount = activePathResponse.ProcessStages.Entities.Count;

        // Iterate through all process stages and identify active stage
        for (int i = 0; i < stageCount; i++)
        {
            if (activePathResponse.ProcessStages.Entities[i].Attributes["processstageid"].ToString() == activeStageId.ToString())
            {
                activeStageName = activePathResponse.ProcessStages.Entities[i].Attributes["stagename"].ToString();
                activeStagePosition = i;
            }
        }

        // If an active stage position is not identified, do nothing
        if (activeStagePosition == null)
        {
            throw new InvalidPluginExecutionException("No active stage of business process flow was identified!");
        }

        // Auto-advance active stages of BPF to last stage so that BPF can be auto-finished
        while (activeStagePosition < stageCount - 1)
        {
            // Retrieve the stage ID of the next stage to be set as the active stage
            var newActiveStageId = (Guid) activePathResponse.ProcessStages.Entities[(int) ++activeStagePosition].Attributes["processstageid"];

            // Retrieve the process instance record to update its active stage
            ColumnSet columnSet = new ColumnSet();
            columnSet.AddColumn("activestageid");
            Entity retrievedProcessInstance = service.Retrieve(dfnd_opportunitydispoprocess.EntityLogicalName, activeProcessId, columnSet);

            // Update active process stage
            retrievedProcessInstance["activestageid"] = new EntityReference(ProcessStage.EntityLogicalName, newActiveStageId);
            service.Update(retrievedProcessInstance);
        }
    }

【问题讨论】:

  • FaultException 告诉你什么?它有一个 Details 属性,该属性具有 Message 属性。这应该为您提供有关异常的更多信息。 catch (FaultException ex) { // ex.Details.Message; }
  • 您无法进入无效阶段
  • @Alessi “发生意外错误。”
  • @jasonscript 这是有道理的,但在收到包含有关 BPF 中阶段的数据的 RetrieveActivePathResponse 对象(通过其 ProcessStages 属性)之前,我不会尝试推进 BPF。也许有一些文档解释了为什么在我的场景中没有返回这个对象?

标签: c# .net dynamics-crm dynamics-crm-365


【解决方案1】:

在不满足 BPF 条件时定向到一个阶段,防止错误被抛出:

我仍然不知道为什么不为不满足 BPF 条件的机会返回 RetrieveActivePathResponse 对象。

【讨论】:

  • 你是按顺序推进这个阶段而不是跳过吗?如果你的 BPF 是 1->2->3,你不能直接从 1 到 3。你需要两次更新,1->2,然后 2->3。 (其中 1,2 和 3 代表您的舞台 GUID)
  • @Alessi 是的,我在收到 RetrieveActivePathResponse 对象后执行此操作,该对象用于确定活动舞台位置,然后从该位置按顺序进行。问题是我根本没有收到这个 RetrieveActivePathResponse 对象,而是一个 System.ServiceModel.FaultException 异常。
猜你喜欢
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多