Tuesday, August 28, 2012

How to Create WorkFlow Activity and the use of Output parameters in MS CRM 2011?


Use the following line of code to create complete workflow activity with two output parameters.

1) Open Visual Studio 2010 ID.
2) Open New Project.
3) Select Class Library Template.
4) Go to Properties of Project
5) Set Framework 4
6) Sign the assembly.
7) Copy the below lines of code and paste.
8) Register Work Flow Activity using the plugin registration tool.
9) Create workflow.
10) To debug the workflow activity code connect it with crmAsyn process.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Collections.ObjectModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using System.Collections;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities.Rules;

namespace CRM2011WFA
{
    public sealed class FeasibilityTask : CodeActivity
    {
        [Output("ManagerMailId")]
        [Default("Not Found")]
        public OutArgument ManagerMailId { get; set; }

        [Output("Manager")]
        [Default("7B1C0F8D-8425-E111-906B-00155D00A500", "systemuser")]
        [ReferenceTarget("systemuser")]
        public OutArgument Manager { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
            ITracingService tracingservice = executionContext.GetExtension();
            IWorkflowContext context = executionContext.GetExtension();
            IOrganizationServiceFactory servicefactory = executionContext.GetExtension();
            IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);

            tracingservice.Trace("Feasibility Task Start");

            #region Variables
            bool IsTaskExist = false;
            Guid FRequestId = context.PrimaryEntityId;
            #endregion Variables

            #region Check Task Already Exist for the selected Feasibility Request for admin user
            tracingservice.Trace("Retrieve the task using QueryByAttribute");
            QueryByAttribute query = new QueryByAttribute();
            query.Attributes.AddRange(new string[] { "regardingobjectid", "subject" });
            query.ColumnSet = new ColumnSet(new string[] { "subject" });
            query.EntityName = "task";
            query.Values.AddRange(new object[] { FRequestId, "Check Feasibility" });

            tracingservice.Trace("Executing the Query for entity {0}", query.EntityName);


            //Execute using a request to test the OOB (XRM) message contracts
            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = query;
            Collection entityList = ((RetrieveMultipleResponse)service.Execute(request)).EntityCollection.Entities;
            if (1 != entityList.Count)
            {
                tracingservice.Trace("The CHeck Feasibility Not Exists");
                IsTaskExist = false;
                //throw new InvalidPluginExecutionException("Query did not execute correctly");
            }
            else
            {
                tracingservice.Trace("Casting the Task from RetrieveMultiple to strong type");
                Entity retrievedTask = entityList[0];
                if (retrievedTask.Id != Guid.Empty)
                {
                    IsTaskExist = true;
                }
            }

            #endregion Check Task Already Exist for the selected Feasibility Request for admin user

            #region Create Task for the selected Feasibility Request for admin user
            Guid OpportunityId = Guid.Empty;
            if (!IsTaskExist)
            {
                if (context.InputParameters != null)
                {
                    OpportunityId = SerializeParamCollection(context.InputParameters);
                }
            }
            #endregion Create Task for the selected Feasibility Request for admin user

            #region Get Business Unit ID of the Opportunity
            Guid BUId = Guid.Empty;
            if (OpportunityId != Guid.Empty)
            {
                tracingservice.Trace("Retrieve the BUID using Opportunity");
                QueryByAttribute queryBU = new QueryByAttribute();
                queryBU.Attributes.AddRange(new string[] { "opportunityid" });
                queryBU.ColumnSet = new ColumnSet(new string[] { "owningbusinessunit" });
                queryBU.EntityName = "opportunity";
                queryBU.Values.AddRange(new object[] { OpportunityId });

                tracingservice.Trace("Executing the Query for entity {0}", queryBU.EntityName);

                //Execute using a request to test the OOB (XRM) message contracts
                RetrieveMultipleRequest requestBU = new RetrieveMultipleRequest();
                requestBU.Query = queryBU;
                Collection entityListBU = ((RetrieveMultipleResponse)service.Execute(requestBU)).EntityCollection.Entities;
                if (1 != entityListBU.Count)
                {
                    tracingservice.Trace("BUID Not Exists");
                }
                else
                {
                    tracingservice.Trace("Casting the Opportunity from RetrieveMultiple to strong type");
                    Entity retrievedOpp = entityListBU[0];
                    if (retrievedOpp.Id != Guid.Empty)
                    {
                        BUId = ((EntityReference)retrievedOpp["owningbusinessunit"]).Id;
                    }
                }
            }

