This walkthrough discusses the principal conference management features provided by the Unified Communications Managed API 2.0 Core SDK that can be used by a Web scheduler application, an application that presents a Web user interface that can be used to manage conference scheduling. The walkthrough focuses on conference management operations that an application must perform for Web scheduling. Other aspects of the application are left to the developer.

Starting the Collaboration Platform

A server platform initialized with a trusted service GRUU is the recommended choice for such an application.

Copy Code
ServerPlatformSettings platformSettings =
new ServerPlatformSettings(_applicationName, _localhost, _port,
_trustedGruu, _certificate);

// We do not need the AudioVideo provider for conference management
operations.
platformSettings.DefaultAudioVideoProviderEnabled = false;

// Create the CollaborationPlatform object.
_platform = new CollaborationPlatform(platformSettings);

// Start the the platform object.
_platform.BeginStartup(PlatformStartupCallback, state);

In the previous code example, the application passes the trusted service GRUU provisioned for the specified port on the hosting computer. The application must provide an appropriate certificate to enable MTLS as well.

Important:
Because the platform uses a trusted service GRUU, any request initiated by an endpoint that uses this platform is not challenged by Office Communications Server. For that reason it is important for an application to authenticate a user through the Web interface using KERBEROS or other secure authentication method before proceeding with endpoint creation and executing user requests.

Creating a UserEndpoint Instance

The application must create an endpoint for each user. It is assumed that the application has already authenticated the user through KERBEROS or other form of secure authentication through the Web interface before proceeding with endpoint creation.

Copy Code
UserEndpointSettings userEndpointSettings = new
UserEndpointSettings(_userUri, _userServer, 5061);

_userEndpoint = new UserEndpoint(_platform, userEndpointSettings);

There is no need to establish the endpoint for conference scheduling applications. This approach avoids multiple points of presence (MPOP) scenarios and other presence-related complications. In addition, the application must know the meeting policies that are provisioned for the user.

Scheduling a New Conference

At this stage the application is ready to schedule a conference on behalf of the user. The application first must retrieve information about the available conferencing capabilities, such as activated MCUs and phone access support, offered by the deployed Office Communications Server. In addition to these capabilities, the application must know the meeting policies provisioned for the user.

Retrieving Conference Capabilities

The following code example demonstrates how the application can retrieve the conferencing capabilities offered by the deployed Office Communications Server.

Copy Code
  
_userEndpoint.ConferenceServices.BeginGetConferencingCapabilities(GetConferencingCapabilitiesCallback,
state);


private void GetConferencingCapabilitiesCallback(IAsyncResult
asyncResult)
{
  try
  {
	// Returns the conferencing capabilities available to the
endpoint owner.
	_conferencingCapabilities =
_userEndpoint.ConferenceServices.EndGetConferencingCapabilities(asyncResult);

	_avmcuAvailable = false;
	foreach (ConferenceMcuInformation mcuInformation in
_conferencingCapabilities.Mcus)
	{
	if (McuType.AudioVideo == mcuInformation.McuType)
	{
		// Indicates that the AVMCU is activated.
		_avmcuAvailable = true;
}
}

	// Indicates whether phone access is supported.
	_isPhoneAccessSupported =
_conferenceCapabilities.SupportsPhoneAccess;

  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information in the
	// Reason, GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown when no C3P error information is available.
  }
}

The ConferencingCapabilitiesinstance that is returned contains the following information:

  • Activated MCUs in the system, such as the InstantMessaging MCU (IM MCU) and the AudioVideo MCU (AV MCU).

  • Whether the deployed Office Communications Server supports phone access, and if so, the available phone numbers and regions.

ConferencingCapabilitieslists the activated MCUs in the system, but a user might be provisioned for Instant Messaging (IM) only and not audio. The application should permit such a user to schedule only IM-enabled conferences.

In addition to this information, the application must retrieve the user’s provisioning information to determine the meeting policy that applies to this user.

The user provisioning information also indicates whether a user can schedule conferences that allow anonymous users to bypass passcode verification. This is discussed further in a later section.

The next code example demonstrates how to retrieve and parse provisioning data.

Copy Code
_userEndpoint.BeginGetProvisioningData(GetProvisioningDataCallback,
state);
private void GetProvisioningDataCallback(IAsyncResult asyncResult)
{
  try
  {
	_provisioningData =
_userEndpoint.EndGetProvisioningData(asyncResult);
	ParseProvisioningData(_provisioningData, _isAudioAllowed,
_canPasscodeVerificationBeOptional);
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
  }
}

