Friday 28 July 2017

How to tackle Concurrent Business Process flows

Dynamics 365 has introduced the new feature of Concurrent Business Process Flows. Here is a couple of good articles on that:



Even though this is called a feature I have found it as quite troublesome so far. It’s true that in some organizations different departments would need to run different processes on the same entity in which case this makes sense. But how if we want to make sure that only one BPF should be active at a time for a record? Right now we can’t do it without writing some fair amount of coding. Ideally Microsoft should have given the option to turn on or off the concurrent business process flows either at Organisation level or Entity level.


One of my clients had this requirement of having multiple BPFs for an entity but only one should be active at a time; i.e. everybody in the business unit should follow that process.

If user A has started the BPF1 and let’s say user B come and switch the Process  to BPF2.
As Alex had mentioned here I used a plugin to achieve this. Inside the plugin I get the GUIDs of all the users in the Business Unit, then create the IOrganizationService object using each User GUID

OrganizationService UserService = serviceFactory.CreateOrganizationService(userid);

and execute a SetProcessRequest with that IOrganizationService instance to set the business process flow in the backend.

SetProcessRequest req = new SetProcessRequest();
req.Target = new EntityReference(“EntityLogicalName”, recordGuid);
req.NewProcess = new EntityReference("process", GuidOfTHeBusinessProcessFlow);
var resp = UserService.Execute(req);


This way you can make sure the same Business Process Flow is used by all users.
But please note that each user should have write privileges on the entity to execute the SetProcessRequest. If not it throws an exception. So if all the users does not have write privileges on the entity you can provide the privilege temporarily dynamically in the plugin itself and once the code is executed you can revert.

UpdateRole(serviceContext, service, "Security Role name", PrivilegeDepth.Local);


public void UpdateRole(XrmServiceContext serviceContext, IOrganizationService service, string roleName, PrivilegeDepth depth)
{
            var securityRole = serviceContext.RoleSet.Where(ro => ro.Name == roleName).FirstOrDefault();
            var roleRequest = new RetrieveRolePrivilegesRoleRequest { RoleId = securityRole.Id };
            var roleResponse = service.Execute(roleRequest);

            var privilegeQuery = new QueryExpression { EntityName = "privilege", ColumnSet = new ColumnSet(true) };

            var privileges = service.RetrieveMultiple(privilegeQuery);
            var entityPrivileges = privileges.Entities.ToList()
            .Where(p => p.GetAttributeValue<string>("name").ToLower()
            .Contains("entityLogicalName"))
            .ToList();

            foreach (var priv in entityPrivileges)
            {

                if (priv.Attributes.Contains("name") && priv.Attributes["name"].ToString() == "prvWrite"+ "entityLogicalName")
                {
                    AddPrivilegesRoleRequest addPrivilegesRequest = new AddPrivilegesRoleRequest
                    {
                        RoleId = securityRole.Id,
                        Privileges = new[]
                        {                           
                            new RolePrivilege
                            {
                                PrivilegeId = priv.Id,
                                Depth=depth
                            }
                        }
                    };
                    service.Execute(addPrivilegesRequest);
                    break;
                }
            }
}


No comments:

Post a Comment

How to tackle Concurrent Business Process flows

Dynamics 365 has introduced the new feature of Concurrent Business Process Flows. Here is a couple of good articles on that: http://dev...