更改C#插件中的业务流程流程阶段 [英] Changing Business Process Flow Stage in C# Plugin

查看:100
本文介绍了更改C#插件中的业务流程流程阶段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注FaultException<OrganizationServiceFault>异常.为什么我会收到错误消息,如何修改代码以成功回到业务流程中的上一个阶段?

I am following this article to change my Business Process Flow stage within a c# plugin. I am able to move the stage forward to the next stage, but I am receiving an error when I try to move back to a previous stage. The error below is what I receive in the UI from Dynamics. When I debug the plugin, I receive a FaultException<OrganizationServiceFault> exception that doesn't contain any information. Why am I receiving an error and how can I modify my code to successfully go back to a previous stage in my Business Process Flow?

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: An unexpected error occurred.
Detail: <OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ActivityId>5df51362-b7c1-4817-a8d0-de2d63b15c17</ActivityId>
  <ErrorCode>-2147220970</ErrorCode>
  <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>An unexpected error occurred.</Message>
  <Timestamp>2018-07-19T18:55:42.6625925Z</Timestamp>
  <ExceptionSource i:nil="true" />
  <InnerFault>
    <ActivityId>5df51362-b7c1-4817-a8d0-de2d63b15c17</ActivityId>
    <ErrorCode>-2147220970</ErrorCode>
    <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>System.NullReferenceException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #0D309052</Message>
    <Timestamp>2018-07-19T18:55:42.6625925Z</Timestamp>
    <ExceptionSource i:nil="true" />
    <InnerFault i:nil="true" />
    <OriginalException i:nil="true" />
    <TraceText i:nil="true" />
  </InnerFault>
  <OriginalException i:nil="true" />
  <TraceText i:nil="true" />
</OrganizationServiceFault>

插件

if (localContext == null)
{
    throw new ArgumentNullException("localContext");
}

IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;

Client client = (Client)service.Retrieve(
    Client.LogicalName,
    new Guid("75FE165F-848B-E811-80F3-005056B33317"),
    new ColumnSet(new String[]{
        Client.Properties.ClientId
    })
);

client.ChangeStage(service);

更改阶段

public void ChangeStage(IOrganizationService service)
{
    // Get Process Instances
    RetrieveProcessInstancesRequest processInstanceRequest = new RetrieveProcessInstancesRequest
    {
        EntityId = this.Id,
        EntityLogicalName = this.LogicalName
    };

    RetrieveProcessInstancesResponse processInstanceResponse = (RetrieveProcessInstancesResponse)service.Execute(processInstanceRequest);

    // Declare variables to store values returned in response
    int processCount = processInstanceResponse.Processes.Entities.Count;
    Entity activeProcessInstance = processInstanceResponse.Processes.Entities[0]; // First record is the active process instance
    Guid activeProcessInstanceID = activeProcessInstance.Id; // Id of the active process instance, which will be used later to retrieve the active path of the process instance

    // Retrieve the active stage ID of in the active process instance
    Guid activeStageID = new Guid(activeProcessInstance.Attributes["processstageid"].ToString());

    // Retrieve the process stages in the active path of the current process instance
    RetrieveActivePathRequest pathReq = new RetrieveActivePathRequest
    {
        ProcessInstanceId = activeProcessInstanceID
    };
    RetrieveActivePathResponse pathResp = (RetrieveActivePathResponse)service.Execute(pathReq);

    string activeStageName = "";
    int activeStagePosition = -1;

    Console.WriteLine("\nRetrieved stages in the active path of the process instance:");
    for (int i = 0; i < pathResp.ProcessStages.Entities.Count; i++)
    {
        // Retrieve the active stage name and active stage position based on the activeStageId for the process instance
        if (pathResp.ProcessStages.Entities[i].Attributes["processstageid"].ToString() == activeStageID.ToString())
        {
            activeStageName = pathResp.ProcessStages.Entities[i].Attributes["stagename"].ToString();
            activeStagePosition = i;
        }
    }

    // Retrieve the stage ID of the next stage that you want to set as active
    activeStageID = (Guid)pathResp.ProcessStages.Entities[activeStagePosition - 1].Attributes["processstageid"];

    // Retrieve the process instance record to update its active stage
    ColumnSet cols1 = new ColumnSet();
    cols1.AddColumn("activestageid");
    Entity retrievedProcessInstance = service.Retrieve("ccseq_bpf_clientsetup", activeProcessInstanceID, cols1);

    // Set the next stage as the active stage
    retrievedProcessInstance["activestageid"] = new EntityReference(ProcessStage.LogicalName, activeStageID);
    service.Update(retrievedProcessInstance);
}


更新

我发现这篇文章介绍了如何使用Web API更新舞台.当我尝试这种方法时,出现错误:


Update

I found this article that explains how to update the Stage using the Web API. When I try this method, I get the error:

未声明的属性"activestageid",仅在有效负载中具有属性注释,而在有效负载中未找到属性值.在OData中,只有声明的导航属性和声明的命名流可以表示为没有值的属性.

An undeclared property 'activestageid' which only has property annotations in the payload but no property value was found in the payload. In OData, only declared navigation properties and declared named streams can be represented as properties without values.

