Walkthrough: Expand a Distribution Group (Lync 2010 SDK)

A distribution group is a mail-enabled Active Directory group objects. Using Exchange Server tools you can add either individual users or other distribution groups to a distribution group. A distribution group is in a collapsed or expanded state. When collapsed, the distribution group’s members are not visible. When you expand a distribution group to access the contacts within it, you may also expand distribution groups that may be nested with it. A nested distribution group can contain additional nested distribution groups. To expand a distribution group you call BeginExpand. Any nested distribution groups can be expanded with another call to BeginExpand.

Warning

You should not recursively expand a distribution group and any nested distribution groups. Such recursive expansion exposes your client to the risk that memory resources will be exhausted if the number of contacts in all nested distribution groups is a very large number. In a large enterprise with thousands of users in the enterprise Active Directory, distribution groups that encompass the entire employee population can be created.

When you get a contact from any distribution group, you subscribe to the contact in order to get contact information such as availability. If a given distribution group has been expanded within the Microsoft Lync 2010 UI, then you do not add the contact members of that distribution group to your contact subscription.

Distribution Group Expansion

The following set of walkthrough sections take you through the process of searching for a distribution group, handling the search callback, and expanding the top level distribution group.

Search for a Distribution Group

The following walkthrough starts a distribution group search operation. To search for contacts, you execute the same steps.

  1. Get an instance of LyncClient by calling into the static GetClient method.

  2. Check the state of the client by reading the State property. If the client is not signed in, you must sign the client in. For information about signing into Lync 2010, see Walkthrough: Sign In to Lync (Lync 2010 SDK).

  3. Get a set of SearchFields to specify the attributes of distribution groups to search for. Call into GetSearchFields.

  4. Start the search operation by calling into BeginSearch.

    Tip

    If you want to search using default search values, call BeginSearch

Handle Search Callback

The following walkthrough handles the search result callback by iterating on search results.

To get the presence of a Contact, you must subscribe to the contact. For information about subscribing to contacts, see Walkthrough: Search For a Contact (Lync 2010 SDK)

  1. Check to see if the operation is compete by reading the IsCompleted property and verifying that true is returned.

  2. Call EndSearch on the ContactManager instance used to start the search. An instance of SearchResults is returned.

  3. Iterate on the Groups property.

  4. Cast each instance of Group to DistributionGroup so that you can get the distribution group related properties and methods.

  5. Read the IsExpanded property.

    1. If true:

      1. Iterate on the Collection of Contact instances to get all of the contacts in the expanded group. You must add each contact to a ContactSubscription in order to get current contact information.

      2. Iterate on the group collection value of the DistributionGroup.NestedGroups property.

    2. If false: Call BeginExpand to expand the distribution group.

    3. End the expansion operation by calling EndExpand. If the distribution group is too large, LyncClientException is raised.

  6. Call Subscribe to start the subscription to all of the contacts obtained in the previous step.

Examples

Class Type Declarations

The following example declares a delegate and event that a Windows Form class registers for to catch the results of the search and distribution group expansion operation.

namespace DgExpansionExample
{
    public delegate void SearchResultDelegate (Dictionary<string, Contact> searchResult);
...
public class ClientModel:IDisposable
    {
        public event SearchResultDelegate ResultOfSearchEvent;
        private Dictionary<string, Contact> FoundContactList;
        private LyncClient _LyncClient;
        private ContactSubscription _ContactSubscription;

        /// <summary>
        /// A collection of objects of type Contact or DistributionGroup. Represents
        /// individual contacts found in a distribution group and all distribution group
        /// in the NestedGroups collection of the found distribution
        /// group. 
        /// This list can be the source consumed by application logic that fills a ListBox on a UI. 
        /// </summary>
        private List<object> _contactListObjects;



...

Search for a Distribution Group

The following example searches for a distribution group.

