Friday, September 23, 2011

Recursing through Group Members with the Core Service

Yesterday I had to write a simple method to get me a list of all users who are members of a given group, using the Core Service.

Obviously, this is one of those tasks you'll immediately classify as "simple" or "easy" or "low complexity". Which is probably true, if you happen to have done this before...

Only one added twist, the list should contain all users who are members of this group, including sub-groups (groups members of the same group).

In TOM.NET this is a trivial foreach(Trustee trustee in group.Members), but in CoreService-land (and WCF-land) we don't have the Object Model available, only the data model. So I had to twist my mind for a while to get this to work, but eventually got it working as follows.

public Dictionary<string, string> GetUserEmailsByName(GroupData group)
{
    Dictionary<string, string> result = new Dictionary<string, string>();
    GroupMembersFilterData groupMembersFilter = new GroupMembersFilterData();
    foreach (XmlNode groupMemberNode in _coreServiceClient.GetListXml(group.Id, groupMembersFilter))
    {
        TrusteeData trustee = (TrusteeData)_coreServiceClient.Read(groupMemberNode.Attributes["href", Constants.XlinkNamespace].Value, ReadOptions);
        if (trustee is UserData)
        {
            if (trustee.Description.Contains("@"))
            {
                string userDescription = trustee.Description;
                string userEmail = UserEmailRegex.Match(userDescription).ToString();
                userDescription = userDescription.Replace(userEmail, "").TrimEnd();
                userEmail = userEmail.Replace("(", "").Replace(")", "");
                if (!result.ContainsKey(userDescription))
                    result.Add(userDescription, userEmail);
            }
        }
        else if (trustee is GroupData)
        {
            Dictionary<string, string> subMembers = GetUserEmailsByName((GroupData)trustee);
            foreach (string key in subMembers.Keys)
            {
                if (!result.ContainsKey(key))
                    result.Add(key, subMembers[key]);
            }
        }
    }
    return result;
}

The hard part to figure out was how to get the list of "Members" for this group, since GroupData does not expose that information:

_coreServiceClient.GetListXml(group.Id, groupMembersFilter)

Adding one more to the bag of CoreService patterns...

No comments: