Therapy coding for Dynamics 365 CE - Business Process Flow creation for a custom entity then activation BPF related codes finally adding it to a custom solution as a component
Hello,
Here is the console application of BPF creation, activation and appending to Test Solution:
enjoy !
Edit - 2020/06/29
Important Notice:
String GuidforControlClassId = Guid.NewGuid().ToString();
I have realized that we can not set random GUID as a ClassId. We have to fetch it from CRM.
Since I use createdon field in the sample, I searched ClassId of DateTime in the CRM and find that we are able to reach ClassId from any forms which have DateTime field (Controller) in the UI with following javascript;
formContext.getControl('createdon').$0_4.$J_2.ClassId.$r_0
I am sorry to say that It is unsupported.
Here is the console application of BPF creation, activation and appending to Test Solution:
#region create business process flow string nameoftheEntityBPFtobeCreatedfor = "new_test"; CrmServiceClient service = null; try { service = Your_Connection_Obkject; if (service.IsReady) {
#region Demonstrate #region Define workflow XAML // Define the workflow XAML. string xamlWF; string GuidMain = Guid.NewGuid().ToString(); String GuidforControlClassId = Guid.NewGuid().ToString(); String GuidforLabelId = Guid.NewGuid().ToString(); String GuidforStepLabelId = Guid.NewGuid().ToString();xamlWF = @" <Activity x:Class=""XrmWorkflow" + GuidMain.Replace("{", "").Replace("}", "").Replace("-", "") + @""" xmlns=""http://schemas.microsoft.com/netfx/2009/xaml/activities"" xmlns:mcwb=""clr-namespace:Microsoft.Crm.Workflow.BusinessProcessFlowActivities;assembly=Microsoft.Crm.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" xmlns:mcwo=""clr-namespace:Microsoft.Crm.Workflow.ObjectModel;assembly=Microsoft.Crm, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" xmlns:mva=""clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" xmlns:mxs=""clr-namespace:Microsoft.Xrm.Sdk;assembly=Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" xmlns:mxswa=""clr-namespace:Microsoft.Xrm.Sdk.Workflow.Activities;assembly=Microsoft.Xrm.Sdk.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" xmlns:scg=""clr-namespace:System.Collections.Generic;assembly=mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" xmlns:sco=""clr-namespace:System.Collections.ObjectModel;assembly=mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" xmlns:srs=""clr-namespace:System.Runtime.Serialization;assembly=System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" xmlns:this=""clr-namespace:"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <x:Members> <x:Property Name=""InputEntities"" Type=""InArgument(scg:IDictionary(x:String, mxs:Entity))"" /> <x:Property Name=""CreatedEntities"" Type=""InArgument(scg:IDictionary(x:String, mxs:Entity))"" /> </x:Members> <this:XrmWorkflow" + GuidMain.Replace("{", "").Replace("}", "").Replace("-", "") + @".InputEntities> <InArgument x:TypeArguments=""scg:IDictionary(x:String, mxs:Entity)"" /> </this:XrmWorkflow" + GuidMain.Replace("{", "").Replace("}", "").Replace("-", "") + @".InputEntities> <this:XrmWorkflow" + GuidMain.Replace("{", "").Replace("}", "").Replace("-", "") + @".CreatedEntities> <InArgument x:TypeArguments=""scg:IDictionary(x:String, mxs:Entity)"" /> </this:XrmWorkflow" + GuidMain.Replace("{", "").Replace("}", "").Replace("-", "") + @".CreatedEntities> <mva:VisualBasic.Settings>Assembly references and imported namespaces for internal implementation</mva:VisualBasic.Settings> <mxswa:Workflow> <mxswa:ActivityReference AssemblyQualifiedName=""Microsoft.Crm.Workflow.BusinessProcessFlowActivities.StageRelationshipCollectionComposite, Microsoft.Crm.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" DisplayName=""RelationshipCollectionStep1""> <mxswa:ActivityReference.Properties> <sco:Collection x:TypeArguments=""Variable"" x:Key=""Variables"" /> <sco:Collection x:TypeArguments=""Activity"" x:Key=""Activities"" /> </mxswa:ActivityReference.Properties> </mxswa:ActivityReference> <mxswa:ActivityReference AssemblyQualifiedName=""Microsoft.Crm.Workflow.Activities.EntityComposite, Microsoft.Crm.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" DisplayName=""EntityStep2: new_test""> <mxswa:ActivityReference.Properties> <sco:Collection x:TypeArguments=""Variable"" x:Key=""Variables"" /> <sco:Collection x:TypeArguments=""Activity"" x:Key=""Activities""> <mxswa:ActivityReference AssemblyQualifiedName=""Microsoft.Crm.Workflow.Activities.StageComposite, Microsoft.Crm.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" DisplayName=""StageStep3: New Stage""> <mxswa:ActivityReference.Properties> <sco:Collection x:TypeArguments=""Variable"" x:Key=""Variables"" /> <sco:Collection x:TypeArguments=""Activity"" x:Key=""Activities""> <mxswa:ActivityReference AssemblyQualifiedName=""Microsoft.Crm.Workflow.Activities.StepComposite, Microsoft.Crm.Workflow, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" DisplayName=""StepStep4: New Step""> <mxswa:ActivityReference.Properties> <sco:Collection x:TypeArguments=""Variable"" x:Key=""Variables"" /> <sco:Collection x:TypeArguments=""Activity"" x:Key=""Activities""> <Sequence DisplayName=""ControlStep5""> <mcwb:Control ClassId=""" + GuidforControlClassId.Replace("{", "").Replace("}", "") + @""" ControlDisplayName=""Name"" ControlId=""new_name"" DataFieldName=""new_name"" IsSystemControl=""False"" IsUnbound=""False"" SystemStepType=""0""> <mcwb:Control.Parameters> <InArgument x:TypeArguments=""x:String""> <Literal x:TypeArguments=""x:String"" Value="""" /> </InArgument> </mcwb:Control.Parameters> </mcwb:Control> </Sequence> </sco:Collection> <sco:Collection x:TypeArguments=""mcwo:StepLabel"" x:Key=""StepLabels""> <mcwo:StepLabel Description=""Name"" LabelId=""" + GuidforLabelId.Replace("{", "").Replace("}", "") + @""" LanguageCode=""1033"" /> </sco:Collection> <x:String x:Key=""ProcessStepId"">" + GuidforLabelId.Replace("{", "").Replace("}", "") + @"</x:String> <x:Boolean x:Key=""IsProcessRequired"">False</x:Boolean> </mxswa:ActivityReference.Properties> </mxswa:ActivityReference> </sco:Collection> <sco:Collection x:TypeArguments=""mcwo:StepLabel"" x:Key=""StepLabels""> <mcwo:StepLabel Description=""New Stage"" LabelId=""" + GuidforStepLabelId.Replace("{", "").Replace("}", "") + @""" LanguageCode=""1033"" /> </sco:Collection> <x:String x:Key=""StageId"">" + GuidforStepLabelId.Replace("{", "").Replace("}", "") + @"</x:String> <x:String x:Key=""StageCategory"">-1</x:String> <x:Null x:Key=""NextStageId"" /> </mxswa:ActivityReference.Properties> </mxswa:ActivityReference> </sco:Collection> <x:Null x:Key=""RelationshipName"" /> <x:Null x:Key=""AttributeName"" /> <x:Boolean x:Key=""IsClosedLoop"">False</x:Boolean> </mxswa:ActivityReference.Properties> </mxswa:ActivityReference> </mxswa:Workflow> </Activity> ";
#endregion Define workflow XAML #region Create Workflow // Create an asynchronous workflow. // The workflow should execute after a new opportunity is created. Workflow workflow = new Workflow() { // These properties map to the New Process form settings in the web application. Name = "Business Process Flow for PowerStages", Type = new OptionSetValue((int)WorkflowTypeEnum.Definition), Category = new OptionSetValue((int)WorkflowCategoryEnum.BusinessProcessFlow), PrimaryEntity = nameoftheEntityBPFtobeCreatedfor, Mode = new OptionSetValue((int)WorkflowModeEnum.Realtime), // Additional settings from the second New Process form. Description = @"it is dedicated for PowerStages", OnDemand = false, Subprocess = false, Scope = new OptionSetValue((int)WorkflowScopeEnum.Organization), //TriggerOnCreate = true, //AsyncAutoDelete = true, Xaml = xamlWF, // Other properties not in the web forms. LanguageCode = 1033 // U.S. English }; _workflowId = service.Create(workflow); Console.WriteLine("Created process '" + workflow.Name + "'"); #endregion Create Workflow #region Activate Workflow // Activate the workflow. var activateRequest = new SetStateRequest { EntityMoniker = new EntityReference (Workflow.EntityLogicalName, _workflowId), State = new OptionSetValue((int)WorkflowStateEnum.Activated), Status = new OptionSetValue((int)workflow_statuscodeEnum.Activated) }; OrganizationResponse activateRepose = service.Execute(activateRequest); Console.WriteLine("Activated process '" + workflow.Name + "'"); #endregion Activate Workflow #region Add BPF to PowerStages Solution // Retrieve a solution String solutionUniqueName = "TestSolution"; QueryExpression queryTestSolution = new QueryExpression { EntityName = Solution.EntityLogicalName, ColumnSet = new ColumnSet(new string[] { "publisherid", "installedon", "version", "versionnumber", "friendlyname", "uniquename" }), Criteria = new FilterExpression() }; queryTestSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, solutionUniqueName); Solution TestSolution = (Solution)service.RetrieveMultiple(queryTestSolution).Entities[0]; // Add an existing Solution Component //Add the workflow to the solution AddSolutionComponentRequest addReq = new AddSolutionComponentRequest() { ComponentType = (int)componenttype.Workflow, ComponentId = _workflowId, SolutionUniqueName = TestSolution.UniqueName }; service.Execute(addReq); #endregion #endregion Demonstrate // CleanUpSample(service); } else { const string UNABLE_TO_LOGIN_ERROR = "Unable to Login to Common Data Service"; if (service.LastCrmError.Equals(UNABLE_TO_LOGIN_ERROR)) { Console.WriteLine("Check the connection string values in cds/App.config."); throw new Exception(service.LastCrmError); } else { throw service.LastCrmException; } } } catch (Exception ex) { SampleHelpers.HandleException(ex); } finally { if (service != null) service.Dispose(); Console.WriteLine("Press <Enter> to exit."); Console.ReadLine(); } #endregion
enjoy !
Edit - 2020/06/29
Important Notice:
String GuidforControlClassId = Guid.NewGuid().ToString();
I have realized that we can not set random GUID as a ClassId. We have to fetch it from CRM.
Since I use createdon field in the sample, I searched ClassId of DateTime in the CRM and find that we are able to reach ClassId from any forms which have DateTime field (Controller) in the UI with following javascript;
formContext.getControl('createdon').$0_4.$J_2.ClassId.$r_0
I am sorry to say that It is unsupported.
Comments
Post a Comment