How to Search for Existing Groups

In this week’s post we look at the three most common queries to search for existing groups: getting all groups, “my groups”, and groups that match a particular filter.  While these examples show off the current prototype client, the filters and principles may be used on any client.  The test case source code may be downloaded from MSDN code gallery.

Example 1: All Groups

To search for all groups, we pass a simple filter “/group” to the Enumerate method.  The Enumerate method returns a .NET enumerator, which C# can use in its foreach construct.  Note that the enumerator returns the parent class RmResource and that we down-cast the returned object to an RmGroup.  Some queries might return a mixed bag of object types so it is necessary to check the status of the cast in production.

Behind the scenes the enumerator is making the enumerate and pull requests.  This iterator does not expose the count of the enumeration since we would prefer to move away from clients relying upon it.  Therefore, if you only want a fixed number of objects, either include a break in the foreach or make the pull request with MaxElements set to the value you desire.

[TestMethod]

public void Example1AllGroups()

{

    // In this example we enumerate all groups in the system

    // and show how to get some common attributes

    foreach (RmResource resource in client.Enumerate("/Group"))

    {

        RmGroup group = resource as RmGroup;

        Assert.IsNotNull(group);

        Console.WriteLine(String.Format(consoleFormat,

            group.DisplayName,

            group.ObjectID,

            group.DisplayedOwner,

            group.ExplicitMember.Count,

            (group.Type == RmGroupType.Distribution)

            )

        );

    }

}

Example 2: My Groups

To search for “my groups”, we search for groups whose owner are equal to the user’s ObjectID.  In this example we already know the user’s ObjectID (perhaps from a previous query for all users whose ObjectSid equals some value).  We also limit results to distribution lists by including the group type.  Note that this client contains an enum for group type for easy checks and searches.

[TestMethod()]

public void Example2GetMyDls()

{

    // In this example we enumerate all of "my" dls

    String filter = String.Format("/Group[{0}={1} and {2}='{3}']",

        RmGroup.AttributeNames.Owner.Name,

        "6FB8413E-49DA-48d9-A204-FFB8F0EEE133",

        RmGroup.AttributeNames.Type.Name,

        RmGroupType.Distribution

    );

       

    foreach (RmResource resource in client.Enumerate(filter))

    {

        RmGroup group = resource as RmGroup;

        Assert.IsNotNull(group);

        Assert.IsTrue(group.Type == RmGroupType.Distribution);

        Console.WriteLine(String.Format(consoleFormat,

            group.DisplayName,

            group.ObjectID,

            group.DisplayedOwner,

            group.ExplicitMember.Count,

            (group.Type == RmGroupType.Distribution)

            )

        );

    }

}

Example 3: Match DisplayName

To search for a group which has a DisplayName or MailNickname like a predicate, we need to use the contains and starts-with functions in FIM’s XPath dialect.  Nima posted great examples on his blog with a more complete description of FIM’s dialect features.  Last, note the static structures we’re using to refer to attribute names.  The static definitions of attributes specific to groups, like Owner and MailNickname, are stored in the RmGroup class.  The static definitions of attributes common to all objects types like DisplayName are stored in the RmResource class. The values of these attributes at runtime, however, are present on the RmGroup object. 

[TestMethod()]

public void Example3SearchGroups()

{

    // In this example we search for a group with displayname or alias that contain the search

    String filter = String.Format("/Group[contains({0}, '{1}') or starts-with({2}, '{1}')]",

        RmResource.AttributeNames.DisplayName.Name,

        "Sales",

        RmGroup.AttributeNames.MailNickname.Name

    );

 

    foreach (RmResource resource in client.Enumerate(filter))

    {

        RmGroup group = resource as RmGroup;

        Assert.IsNotNull(group);

        Console.WriteLine(String.Format(consoleFormat,

            group.DisplayName,

            group.ObjectID,

            group.DisplayedOwner,

            group.ExplicitMember.Count,

            (group.Type == RmGroupType.Distribution)

            )

        );

    }

}