Advise for and Handle Events in a Unified Communications Client API Client
This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.
The interface methods of the Unified Communications Client API operate asynchronously. That is, a client catches the results of an API operation by implementing callback methods defined by the API. In many cases, the event raised by a method call must be caught in order to advise for events on an instance of a Unified Communications API interface returned by the initial event.
A good example of this is the presence subscription process that provides real-time presence for remote users in the form of a contact list. The client advises for presentity events whose callback methods return category context data published by a given presentity. Each category context must also be advised so that category context events can be caught. A category context event returns an instance of published category information - the ultimate source of remote user presence information.
An essential part of a Unified Communications Client API application is to handle events raised by Unified Communications Client API objects. When a Unified Communications Client API client makes a request requiring an operation on a server, the client starts the operations by initiating appropriate requests to the server. The server processes the request and returns the results (data or operational status) in a series of events. The client does not block code execution to wait for results from the server. The client receives the results asynchronously by catching interested events. This implies that the client must implement an event handler for each event it is interested in and advise the object raising the event of the implemented event handler. Typically, a client advises the object of the handler when the object is created.
Unified Communications Client API defines the client-initiated method call in a COM interface inheriting from the IUnknown interface. It defines the server-returned events in a corresponding dispinterface, which inherits from the IDispatch interface supporting a specific way of invoking its members through a predefined DISPATCH ID. The names of the interfaces and their corresponding dispinterfaces are discussed in Naming Convention Used in Unified Communications Client API.
A C# implementation advises the object of the event handlers by calling a generic method (
UCC_Advise<T>(object source, T sink, out int cookie)), which wraps functionality exposed by the System.Runtime.InteropServices.ComTypes namespace, is shown in Code Listing: Basic Event Registration and Other Helper Methods in C#. This implementation of Advise is used in code examples throughout the SDK.
A good example of the asynchronous programming pattern previously discussed is as follows. To log a user into a server, a Unified Communications Client API client instantiates an endpoint object and advises it of endpoint event handlers. Calling Enable on an endpoint object implementing the IUccEndpoint interface starts the sign-in process. After authenticating the user and setting up the session configuration, the server returns the operational status to the originating IUccEndpoint object, which in turn raises an OnEnable event. To complete the sign-in process, the client must catch this event. To do so, the client implements the OnEnable method and advises the IUccEndpoint object of the implementation when the endpoint object is created. This programming pattern applies to all the asynchronous operations defined in any of the IUnknown interfaces in Unified Communications Client API.
In COM, the event advising means connecting an event source with an event sink. An event is raised by the event source and caught or handled in the event sink. In COM, this is accomplished by calling the IConnectionPoint::Advise method to connect the connection points from the source object to the sink object. A C# implementation to connect an event source with an event sink is shown in Code Listing: Basic Event Registration and Other Helper Methods in C#.
Each time an event handler is advised for, memory resources are consumed. When a client is no longer interested in events by some objects, it should cancel the advise action to conserve the application resources. A Unified Communications Client API client can cancel an event advise explicitly by calling the IConnectionPoint::Unadvise method to disconnect the connection points between the event source and the event sink. A C# implementation of this is shown in Code Listing: Basic Event Registration and Other Helper Methods in C#.
When a Unified Communications Client API client must cancel an event advise action explicitly, it must cache the event advise ID returned from the Advise method call.
For each asynchronous operation, a client can assign an operation ID and other application-specific properties to form the operation context. The client can pass this operation context to the asynchronous call. When the server returns an event for the operation, it passes this operation context as part of the event arguments. The client can use this information to correlate the result with a specific asynchronous operation. The operation ID serves to identify the sequence of the operation and the client can use it to associate a set of results with a method call. The operation context is encapsulated in the IUccOperationContext interface, which can be co-created using the UccOperationContext co-class.
The following example shows how to assign an operation ID and pass it into an asynchronous operation call.
UccOperationContext ctx = new UccOperationContext(); Int opId = 100; ctx.Initialize(opId, null);
For an asynchronous operation, the server returns ongoing operational status at different stages of the operation. Such operational status is encapsulated by the IUccOperationProgressEvent interface. When a client receives a status through an instance of this type, the client can check the IsComplete property to determine whether the operation is still pending or already completed. For example, when a client calls AddParticipant to invite a user to join a session, the server sends the invitation to the remote user on behalf of the local participant. If the remote user does not immediately accept the invitation and the server does not return operational status, the inviting client likely questions the long delay.