private static bool ParseProvisioningData(
	ProvisioningData provisioningData,
	out bool isAudioAllowed,
	out bool canPasscodeVerificationBeOptional)
{
  bool parsingSuccessful = false;

  // Assume false by default.
  isAudioAllowed = false;
  canPasscodeVerificationBeOptional = false;

  if (provisioningData != null &&
	provisioningData.MeetingPolicyConfiguration != null
&&
	 
!string.IsNullOrEmpty(provisioningData.MeetingPolicyConfiguration.ElementXml))
  {
	// Parse the meeting policy section of the provisioning data.

	// The meeting policy XML blob does not have a root, so just
add a fictitious root.
	string xml = string.Format("<{0}>{1}</{0}>",
"root", provisioningData.MeetingPolicyConfiguration.ElementXml);

	XmlDocument meetingPolicyXML = new XmlDocument();
	meetingPolicyXML.LoadXml(xml);
	XmlNamespaceManager xmlnsMgr = new
XmlNamespaceManager(meetingPolicyXML.NameTable);
	xmlnsMgr.AddNamespace("tempNs",
"http://schemas.microsoft.com/2006/09/sip/provisiongrouplist-notification");

	// Confirm whether the endpoint owner is provisioned for audio.
	isAudioAllowed = GetProvisioningSetting(meetingPolicyXML,
"root", "AllowIPAudio", xmlnsMgr);

	// Confirm whether passcode verfication can be optional.
	canPasscodeVerificationBeOptional =
!GetProvisioningSetting(meetingPolicyXML, "root",
"TrustedConferencingPinRequired", xmlnsMgr);

	parsingSuccessful = true;
  }
   
}

