The ContactGroupServicesclass provides a number of methods for managing contacts and groups.

The following code shows how to use the ContactGroupServicesproperty on a UserEndpointinstance to start the contacts and groups subscription. Also shown in this example are implementations of a ContactGroupSubscriptionCompletedcallback method and an event handler for the NotificationReceivedevent.

Copy Code
// Set up contact and group services
ContactGroupServices cgServices =
userEndpoint.ContactGroupServices;
// Register for NotificationReceived event
cgServices.NotificationReceived += CGNotificationReceived;

…

try
{
  cgServices.BeginSubscribe(ContactGroupSubscriptionCompleted,
cgServices);
}
catch(InvalidOperationException)
{
  Console.WriteLine(“Contact Group Subscription failed.”);
}
catch(RealTimeException exception)
{
  Console.WriteLine(
			“Contact Group Subscription failed. {0}”,
			exception.ToString() );
}

void ContactGroupSubscriptionCompleted(IAsyncResult asyncResult)
{
  ContactGroupServices cgServices = 
			asyncResult.AsyncState as ContactGroupServices;
  try
  {
	cgServices.EndSubscribe(asyncResult);
  }
  catch(RealTimeException exception)
  {
	Console.WriteLine(
			“Contact Group Subscription failed. {0}”,
			exception.ToString());
  }
}

void CGNotificationReceived(
	object sender, ContactGroupNotificationEventArgs e)
{
  if (e.FullNotification)
  {
	Console.WriteLine(“Got full notification of CG”);
  }
  Console.WriteLine(“Delta Numbers for this notification = {0}”,
					e.DeltaN
  foreach(NotificationItem<Contact > notification in
e.Contacts)
  {
	if (notification.Operation == PublishOperation.Add)
	{
	Console.WriteLine(“Contact Added. uri = {0} Name = [1}”, 
						 notification.Item.Uri,
notification.Item.Name);
}
	// notification.Item.GroupIDs indicate the list of groups this
	// contact is a member of.
  }
  // Similar code for Remove and Update operations. 


  foreach(NotificationItem<Group> notification in e.Groups)
  {
	if (notification.Operation == PublishOperation.Add)
	{
	Console.WriteLine(“Group Added. Name = [0} Id = {1}”, 
						 notification.Item.Name,
						 notification.Item.Groupid);
}
  }
  // Similar code for Remove and Update operations.
}

After ContactGroupServiceshas been initialized successfully with a subscription, the application will begin receiving notifications about the existing contacts and groups. After the subscription is completed, the application can add, remove, or update contacts or groups.

Copy Code
// Add a new contact.
try
{
  cgServices.BeginAddContact(
	 “sip:mybuddy@contoso.com”, AddContactCompleted, cgServices);
}
catch(InvalidOperationException)
{
  Console.WriteLine(“Add Contact failed with invalid operation.”);
}

catch(PublishSubscribeException pse)
{
  Console.WriteLine(“UpdateContact failed. {0}”, pse.ToString());
}

catch(RealTimeException exception)
{
  Console.WriteLine(“Add Contact failed.”, exception.ToString());
}

void AddContactCompleted(IAsyncResult asyncResult)
{
  ContactGroupServices cgServices = 
asyncResult.AsyncState as ContactGroupServices;
  try
  {
	cgServices.EndAddContact(cgServices);
  }
  catch(RealTimeException exception)
  {
	Console.WriteLine(“Add Contact failed.”, exception.ToString());
  }
}

The application can update a contact by first retrieving the cached contact, updating the properties, and then updating the contact. The reason for this is that the contact might have been already updated due to a recent notification. The delta number of the contact is needed to successfully update the contact. If the delta number does not match, it will fail the operation. The retrieval of the contact is an asynchronous operation since the cache might not exist at that time and a refresh operation might be needed for obtaining the contacts from the server in order to satisfy the requested operation.

Copy Code
// Assume that the application wants to update the name of a
contact 
try
{
  // Assume that the application has a simple container class for
storing information.
  MyContactOperation myContactOperation = new MyContactOperation();
  myContactOperation.Cgs = cgServices;
  myContactOperation.NewName = “updatedname”;
  
  cgServices.BeginGetCachedContact(
				“sip:mybuddy@contoso.com”, 
				GetCachedContactCompleted, myContactOperation);
}
catch(InvalidOperationException)
{
  Console.WriteLine(“GetCachedContact operation failed.”);
}

catch(PublishSubscribe Exception pse)
{
  Console.WriteLine(“UpdateContact failed. {0}”, pse.ToString());
}


catch(RealTimeException ex)
{
  Console.WriteLine(“GetCachedContact failed. {0}”, ex.ToString());
}

void GetCachedContactCompleted(IAsyncResult asyncResult)
{
  try
  {
	MyContactOperation myContactOperation = 
			asyncResult.AsyncState as MyContactOperation;
	Contact  updateContact =   
		 
myContactOperation.Cgs.EndGetCachedContact(asyncResult);
	updateContact.Name = myContactOperation.NewName;
	try
	{
	myContactOperation.Cgs.BeginUpdateContact(
				updateContact, UpdateContactCompleted,
				myContactOperation);
}
	catch(InvalidOperationException)
	{
	Console.WriteLine(“UpdateContact operation failed.”);
}
	catch(RealTimeException ex)
	{
	Console.WriteLine(“UpdateContact failed. {0}”,
ex.ToString());
}
  }
}

void UpdateContactCompleted(IAsyncResult asyncResult)
{
  try
  {
	MyContactOperation myContactOperation = 
			asyncResult.AsyncState as MyContactOperation;
	myContactOperation.Cgs.EndUpdateContact(asyncResult);
	Console.WriteLine(“Contact Update succeeded.”);  
  }

  catch(PublishSubscribe Exception pse)
  {
	Console.WriteLine(“UpdateContact failed. {0}”, pse.ToString());
  }

  catch(RealTimeException ex)
  {
	Console.WriteLine(“UpdateContact failed. {0}”, ex.ToString());
  }
}

ContactGroupServices State Transitions

The ContactGroupServicesstate transitions are shown in the following illustration. The state values are the members of the CollaborationSubscriptionStateenumerated type.