            #endregion Get Business Unit ID of the Opportunity

            #region Find Admin User in The Opportunity Business Unit ID
            Guid TaskOwner = Guid.Empty;
            if (BUId != Guid.Empty)
            {
                TaskOwner = FindAdminUser(service, BUId);
                if (TaskOwner != Guid.Empty)
                {
                    #region Create task for feasibility request
                    Entity task = new Entity("task");
                    task["subject"] = "Check Feasibility";
                    task["regardingobjectid"] = new EntityReference("new_feasibilityrequest", FRequestId);
                    task["ownerid"] = new EntityReference("systemuser", TaskOwner);
                    task["description"] = "Please check the Feasibility for this opportunity";
                    Guid TaskID = service.Create(task);

                    #region Get and set Manager & Manager Mail ID in Output parameters
                    QueryExpression qe = new QueryExpression();
                    qe.EntityName = "systemuser";
                    qe.ColumnSet = new ColumnSet(true);

                    qe.LinkEntities.Add(new LinkEntity("systemuser", "systemuser", "systemuserid", "parentsystemuserid", JoinOperator.Inner));
                    ConditionExpression ce = new ConditionExpression("systemuserid", ConditionOperator.Equal, new Object[] { TaskOwner });
                    qe.Criteria.AddCondition(ce);

                    EntityCollection ec = service.RetrieveMultiple(qe);

                    if (ec.Entities.Count > 0)
                    {
                        foreach (Entity act in ec.Entities)
                        {
                            Manager.Set(executionContext, new EntityReference("systemuser", new Guid(act.Attributes["systemuserid"].ToString())));
                            ManagerMailId.Set(executionContext, act.Attributes["internalemailaddress"].ToString());
                        }
                    }
                    else
                        ManagerMailId.Set(executionContext, "Not Found");
                    #endregion Get and set Manager & Manager Mail ID in Output parameters

                    #endregion Create task for for easibility request
                }
                else
                {
                    ManagerMailId.Set(executionContext, "Not Found");
                }
            }
            else
            {
                ManagerMailId.Set(executionContext, "Not Found");
            }
            #endregion Find Admin User in The Opportunity Business Unit ID

        }

        private static Guid FindAdminUser(IOrganizationService service, Guid BUId)
        {
            Guid adminUserId = Guid.Empty;

            QueryExpression qe = new QueryExpression();
            qe.EntityName = "systemuser";
            ColumnSet columns = new ColumnSet();
            columns.AddColumn("systemuserid");
            columns.AddColumn("fullname");
            qe.ColumnSet = columns;

            LinkEntity leRole = new LinkEntity("systemuser", "systemuserroles", "systemuserid", "systemuserid", JoinOperator.Inner);
            LinkEntity le = new LinkEntity("systemuserroles", "role", "roleid", "roleid", JoinOperator.Inner);

            ConditionExpression ce = new ConditionExpression("name", ConditionOperator.Equal, new Object[] { "Admin User" });
            ConditionExpression cebu = new ConditionExpression("businessunitid", ConditionOperator.Equal, new Object[] { BUId });

            le.LinkCriteria = new FilterExpression();
            le.LinkCriteria.AddCondition(ce);
            le.LinkCriteria.AddCondition(cebu);

            leRole.LinkEntities.Add(le);
            qe.LinkEntities.Add(leRole);

            EntityCollection ec = service.RetrieveMultiple(qe);
            if (ec.Entities.Count > 0)
            {
                foreach (Entity act in ec.Entities)
                {
                    adminUserId = new Guid(act["systemuserid"].ToString());
                }
            }
            else
            {
                Guid ParentBunitid = GetParentBU(service, BUId);
                if (ParentBunitid != Guid.Empty)
                {
                    adminUserId = FindAdminUser(service, ParentBunitid);
                }
            }

            return adminUserId;
        }