        /// Method that instigates the search; called by button click
        /// Set to search the Global Address List
        /// parameter "searchName" is entered string from form
        public void SearchForGroupOrContact(string searchName, uint numResults)
        {
            try
            {
                _LyncClient = LyncClient.GetClient ();
            }
            catch (ClientNotFoundException h)
            {
                throw new ClientWrapException(h, "Lync is not running", true);
            }
            if (_LyncClient.State == ClientState.SignedIn)
            {
                SearchFields searchFields = _LyncClient.ContactManager.GetSearchFields();
                object[] _asyncState = { _LyncClient.ContactManager, searchName };
                _LyncClient.ContactManager.BeginSearch(
                    searchName
                    , SearchProviders.GlobalAddressList | SearchProviders.ExchangeService | SearchProviders.WindowsAddressbook
                    , searchFields
                    , SearchOptions.Default
                    , numResults
                    , SearchResultsCallback
                    , _asyncState);
            }
        }

Handle Search Callback

The following example handles the callback raised when a search operation completes. A search operation can only return individual contacts or distribution groups. It does not return custom groups defined by the local user. For this reason, you can assume that any group returned in the search results groups collection is a distribution group.

        /// Handles callback containing results of a search
        /// </summary>
        /// <param name="source"></param>
        /// <param name="results"></param>
        /// <param name="_asyncOperation"></param>
        public void SearchResultsCallback(IAsyncResult ar)
        {
            if (ar.IsCompleted == true)
            {
                SearchResults results = null;
                object[] _asyncState = (object[])ar.AsyncState;
                results = ((ContactManager)_asyncState[0]).EndSearch(ar); 
                if (results != null)
                {
                    FoundContactList = new Dictionary<string,Contact>();
                    _ContactSubscription = _LyncClient.ContactManager.CreateSubscription();

                    foreach (Group _SearchResultGroup in results.Groups)
                    {
                        DistributionGroup foundGroup = _SearchResultGroup as DistributionGroup;
                        DGExpander(foundGroup);
                        break;
                    }
                }
            }
        }

Distribution Group Expansion Helper Method

The following example gets all of the contacts and nested distribution groups out of a distribution group, adds them to a collection of object, and subscribes to all of the contacts in the distribution group. If the distribution group is not expanded when returned in search results, the example first expands the distribution group and then gets the members of the group.

        /// <summary>
        /// Expands any groups found in search results 
        /// </summary>
        /// <param name="workMaterial"></param>
        private void DGExpander(DistributionGroup DGGroup)
        {
            //Only distribution groups can be expanded.
            //_Group is a class field that references the Microsoft.Lync.Model.Group.Group instance
            //encapsulated by the GroupModel class.
            if (DGGroup.Type != GroupType.DistributionGroup)
            {
                return;
            }

            IAsyncResult asyncOpResult = null;

            //If the distribution group has not been expanded yet,
            //it must be expanded before group members are visible
            if (DGGroup.IsExpanded == false)
            {
                //Begin the group expansion operation
                asyncOpResult = DGGroup.BeginExpand(null, null);

                //Block this thread until expansion is complete.
                //not necessary
                asyncOpResult.AsyncWaitHandle.WaitOne();

                try
                {
                    //Complete group expansion operation
                    DGGroup.EndExpand(asyncOpResult);
                }
                catch (LyncClientException)
                {
                    System.Windows.Forms.MessageBox.Show("Lync Client Exception on expand " + DGGroup.Name);
                }

                if (DGGroup.Count > 0)
                {
                    foreach (Contact c in DGGroup)
                    {
                        //object list for use of list box
                        _contactListObjects.Add(c);
                        _ContactSubscription.AddContact(c);
                    }
                }
                foreach (Group group in DGGroup.NestedGroups)
                {
                    // object list for use of list box
                    _contactListObjects.Add(group);
                }
            }
            else
            {
                if (DGGroup.Count > 0)
                {
                    foreach (Contact c in DGGroup)
                    {
                        // object list for use of list box
                        _contactListObjects.Add(c);
                        _ContactSubscription.AddContact(c);
                    }
                }
                foreach (Group group in DGGroup.NestedGroups)
                {
                    // object list for use of list box
                    _contactListObjects.Add(group);
                }
            }
            //Specify the ContactInformationTypes to subscribe for.
            ContactInformationType[] subscriptionTypes = {ContactInformationType.Activity, ContactInformationType.Availability};

            //Subscribe to the contacts and contact information in this contact subscription.
            _ContactSubscription.Subscribe(ContactSubscriptionRefreshRate.Low, subscriptionTypes);
        }

See Also

Concepts

Lync Model API Contacts and Groups Walkthroughs (Lync 2010 SDK)

Walkthrough: Search For a Contact (Lync 2010 SDK)

Change History

Date

History

Reason

March 2011

Updated code examples to simplify distribution group expansion

Content bug fix.