How To Get Context Users UserGroups In An Action Script In Content Hub

Example Subheading

December 14, 2022

By Mike Payne

Getting the User and UserGroup objects from within an Action script can be a head-scratcher for those who are fairly new to Sitecore Content Hub script writing. You first need to know a little about the different kinds of data on an entity and how they are loaded. You may also get confused by the documentation. For instance, the Context object looks different between different script types i.e., the Action and Metadata processing script. In the Metadata processing script we have access to the User entity here: Context.User. However, in our Action script we only have access to the Users ID: Context.TriggeringUserId

The UserGroup information is not loaded by default when you request the User entity from the MClient (the querying client provided by the SDK). The MClient does not load relationship data by default so we must configure our Load Configuration object to include those relations we need.

Load Configurations

Load configurations aggregate multiple load options for entities. By default, all properties are loaded but relations are not. Note: relations are not the same as a property. We will elaborate on this in a moment.

Below are the different load options available to us. It is important, especially in a production environment, to load the least amount of data as possible in order to minimize the server load. In our example, we are using Default, but in theory we could use Minimal and just return only the properties and relations that we need for our script.

  • EntityLoadConfiguration.Minimal: loads entities without any cultures, properties and relations. Only system properties are available (id, definition, created on, created by...).
  • EntityLoadConfiguration.Default: loads entities in the default culture, all properties and no relations.
  • EntityLoadConfiguration.DefaultCultureFull: loads entities in the default culture, with all properties and all relations.
  • EntityLoadConfiguration.Full: loads entities in all cultures, all properties and all relations.

Relations Versus Properties

Relations are used to link together entities. For example, assets to assets or assets to taxonomies. There are four main relation types as defined in the Sitecore documentation. The relation type we are concerned with in our problem is the IChildToManyParentsRelation.

Properties simply hold data that is stored on an entity. An example of a property is the Title which is a string.

The Script

The following script is linked to a Trigger which is activated on Entity creation.

At the top of our Action script, we include references to the libraries needed to run our code.


using System.Linq;
using System.Collections.Generic;
using Stylelabs.M.Sdk.Clients;
using System.Threading.Tasks;
using Stylelabs.M.Base.Querying;
using Stylelabs.M.Base.Querying.Linq;

Then we want to define our Load Configuration. We are using the Default load option for this which means we have access to all properties but no relations. Therefore, to get our UserGroup relationship from the User, we need to tell our Load Configuration to include this relationship when loading our entity.

The IEntityLoadConfiguration comes with a builder to create or extend load configurations. Our Load Configuration is going to use the builder to include the required relationship: "UserGroupToUser".



var loadConfig = EntityLoadConfiguration.Default.Builder().WithRelations(new[] { "UserGroupToUser" }).Build();


Next, we need to get our User from the Context object of the Action script. The User object itself is not available here but we do have access to the TriggeringUserId property.

We will pass this ID into the MClient's GetUserAsync method, along with our custom load configuration, to get the User object with the data we require.



var user = await GetUser();

async Task GetUser () {
    var userId = Context.TriggeringUserId;
    return await MClient.Users.GetUserAsync(userId.Value, loadConfig);
}


Now we have a User object with the UserGroupToUser relationship returned within its data. Therefore, we can get the UserGroups from this relation data.

We are saying UserGroups (plural) here because a User can belong to one or many UserGroups. So this relationship is of a List type rather than a single value. Depending on our application, we may need to iterate through each of them to find the information we need. For my application, I wanted to aggregate all the taxonomies added to a custom field of all the UserGroups a User belonged to and add them to a field on the newly created Asset object.



var userGroupRelationship = await GetUserGroupRelationship(user);

foreach (int userGroupId in userGroupRelationship.Parents) {
    var userGroup = await GetUserGroup(userGroupId, loadConfig);
	
	// Here we can access each individual associated UserGroup
}

async Task GetUserGroupRelationship (IEntity user) {
    return await user.GetRelationAsync("UserGroupToUser");
}

async Task GetUserGroup (int userGroupId, IEntityLoadConfiguration config) {
    var ugQuery = Query.CreateQuery(entities =>
    from e in entities
    where e.Id == userGroupId
    select e);

    return await MClient.Querying.SingleAsync(ugQuery, config);
}


Last but not least, if you are modifying the data of the newly created asset... don't forget to save it at the end of the script!



await MClient.Entities.SaveAsync(asset);


Mike Headshot

Mike Payne

Development Team Lead

Mike is a Development Team Lead who is also Sitecore 9.0 Platform Associate Developer Certified. He's a BCIS graduate from Mount Royal University and has worked with Sitecore for over seven years. He's a passionate full-stack developer that helps drive solution decisions and assist his team. Mike is big into road cycling, playing guitar, working out, and snowboarding in the winter.