        private static Guid GetParentBU(IOrganizationService service, Guid BUId)
        {
            Guid ParentBUID = Guid.Empty;
            QueryByAttribute queryBU = new QueryByAttribute();
            queryBU.Attributes.AddRange(new string[] { "businessunitid" });
            queryBU.ColumnSet = new ColumnSet(new string[] { "parentbusinessunitid" });
            queryBU.EntityName = "businessunit";
            queryBU.Values.AddRange(new object[] { BUId });

            //Execute using a request to test the OOB (XRM) message contracts
            RetrieveMultipleRequest requestBU = new RetrieveMultipleRequest();
            requestBU.Query = queryBU;
            Collection entityListBU = ((RetrieveMultipleResponse)service.Execute(requestBU)).EntityCollection.Entities;
            if (entityListBU.Count != 0)
            {
                Entity retrievedOpp = entityListBU[0];
                if (retrievedOpp.Id != Guid.Empty)
                {
                    ParentBUID = retrievedOpp.Id;
                }
            }
            return ParentBUID;
        }

        private static string SerializeEntityImageCollection(EntityImageCollection entityImageCollection)
        {
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair entityImage in entityImageCollection)
            {
                sb.Append(Environment.NewLine);
                sb.Append(entityImage.Key + ": " + SerializeEntity(entityImage.Value));
            }
            return sb.ToString();
        }

        private static string SerializeParameterCollection(ParameterCollection parameterCollection)
        {
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair parameter in parameterCollection)
            {
                if (parameter.Value != null && parameter.Value.GetType() == typeof(Entity))
                {
                    Entity e = (Entity)parameter.Value;
                    sb.Append(parameter.Key + ": " + SerializeEntity(e));
                }
                else
                {
                    sb.Append(parameter.Key + ": " + parameter.Value + "; ");
                }
            }
            return sb.ToString();
        }

        private static string SerializeEntity(Entity e)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(Environment.NewLine);
            sb.Append(" LogicalName: " + e.LogicalName);
            sb.Append(Environment.NewLine);
            sb.Append(" EntityId: " + e.Id);
            sb.Append(Environment.NewLine);
            sb.Append(" Attributes: [");
            foreach (KeyValuePair parameter in e.Attributes)
            {
                sb.Append(parameter.Key + ": " + parameter.Value + "; ");
            }
            sb.Append("]");
            return sb.ToString();
        }

        private Guid SerializeParamCollection(ParameterCollection parameterCollection)
        {
            Guid oppid = new Guid();
            foreach (KeyValuePair parameter in parameterCollection)
            {
                if (parameter.Value != null && parameter.Value.GetType() == typeof(Entity))
                {
                    Entity e = (Entity)parameter.Value;
                    oppid = OpportunityId(e);
                    break;
                }
            }
            return oppid;
        }

        private Guid OpportunityId(Entity e)
        {
            Guid oppid = new Guid();
            foreach (KeyValuePair parameter in e.Attributes)
            {
                if (parameter.Key == "new_opportunity_new_feasibilityrequid")
                {
                    oppid = ((EntityReference)(parameter.Value)).Id;
                    break;
                }
            }

            return oppid;
        }
    }
}

No comments:

Split the String values with a special character in MS Flow to convert this into Array

 Many times we have a requirement to prepare the Mailing address for some of the documents, suppose there are Address Line1, Address Line2, ...