Introduction to K2 Roles
K2 Roles are a way to create re-usable groups of users that can be used across processes. For instance you could create a K2 Role called Accounting Managers and that K2 Role can be used in a K2 Destination Rule. They are similar to an AD Group or a SharePoint Group but a little different. One added advantage of using K2 Roles will be kept in sync with tasks created for users to action. So what does that mean? Basically when you do not use a K2 Role and assign a specific user account to a destination rule that account will tied to the slot that is created at run time. Once the slot is created for that destination user it cannot be changed unless the user or administrator delegates the task. However if the you use a K2 Role, users that are in of the Accounting Managers K2 Role, will have immediate access to the worklist item slot (based on the refresh interval). So this is good thing to use if you anticipate that users who can potentially be assigned a task may change often.
I highly recommend reading this whitepaper - http://k2underground.com/files/folders/technical_product_documents/entry20948.aspx. It explains what is a K2 Role in detail.
Here are some of my notes on K2 Roles:
- Destination Rules are required to compile a client side event. They can be set to Static user: user dynamically, AD Group, XML list, K2 Role, SmartObject, etc.
- K2 Roles are a role is a common group that is defined within K2 that can be re-used across K2 processes. K2 Roles can be made of from accounts in AD or a custom repository like in SmartObject.
- Slots determine how many Worklist items can be Open for an Activity. As soon as a user clicks on a Worklist item, the status immediately changes from Available to Open and 1 Activity Slot is occupied. The number of Slots can be limited to a specific number or a slot can be created for each destination. Slots control how users will work with data. Configuration of the destination rules directly determine how many slots are created.
- Succeeding rules by default will evaluate the outcomes of actions along with the Slots that are created to determine if the Activity is allowed to go to the next Activity in the process.
- By default all destination rules are set to "plan just once". A slot will be created for each user and a Worklist items is created however only one activity instance is created. Any time a user is added to a K2 Role it should appear on their worklist based on interval.
- Plan per Destination supports parallel processing as multiple activity instances will be created for each user. "All at once" allows all users to access the worklist item. One at a time" only allows one user at a time to access the item.
- Plan per Slot use for an IPC event or call out to an external system.
- Cached K2 Roles - By default, a single slot will be created for each Role. By default, on a 10 minute interval, the Role and its users will be refreshed with that slot. This can be configured in each K2 process that is deployed by using the K2 Workspace. If you select, "Resolve all roles and groups to users", changes to the K2 role will not be reflected but using the "Keep roles synchronized" checkbox will keep in sync on interval.
- Dynamic Roles can only be used with "Plan just once" or "Plan per destination" where Roles do not resolve to users. Dynamic roles are on-demand. This means the K2 Role is refreshed when dynamic roles are defined and every time worklists are opened which contain items that use the role. This ensures that new users in a K2 Role will see the worklist item immediately and users removed from K2 Role will have permission blocked.
Getting User who Actioned
When using K2 Roles I have run into situations that have tripped me up a couple times. Let's say I have a client side event (InfoPath) and I want to perform custom code after the InfoPath event. Specifically, I need to know who was the user who actioned the event. To do this you need to execute the following code:
public static string GetActionUser(ActivityInstance activityInstance) {
//Loop over the activity slots to see who was the user who
//actioned the worklist item.
foreach (Slot slot in K2.ActivityInstanceDestionation.ActivityInstance.WorklistSlots) {
if (slot.Status == ActInstSlotStatus.Completed) {
return slot.User.Name;
}
}
return "";
}
What this does is loop over the slots, checks which slot was completed and by whom. You cannot go directly to the ActivityInstanceDestionation because the K2 Role was assigned as the destination user. However slots will be created dynamically for each user in the K2 Role based on the refresh interval.
Email All users in K2 Role
In many situations, I have needed to email all of the users in a K2 Role. One solution to do this without having to write any custom code would be to go to the advanced destination rules of an activity where an Email Event has been added. Select Plan per Destination All at Once. Then select Resolve All Roles to users. Then in the Email Event select send the email to the Destination User checkbox. I would only recommend doing this in an Email Event that is in its own Activity. Do not do this in the same activity where you have a client side event, like an InfoPath event. What this will do is not allow the K2 Role to be dynamic refreshed defeating the purpose of all the stuff we just talked about.
Another approach would be to use the following code to build a string of email addresses that are in the K2 Role. Then set the email string into an activity level field. Then use activity level field in the Email Event wizard. You can see in the code I have an AD SmartObject with a method called GetDetails that I use to get the user's email address.
using SourceCode.Security.UserRoleManager.Management;
using SourceCode.SmartObjects.Client;
public static string GetEmailsInRole(string conn, string roleName){
string emailAddress = "";
conn = conn.Replace(" ", "");
UserRoleManager roleManager = null;
SmartObjectClientServer server = null;
try {
//Create Manager
roleManager = new UserRoleManager();
roleManager.CreateConnection();
roleManager.Connection.Open(conn);
//Get Role
Role role = roleManager.GetRole(roleName);
//SmartObject server reference
server = new SmartObjectClientServer();
server.CreateConnection();
server.Connection.Open(conn);
//Get Person Definition
SmartObject person = server.GetSmartObject("Person");
person.MethodToExecute = "GetDetails";
foreach (RoleItem item in role.Include) {
//Now get the email from the smartobject
person.Properties["ADID"].Value = item.Name.Replace("K2:", "");
server.ExecuteScalar(person);
emailAddress += person.Properties["Email"].Value +";";
}
//remove last semi-colon
emailAddress = emailAddress.Substring(0, emailAddress.Length - 1);
}
catch (Exception ex) {
}
Finally {
if (roleManager.Connection != null) {
roleManager.Connection.Close();
}
if (server.Connection != null) {
server.Connection.Close();
}
}
return emailAddress;
}
}