  1. The transition from Idleto Subscribingoccurs when the application calls BeginSubscribe.

  2. The transition from Subscribingto Subscribedoccurs when the subscription to the local presentity succeeds.

  3. The transition from Subscribingto Terminatingoccurs when the subscription to the local presentity fails. This is a non-recoverable error.

  4. The transition from Subscribingto WaitingForRetryoccurs when the subscription could not be successfully created, but the server requests UCMA 2.0 Core SDK to try subscribing to the cross-pool server, or to try subscribing at a later time because it is busy now.

  5. The transition from WaitingForRetryto Subscribingoccurs when another subscription to the local presentity is attempted for the reason given in step 4.

  6. The transition from WaitingForRetryto Terminatingoccurs when the subscription attempt to the local presentity fails.

  7. The transition from Subscribedto WaitingForRetryoccurs for one of the following reasons: when the server requests UCMA 2.0 Core SDK to close this subscription and create a new subscription. This action can happen at any time.

    • The server requests UCMA 2.0 Core SDK to close this subscription and to create a new subscription by sending a NOTIFY request with an Expires:0 parameter. The server can make this request at any time.

    • Route-set recovery begins.

    • The server sends a “481 Call leg unavailable” response.

  8. The transition from Subscribedto Terminatingoccurs when BeginUnsubscribeis called.

  9. The transition from Terminatingto Idleoccurs when the call to BeginUnsubscribeends successfully. The subscription can be reused; that is, an application can call BeginSubscribewhen the state is Idle.

ContactGroupServices Constructors

The ContactGroupServicesclass has no public constructors.

ContactGroupServices Properties

The following are the public properties on the ContactGroupServicesclass.

Copy Code
// Gets the state of the subscription.
public CollaborationSubscriptionState CurrentState {get;}

ContactGroupServices Methods

The following are the public methods on the ContactGroupServicesclass.

Copy Code
// Starts a service request to add a contact.
public IAsyncResult BeginAddContact(string contactUri,
	AsyncCallback userCallback,
	object state)

// Starts a service request to add a contact.
public IAsyncResult BeginAddContact(string contactUri,
	string contactName,
	bool isSubscribed,
	string contactData,
	string contactExtension,
	int[] groupIds,
	AsyncCallback userCallback,
	object state)

// Sends a service request to update the contact information for
the specified contact in contactList.
public IAsyncResult BeginUpdateContact(Contact contact,
AsyncCallback userCallback, object state)

// Sends a service request to remove the specified contact from
contactList.
public IAsyncResult BeginDeleteContact(string contactUri,
AsyncCallback userCallback, object state)

// Sends a service request to add the specified group in groups
list.
public IAsyncResult BeginAddGroup(string groupName, string
groupData, AsyncCallback userCallback, object state)

// Sends a service request to update the specified group
information for the group in groups list.
public IAsyncResult BeginUpdateGroup(Group group, AsyncCallback
userCallback, object state)

// Sends a service request to remove the specified group from
groups list.
public IAsyncResult BeginDeleteGroup(int groupId, AsyncCallback
userCallback, object state)

// Starts the asynchronous operation to get the cached contact.
public IAsyncResult BeginGetCachedContact(string contactUri,
AsyncCallback userCallback, object state)

// Starts the asynchronous operation to get the cached group.
public IAsyncResult BeginGetCachedGroup(int groupId, AsyncCallback
userCallback, object state)

// Ends the asynchronous operation initiated by BeginAddContact.
public void EndAddContact(IAsyncResult result)

// Ends the asynchronous operation initiated by BeginUpdateContact.
public void EndUpdateContact(IAsyncResult result)

// Ends the asynchronous operation initiated by BeginDeleteContact.
public void EndDeleteContact(IAsyncResult result)

// Ends the asynchronous operation initiated by BeginAddGroup.
public void EndAddGroup(IAsyncResult result)

// Ends the asynchronous operation initiated by BeginUpdateGroup.
public void EndUpdateGroup(IAsyncResult result)

// Ends the asynchronous operation initiated by BeginDeleteGroup.
public void EndDeleteGroup(IAsyncResult result)

// Completes the asynchronous operation initiated by
BeginGetCachedContact.
public Contact EndGetCachedContact(IAsyncResult result)

// Completes the asynchronous operation initiated by
BeginGetCachedGroup.
public Group EndGetCachedGroup(IAsyncResult result)

// Returns ContactGroupServices.MicrosoftRoamingContactEvent.
protected override string GetEventPackageName()

// Refresh the underlying subscription.
// If method is called before the subscription is established, it
will 
// throw InvalidOperationException.
public override IAsyncResult BeginRefresh(AsyncCallback
userCallback, object state)

ContactGroupServices Events

The following are the public events on the ContactGroupServicesclass.

Copy Code
// Raised when the contact group changes.
public event EventHandler<ContactGroupNotificationEventArgs>
NotificationReceived;

// Raised when there are changes in the state of the underlying
subscription.
public event EventHandler<SubscriptionStateUpdatedEventArgs>
SubscriptionStateChange;