我尝试了几种"activestageid",但都没有成功(ActiveStageId,_activestageid_value).

I've tried a few varieties of 'activestageid' without success (ActiveStageId, _activestageid_value).

根据Arun的反馈,我尝试了以下Web API调用,但均未成功.我从ccseq_bpf_clientsetups表上的BusinessProcessFlowInstanceId中提取的URL括号(ccseq_bpf_clientsetups(###))中的ID.我从ProcessStageBase表中的ProcessStageId中提取的流程阶段ID

Based on Arun's feedback, I tried the below Web API calls without success. The ID inside the brackets in the url (ccseq_bpf_clientsetups(###)) I pulled from the BusinessProcessFlowInstanceId on the ccseq_bpf_clientsetups table. The processstages ID I pulled from the ProcessStageId in the ProcessStageBase table

// Attempt 1
PATCH /COHEN/api/data/v8.2/ccseq_bpf_clientsetups(bc892aec-2594-e811-80f4-005056b33317) HTTP/1.1
{ "ActiveStageID@odata.bind": "/processstages(70018854-db7c-4612-915b-2ad7870a8574)"}

// Attempt 2
PATCH /COHEN/api/data/v8.2/ccseq_bpf_clientsetups(bc892aec-2594-e811-80f4-005056b33317) HTTP/1.1
{ "activestageid@odata.bind": "/processstages(70018854-db7c-4612-915b-2ad7870a8574)"}

// Attempt 3
PATCH /COHEN/api/data/v8.2/ccseq_bpf_clientsetups(bc892aec-2594-e811-80f4-005056b33317) HTTP/1.1
{ "ActiveStageId@odata.bind": "/processstages(70018854-db7c-4612-915b-2ad7870a8574)"}


更新3

我下载了jLattimer的CRM Rest Builder,并尝试运行他生成的工具中的JavaScript.该代码与我之前编写的代码相同,但是不幸的是,该代码无法正常工作.目前,我非常有信心Web API v8.2不支持更改阶段.


Update 3

I downloaded jLattimer's CRM Rest Builder and tried running the JavaScript his tool generated. The code was identical to what I had written previously and unfortunately did not work. At this point I'm fairly confident that changing stages is not supported in v8.2 of the Web API.

推荐答案

我遇到了同样的问题.它比您想象的要简单得多. 确定,打开高级查找,选择{您的BPF}. 添加两列查询:{您的实体} {遍历的路径}.

I was having the same issue. It's a lot simpler than you think. OK, open advanced find, select {your BPF}. Add two columns to query: {your Entity} {traversed path}.

好,因此,请查看实际处于上一阶段(您想返回的阶段)的实体的遍历路径.

Ok, so look at the traversed path for an entity that is actually in the previous stage (the one you want to go back to).

使用您的代码,您需要动态分解遍历的路径(.Split(','))或类似的内容...删除最后一个阶段(您当前所在的那个阶段),瞧!您正在用汽油做饭.

With your code, you need to dynamically break down the traversed path (.Split(',')) or something similar...remove the last stage (the one you're currently in), and voila! You're cooking with gasoline.

如果当前遍历的路径是数组:

if the current traversed path were an array:

string[] currentPath = {"A", "B", "C", "D"};

您之前的路径必须为:

string[] previousPath = {"A", "B", "C"};

假设您是检索到的实体,请按照以下步骤在代码中进行操作:

Here's how you could do it in code, assuming 'entity' is your retrieved entity:

string traversedPath = (string) entity["traversedpath"];
string[] stages = traversedPath.Split(',');
string newPath = "";
//use length - 1 to omit last stage (your current stage)
for (int i = 0; i < stages.Length - 1; i++) 
{ 
     if (i != stages.Length - 1)
     newPath += stages[i] + ",";
     else
     newPath += stages[i];

}
entity["processid"] = new Guid("BPF Guid") //may be optional
entity["stageid"] = new Guid("previous stage guid");
entity["traversedpath"] = newPath;
service.Update(entity);

基本上,遍历路径不会+ =您的前一阶段"到遍历路径的末尾.它想将遍历路径设置为您的上一阶段"的原始遍历路径.找出所需阶段的遍历路径是什么,然后将吸盘硬编码成字符串(如果永远都只能进入那个阶段)..或者通过.Split(',')方法以编程方式完成代码中的Entity ["traversedpath"]属性.

Basically, the traversed path does not += 'your previous stage' to the end of the traversed path. It wants to set the traversed path to the ORIGINAL traversed path for 'your previous stage'. Find out what the traversed path is for the stage desired, and either hardcode that sucker into a string (if it's only gonna go to that stage, ever)..or programmatically do it via the .Split(',') method on the Entity["traversedpath"] attribute in code.

请记住,您是从中减去而不是向...添加经过的路径.我花了很多无效的遍历路径错误才能得出这个结论……而且行之有效.祝你好运!

Remember, you are subtracting from, not adding to...the traversed path. It took me a lot of invalid traversed path errors to come to this conclusion...and it works. Good luck!

这篇关于更改C#插件中的业务流程流程阶段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