A distribution group is created and updated using Microsoft Outlook. Updating a distribution group includes adding or removing individual contacts and other distribution groups. When you expand a distribution group to access the contacts within it, you must also expand distribution groups that may be nested with it. A nested distribution group can contain additional nested distribution groups. To get all of the contacts within all possible nested distribution groups, you application code should be designed to recursively call BeginExpand .

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, expanding the top level distribution group, and recursively expanding any nested distribution groups.

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 .

  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 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 and expanding any distribution group found among the results.

To get the presence of a Contact at any level of distribution group nesting, you must subscribe to the contact. For information about subscribing to contacts, see Walkthrough: Search For a Contact

  1. Check to see if the operation is compete by reading the IsCompleted property and verifying that trueis 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 and cast each instance of Group to DistributionGroup so that you can get the distribution group related properties and methods.

  4. Read the IsExpanded property.

    1. If true: Call BeginGetAllMembers to get all of the contacts in the group.

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

Handle Distribution Group Expansion Callback

The distribution group expansion callback logic in the following walkthrough can be executed whether you've called BeginGetAllMembers or BeginExpand .

There is a limit to the size of a distribution group that can be expanded. If you attempt to expand a distribution group beyond the size limit, a LyncClientException is raised. The exception is raised with the EndExpand call. For this reason, you must enclose the call inside a Try/ Catchblock where this exception is caught.

You should use a recursive code pattern within this callback if you want to expand nested distribution groups automatically. Alternatively, your application can leave each nested group un-expanded and pass the nested group to your UI. If you provide a group expansion control to your user, you can individually expand nested groups. Using this technique, you do not call BeginExpand or BeginGetAllMembers recursively. Instead, call either method using the individual distribution group specified by a user. The following walkthrough automatically expands all nested distribution groups.

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

    Important note Important

    An individual user may exist in multiple nested distribution groups. Before executing the next step, you should verify that you have not already added a contact to the contact subscription. You cannot call ContactsContains(Titem) . While the actual user can be a duplicate, the Contact instance representing the user is unique within each distribution group. Instead, maintain a list of contact Uri strings, one Uri for each contact you add to the contact subscription. Before adding the current contact to the contact subscription, check your list for an Uri matching the new Uri . If not in the list, add to the list and contact subscription.

  2. 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.

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

  4. Get the collection of nested groups by reading the NestedGroups property value.

  5. For each Group:

    1. Check the expanded state of the group by reading the IsExpanded property.

    2. If true, call BeginGetAllMembers , passing the same group expansion callback that is described in these walkthrough steps..

      Important note Important

    3. If false, call BeginExpand , passing the same group expansion callback that is described in these walkthrough steps.

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.

C#  Copy imageCopy Code
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;

...

Search for a Distribution Group

The following example searches for a distribution group.

C#  Copy imageCopy Code
		///// 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

C#  Copy imageCopy Code
		/// 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;
						if (foundGroup.IsExpanded == true)
						{
						 
foundGroup.BeginGetAllMembers(GroupExpansionCallback, foundGroup);
					}
						else
						{
						 
foundGroup.BeginExpand(GroupExpansionCallback, foundGroup);
					}
						break;
				}
			}
		}
	}

Handle Distribution Group Expansion Callback

The following example handles the callback invoked when a group expansion operation completes. The example automatically expands all nested distribution groups.

C#  Copy imageCopy Code
		/// <summary>
		/// Invoked when a group expansion operation completes.
		/// </summary>
		/// <param name="ar">IAsyncResult. The result of the
operation.</param>
		private void GroupExpansionCallback(IAsyncResult ar)
		{
			DistributionGroup searchResultGroup =
((DistributionGroup)ar.AsyncState);
			try
			{
				searchResultGroup.EndExpand(ar);
		}
			catch (LyncClientException)
			{
				System.Windows.Forms.MessageBox.Show("Lync Client
Exception on expand " + searchResultGroup.Name);
		}
			finally
			{
				foreach (Contact groupContactObject in
searchResultGroup)
				{
					Contact groupContact =
(Contact)groupContactObject;

					//Check dictionary for existence of this user
in another distribution group.
					if
(_FoundContactList.ContainsKey(groupContact.Uri) == false)
					{
						//If not already added to dictionary and
contact subscription, add the contact.
						_FoundContactList.Add(groupContact.Uri,
groupContact);
					 
_ContactSubscription.AddContact(groupContact);
				}
			}

				//If a class instance has registered for
ResultOfSearchEvent, ResultOfSerchEvent is not null
				if (ResultOfSearchEvent != null)
				{
					//Iterate on all contacts found in distribution
group to add to ContactSubscription.
					Foreach(Contact c in _FoundContactList)
					{
						_ContactSubscription.AddContact(c);
				}

					//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);

					//Raise event to registered class instances.
					ResultOfSearchEvent(_FoundContactList);

					//Clear List<Contact> for next recursion.
					_FoundContactList.Clear();
			}

				foreach (Group nestedGroup in
searchResultGroup.NestedGroups)
				{
					DistributionGroup nestedDG =
(DistributionGroup)nestedGroup;
					if (nestedDG.IsExpanded == true)
					{
						//Recursive asynchronous callback
					 
nestedDG.BeginGetAllMembers(GroupExpansionCallback, nestedDG);
				}
					else
					{
						//Recursive asynchronous callback
					 
nestedDG.BeginExpand(GroupExpansionCallback, nestedDG);
				}
			}
		}
	}

See Also