private static bool GetProvisioningSetting(
XmlDocument xmlDocument, 
string root, 
string provisioningKey, 
XmlNamespaceManager xmlnsMgr)
{
  string xpath =
string.Format("//{0}/tempNs:property[@name='{1}']", root,
provisioningKey);

  XmlNode node =
xmlDocument.DocumentElement.SelectSingleNode(xpath, xmlnsMgr);

  if (node != null)
  {
	return Convert.ToBoolean(node.FirstChild.Value);
  }
  else
  {
	throw new InvalidOperationException("Provisioning key does not
exist");
  }
}

The Web Scheduler application can use the information retrieved in the previous example to render user interface options to the user. The following sections explain how to schedule an audio-enabled conference and a PSTN-enabled conference.

Scheduling an Audio-Enabled Conference

Before scheduling an audio-enabled conference, the application must check that the AV MCU is available and that the user is provisioned for audio, as shown in the previous code example.

The ConferenceServices. BeginScheduleConferencemethod is used to schedule new conferences. The application uses a ConferenceScheduleInformationinstance to create a conference with specific settings.

Note:
A UserEndpointinstance can schedule conferences only for the endpoint owner and no other user. Each conference is identified by the conference organizer and a conference ID that is unique among the other conferences scheduled by the same organizer. If the application does not supply its own conference ID, the UCMA 2.0 Core SDK creates a GUID as the conference ID.

The following code example creates a ConferenceScheduleInformationinstance and sets basic conference properties on that instance.

Copy Code
ConferenceScheduleInformation csi = new
ConferenceScheduleInformation();
csi.Subject = "An audio-enabled conference";
csi.Description = "Demonstration of how to schedule an
audio-enabled conference";
csi.ExpiryTime = DateTime.Now.AddDays(2); //The default expiration
time is 8 hours.

The application must specify the admission policy. Three options are available:

  • ClosedAuthenticated

    Allows authenticated enterprise and federated users that are explicitly included in the participant list to join the conference. Other users are denied access.

  • OpenAuthenticated

    Allows authenticated enterprise users to join the conference (even those not explicitly included in the participant list). Federated users who are included in the participant list are allowed into the conference as well.

  • Anonymous

    Allows any authenticated enterprise, federated, or anonymous user to join the conference. Anonymous access is discussed in more detail in the next section.

The admission policy options are members of the ConferenceAdmissionPolicyenumeration.

The next code example sets the admission policy to ClosedAuthenticatedand adds participants to the participant list, including a leader.

Copy Code
csi.AdmissionPolicy =
ConferenceAdmissionPolicy.ClosedAuthenticated;
csi.Participants.Add(new
ConferenceParticipantInformation("sip:alice@contoso.com",
ConferencingRole.Attendee));
csi.Participants.Add(new
ConferenceParticipantInformation("sip:bob@contoso.com",
ConferencingRole.Leader)); // Bob is admitted as a leader.

The application must specify the list of participants who can join the conference by adding participants and specifying their role. On scheduling a closed authenticated conference, the organizer can use the participant list to specify other conference leaders and to allow federated users into the conference. The organizer does not need to be added to the list. By default, the organizer is considered to be a conference leader.

Assuming that the AV MCU is activated and the user is provisioned for audio, the application can add an audio-video MCU and an instant messaging MCU to the scheduled conference.

Copy Code
csi.Mcus.Add(new ConferenceMcuInformation(McuType.AudioVideo));
csi.Mcus.Add(new
ConferenceMcuInformation(McuType.InstantMessaging)); //For
IM-enabled clients.

The ConferenceServices. EndScheduleConferencemethod returns a Conferenceinstance for the scheduled conference. The Conference. ConferenceUriproperty returns the URI that participants can use to join the conference.

Copy Code
_userEndpoint.ConferenceServices.BeginScheduleConference(csi,
ScheduleAudioConferenceCallback, state);
private void ScheduleAudioConferenceCallback(IAsyncResult
asyncResult)
{
  try
  {
	_conference =
_userEndpoint.ConferenceServices.EndScheduleConference(asyncResult);
	// Conference ID : _conference.ConferenceID
	// Conference URI: _conference.ConferenceUri
  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information.
	// ConferenceFailureException wraps error information in the
	// Reason, GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown 
	// when no C3P error information is available.
  }
}

Scheduling a PSTN-Enabled Conference

A public switched telephone network-enabled (PSTN-enabled) conference is a conference that allows participants to join by phone as well as from other traditional clients. PSTN users dial specific access numbers to reach the deployed and activated application.

After calling the phone access number, a PSTN user is asked to enter the conference phone ID to identify the conference to join. Based on the conference settings, an application might challenge the user for a passcode. If the user provides a previously-assigned corporate PIN, the user is admitted as an authenticated participant. Otherwise, the user is admitted into the conference as an anonymous participant.

To organize a PSTN-enabled conference, the returned conferencing capabilities should indicate that phone access is supported (in other words, ConferencingCapabilities. SupportsPhoneAccessis set to true) and the AV MCU must be activated. The organizer should be provisioned for audio as well. Retrieving this information was illustrated in a previous section.

Copy Code
ConferenceScheduleInformation csi = new
ConferenceScheduleInformation();
csi.Subject = "A PSTN-enabled conference";
csi.Description = "Demonstrating scheduling an PSTN-enabled
conference";
csi.ExpiryTime = DateTime.Now.AddDays(1); // The default expiration
time is 8 hours.

Tto allow anonymous users access to the conference, the conference admission policy must be set to anonymous.

Copy Code
csi.AdmissionPolicy = ConferenceAdmissionPolicy.Anonymous;

Then, phone access must be enabled for this conference, and MCUs must be added to the list of MCUs supported by this conference.

Copy Code
csi.PhoneAccessEnabled = true;
csi.Mcus.Add(new ConferenceMcuInformation(McuType.AudioVideo));
csi.Mcus.Add(new
ConferenceMcuInformation(McuType.InstantMessaging)); // For
IM-enabled clients.

The organizer might require that anonymous users be challenged for a passcode before they are admitted into the conference. In other scenarios, the organizer can choose to have the application admit anonymous users into the conference without verifying their passcodes.

The organizer must be allowed by the administrator to schedule such a conference. Example code in a previous section demonstrated how to parse a user’s provisioning data to determine whether passcode verification is optional or required.

Note:
In case a client, for example Office Live Meeting 2007, does not support optional passcode verification for anonymous users, an organizer who schedules a conference with anonymous access must always provide a passcode, even if optional passcode verification was elected.

For PSTN-enabled conferences, the passcode must be a numeric string so that PSTN users can key in the passcode, when requested. The following example assumes that the user is provisioned to schedule conferences with optional passcode verification.

Copy Code
// For a PSTN-enabled conference, the passcode must be a numeric
string.
csi.Passcode = "22907323";

csi.IsPasscodeOptional = true;
_userEndpoint.ConferenceServices.BeginScheduleConference(csi,
SchedulePSTNConferenceCallback, state);
private void SchedulePSTNConferenceCallback(IAsyncResult
asyncResult)
{
  try
  {
	_conference =
_userEndpoint.ConferenceServices.EndScheduleConference(asyncResult);
  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information.
	// ConferenceFailureException wraps error information in the 
	// Reason, GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown when no C3P error information is
	// available.
  }
}

The Conferenceobject that is returned should include the conference ID that uniquely identifies the conference among all of the conferences scheduled by the organizer, and should include the conference phone ID to be used by PSTN users. The phone conference ID is a numeric string generated by the Office Communications Server computer that is unique among all PSTN-enabled conferences (including those organized by others). The returned Conferenceobject will also include the phone access numbers used by PSTN users to dial into the conference. A conference organizer must share the conference phone ID, phone access information, and passcode (if required) with PSTN users.

Copy Code
// The conference phone ID to be used by PSTN users to identify
which conference they want to join.
_conference.PhoneInformation.ConferencePhoneId;

// The phone access numbers to dial into the conference.
_conference.PhoneInformation.PhoneAccess;
Note:
A PSTN-enabled conference can also be joined using the conference URI that is returned in the Conferenceobject.

Summary

This section discusses how to retrieve conferencing capabilities provided by the system, and the organizer’s provisioning data, to determine the different scheduling mechanisms that are available to the organizer.

An application that is intended to schedule a conference on behalf of a user must:

  1. Retrieve conferencing capabilities by using the ConferenceServices. BeginGetConferencingCapabilitiesmethod to determine

    • Deployed and activated MCUs.

    • Whether phone access is enabled.

  2. Retrieve the organizer’s provisioning data and parse it to extract:

    • The MCUs provisioned for the organizer.

    • Whether the organizer can schedule conferences with optional passcode verification or not.

Enumerating and Retrieving Conference Details

The following example code retrieves a list of basic information for all conferences organized by the user.

Copy Code
_userEndpoint.ConferenceServices.BeginGetConferenceSummaries(GetConferenceSummariesCallback,
state);
private void GetConferenceSummariesCallback(IAsyncResult
asyncResult)
{
  try
  {
	_conferenceSummaries =
_userEndpoint.ConferenceServices.EndGetConferenceSummaries(asyncResult);

  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information.
	// ConferenceFailureException wraps error information in the
Reason,
	// GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown when no C3P error information is
	// available.
  }
}

The ConferenceSummarycollection that is returned includes a list of all conferences organized by the user. Each ConferenceSummaryinstance in the collection contains the conference ID, subject, admission policy, and conference URI. The application can retrieve this information about a conference by calling the ConferenceServices. BeginGetConferencemethod.

Copy Code
_userEndpoint.ConferenceServices.BeginGetConference(_conferenceSummaries[0].ConferenceId,
GetConferenceCallback, state);
private void GetConferenceCallback(IAsyncResult asyncResult)
{
  try
  {
	_conference =
_userEndpoint.ConferenceServices.EndGetConference(asyncResult);
  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information.
	// ConferenceFailureException wraps error information in the
	// Reason, GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown when no C3P error information is
	// available.
  }

}

Updating and Canceling Existing Conferences

An existing conference can be updated by a call to the ConferenceServices. BeginUpdateConferencemethod. This method takes a ConferenceScheduleInformationobject. To update the conference, the ConferenceScheduleInformationobject must include the conference ID and should also include the other properties that the application does not intend to change. If those properties are not set to the same values, their values are overridden.

The recommended way to update a conference is to first retrieve the full conference details using the ConferenceServices. BeginUpdateConferencemethod and convert the Conferenceobject that is returned by the ConferenceServices. EndUpdateConferencemethod into a ConferenceScheduleInformationobject.

This conversion preserves all the conference properties with the exception of phone access support. The application can then modify the specific properties it needs and leave the rest unchanged.

Copy Code
// Convert the retrieved Conference object to a
ConferenceScheduleInformation object.
ConferenceScheduleInformation csi = _conference;

// Preserve the phone access setting after conversion, as the
conversion does not preserve the value.
// If the conference contains phone information, then phone access
is enabled.
csi.PhoneAccessEnabled = (_conference.PhoneInformation != null);

// You can change most of the properties but do not change the
conference ID or the conference version.
// You must ensure that you retrieved the most updated conference,
or the update request will fail.
csi.Subject = string.Format("New conference updated at
{0}",DateTime.Now);

_userEndpoint.ConferenceServices.BeginUpdateConference(csi,
UpdateConferenceCallback, null);
private void UpdateConferenceCallback(IAsyncResult asyncResult)
{
  try
  {
	_updatedConference =
_userEndpoint.ConferenceServices.EndUpdateConference(asyncResult);
  }
  catch (ConferenceFailureException cfex)
  {
	// Perform appropriate error handling here.
	// ConferenceFailureException wraps Centralized Conferencing
Control Protocol (C3P) error information.
	// ConferenceFailureException wraps error information in the 
	// Reason, GeneralReason, and DiagnosticInformation properties.
  }
  catch (RealTimeException rte)
  {
	// Perform appropriate error handling here.
	// RealTimeException and RealTimeException derivatives are
thrown when no C3P error information is
	// available.
  }

}