Archive

Posts Tagged ‘stage’

[Code Snippet] Set Business process flow (BPF) stage using C#

October 15, 2020 Leave a comment

Assume you have a BPF with 3 Stages on an Entity ‘Employer’. When you create a new ‘Employer’ record, by default ‘Stage-1’ gets set.

What if you have to create the ‘Employer’ record with a different stage.

Lets see how to create a record and set the desired BPF stage with an example entity ‘Employer’.

I’ve an ‘Employer’ entity and a BPF name ‘Employer flow’ with 3 stages named ‘Basic Details’, ‘Address’ and ‘Experience’.

Key point to notice is, when ever you create a BPF a new entity gets created with the given BPF name.

‘Employer flow’ is BPF Entity

Following are the steps to create a ‘Employer’ record and set the BPF stage to ‘Experience’.

  • Query ‘Workflow’ entity to get the ‘BPF ID’ by passing the BPF entity schema name (i.e., crf10_employerflow).
var queryEmployerBPF = new QueryExpression
                {
                    EntityName = "workflow",
                    ColumnSet = new ColumnSet(true),
                    Criteria = new FilterExpression
                    {
                        Conditions =
                        {
                            new ConditionExpression
                            {
                                AttributeName = "uniquename",
                                Operator = ConditionOperator.Equal,
                                Values = { "crf10_employerflow" }
                            }
                        }
                    }
                };
                var retrievedBPF = ConnectionManager.CrmService.RetrieveMultiple(queryEmployerBPF).Entities[0];
                var _bpfId = retrievedBPF.Id;
  • Query Process Stage by passing ‘BPF ID’ fetched in previous step.
var queryPS = new QueryExpression{
EntityName = "processstage",
ColumnSet = new ColumnSet(true),
Criteria = new FilterExpression{
Conditions ={
new ConditionExpression{
AttributeName = "processid",
Operator = ConditionOperator.Equal,
Values={ _bpfId }
}
}
}
};
  • Copy the ‘Stage’ GUID’s which will be used in next steps.
  • Create the ‘Employer’ record, which also creates record in ‘BPF entity’ (i.e., Employer Flow).
            Entity entEmployer = new Entity("crf10_employer");
            entEmployer["crf10_name"] = "BPF Test";
            //entEmployer["processid"] = Guid.Empty;
            var violationID = ConnectionManager.CrmService.Create(entEmployer);
  • Fetch the ‘BPF entity’ (i.e., Employer Flow) record, which auto created in previous step, using ‘RetrieveProcessInstancesRequest’ request.
                var procOpp2Req = new RetrieveProcessInstancesRequest
                {
                    EntityId = violationID,
                    EntityLogicalName = "crf10_employer"
                };

                var procOpp2Resp = (RetrieveProcessInstancesResponse)ConnectionManager.CrmService.Execute(procOpp2Req);
  • Update ‘activestageid’ field of the ‘BPF entity’ (i.e., Employer Flow) record fetched in previous step, with the desired stage GUID captured in Step #2.
// Declare variables to store values returned in response
                int processCount = procOpp2Resp.Processes.Entities.Count;
                var activeProcessInstance = procOpp2Resp.Processes.Entities[0]; // First record is the active process instance
                var _processOpp2Id = activeProcessInstance.Id; // Id of the active process instance, which will be used

                // Retrieve the process instance record to update its active stage
                ColumnSet cols1 = new ColumnSet();
                cols1.AddColumn("activestageid");
                Entity retrievedProcessInstance = ConnectionManager.CrmService.Retrieve("crf10_employerflow", _processOpp2Id, cols1);

                // Update the stage to 'Experience' by passing GUID (i.e.,"05aeaf03-e135-40ac-8ae7-cafc7d746a02") 
                retrievedProcessInstance["activestageid"] = new EntityReference("processstage", new Guid("05aeaf03-e135-40ac-8ae7-cafc7d746a02"));
                ConnectionManager.CrmService.Update(retrievedProcessInstance);
  • Open the record from the App and the stage should set to ‘Experience’.
‘BPF Test’ record’s stage set to ‘Experience’
  • Check the BPF records and you should see ‘Active Stage’ got set to ‘Experience’ (This is optional step and for your learning).
  • Below is the complete snippet.
                var queryEmployerBPF = new QueryExpression
                {
                    EntityName = "workflow",
                    ColumnSet = new ColumnSet(true),
                    Criteria = new FilterExpression
                    {
                        Conditions =
                        {
                            new ConditionExpression
                            {
                                AttributeName = "uniquename",
                                Operator = ConditionOperator.Equal,
                                Values = { "crf10_employerflow" }
                            }
                        }
                    }
                };
                var retrievedBPF = ConnectionManager.CrmService.RetrieveMultiple(queryEmployerBPF).Entities[0];
                var _bpfId = retrievedBPF.Id;

                var queryPS = new QueryExpression
                {
                    EntityName = "processstage",
                    ColumnSet = new ColumnSet(true),
                    Criteria = new FilterExpression
                    {
                        Conditions =
                        {
                            new ConditionExpression
                            {
                                AttributeName = "processid",
                                Operator = ConditionOperator.Equal,
                                Values={ _bpfId }
                            }
                        }
                    }
                };
                var retrievedPS = ConnectionManager.CrmService.RetrieveMultiple(queryPS);
// Copy the Stage GUID's using below loop.
                foreach (var stage in retrievedPS.Entities)
                {
                    Console.WriteLine($"Stage Name : {stage["stagename"]}");
                    Console.WriteLine($"Stage ID : {stage["processstageid"]}");
                }
//Create 'Employer' record
                var entEmployer = new Entity("crf10_employer");
                entEmployer["crf10_name"] = "BPF Test";
                //entEmployer["processid"] = Guid.Empty;
                var violationID = ConnectionManager.CrmService.Create(entEmployer);

                var procOpp2Req = new RetrieveProcessInstancesRequest
                {
                    EntityId = violationID,
                    EntityLogicalName = "crf10_employer"
                };

                var procOpp2Resp = (RetrieveProcessInstancesResponse)ConnectionManager.CrmService.Execute(procOpp2Req);

                // Declare variables to store values returned in response
                int processCount = procOpp2Resp.Processes.Entities.Count;
                var activeProcessInstance = procOpp2Resp.Processes.Entities[0]; // First record is the active process instance
                var _processOpp2Id = activeProcessInstance.Id; // Id of the active process instance, which will be used

                // Retrieve the process instance record to update its active stage
                var cols1 = new ColumnSet();
                cols1.AddColumn("activestageid");
                var retrievedProcessInstance = ConnectionManager.CrmService.Retrieve("crf10_employerflow", _processOpp2Id, cols1);

                // Update the stage to 'Experience' by passing GUID (i.e.,"05aeaf03-e135-40ac-8ae7-cafc7d746a02") 
                retrievedProcessInstance["activestageid"] = new EntityReference("processstage", new Guid("05aeaf03-e135-40ac-8ae7-cafc7d746a02"));
                ConnectionManager.CrmService.Update(retrievedProcessInstance);

🙂

Categories: CRM Tags: , , ,

Plug-ins in CRM 2011 – Useful points

Plug-in stages

  • Pre validation
    • Registered Plug-in run before the form is validated
    • Useful if you want to implement business logic before the actual validation starts.  i.e., Changes made in plug-in won’t be saved if the validation of the main system plugins complain because the changes are outside the database transaction.
    • Ex – Some “delete” plug-ins. Deletion cascades happen prior to pre-operation, therefore if you need any information about the child records, the delete plugin must be pre-validation.
  • Pre -operation
    • After validation and before the values are saved to the database
  • Post operation
    • Plugin will run after the values have been inserted/changed on the database

Database Transactions in Plug-Ins

  • Plug-ins may or may not execute within the database transaction
  • You can check if the plug-in is executing in-transaction by reading the ‘IsInTransaction‘ property of IPluginExecutionContext
  • Stages 20 and 40 are part of the database transaction while stage 10 and 50 may be part of the transaction
  • If plugin throws an exception, every action done during the transaction will be rollback

Few more Points

  • Whether a plug-in executes synchronously or asynchronously, there is a 2 minute time limit imposed on the execution of a (message) request.
  • If the execution of your plug-in logic exceeds the time limit, a Timeout exception is thrown
  • If a plug-in needs more processing time than the 2 minute time limit, consider using a workflow or other background process
  • ‘Pre-operation’ operations that CRM will do will not be carried out in pre-validation stage.
    • If you are deleting a record that has many-to-many relationship records with another entity; these relationship records will still be available in pre-validation stage, but not in pre-operation stage.
  • “Target” entity (i.e., pluginContext.InputParameters[“Target”])
    • It’s the entity on which plug-in registered
    • It only contains “dirty” attributes. if you convert to early bound, the value of the unchanged attribute will be null

Useful MSDN article :)