Expand Minimize

Working with Lync 2010 Contextual Data Methods and Events

Summary:   This article and the accompanying video describe how to use Microsoft Lync 2010 to send and read contextual data. Two sample applications are used to show how contextual data properties, methods, and events interact in Lync 2010 contextual conversations.

Applies to:   Microsoft Lync 2010 SDK | Microsoft Lync 2010

Published:   May 2011 | Provided by:   John Clarkson, Microsoft | About the Author

Contents

Microsoft Lync 2010 SDK adds contextual data to conversations. The purpose of contextual data is to include data and functionality with a message at the time that it is sent so that the message immediately provides the information that is needed to discuss the topic or answer the question. Lync SDK provides two kinds of contextual data.

  • Initial context data is a smaller piece of data, up to 2 KB, and is used as introductory content. It is kept separate from context data so that initial data is always available to update participants who join a live conversation. Initial context data is sent in the SIP INVITE request, and is always cached. You can always update initial context data.

  • Context data is a larger piece of data, up to 64 KB. It is used for general context updates in a conversation. Context data is sent in the SIP INFO message, and is never cached.

Microsoft Lync 2010 contextual data APIs appear in Figure 1 and Figure 2.

Figure 1. Initial context data API

Initial context data

Figure 2. Context data API

Context Data

To understand how to use contextual data, we recommend that you create two Microsoft Lync 2010 extensibility applications. The first application sends data and the second receives the data.

Prerequisites

  • Microsoft Lync 2010

  • Microsoft Lync 2010 SDK

NoteNote

In addition to installing Lync client and Lync SDK, each computer must be configured to run in a Microsoft Lync Server 2010 domain.

For more information about prerequisites, see Walkthrough: Presence Hello World.

Creating the Application That Sends Contextual Data

  1. Create a Lync Silverlight Application. In the Page.xaml file, delete the existing content of the Grid control and replace it with the following XAML.

    <StackPanel>
      <StackPanel.Resources>
        <controls:ConversationContextualInfo 
          x:Key="contextualInfo" 
          ApplicationId="{}{21224942-AC24-4D0D-B0C7-6107D79448DF}"
          ApplicationData="ApplicationData data"
          Subject="Try out this customized subject!"
      />
      </StackPanel.Resources>
        <controls:StartInstantMessagingButton 
          x:Name="startInstantMessaging"
          Source="barbara@contoso.com"
          ContextualInformation="{StaticResource contextualInfo}"
      />
      <StackPanel HorizontalAlignment="Left" Height="100" Name="stackPanel1" Width="200">
        <Button Click="button1_Click" HorizontalAlignment="Left" Content="BeginSendInitialContext" Height="23" Name="button1" Width="149" />
        <Button Click="button2_Click" HorizontalAlignment="Left" Content="BeginSendContextData" Height="23" Name="button2" Width="148" />
      </StackPanel>
      <TextBox Height="23" Name="textBox1" Width="205" />
      <TextBox Height="23" Name="textBox2" Width="204" />
    </StackPanel>
    
  2. Add a project reference to Microsoft.Lync.Model.

  3. In the Page.xaml.cs file, add the following C# code.

    using Microsoft.Lync.Model.Conversation;
    using Microsoft.Lync.Model;
    
    namespace ContextDataSender
    {
        public partial class Page : UserControl
        {
            Conversation conversation;
            string AppData;
            int Counter = 0;
            
            // The following GUID must be registered, and match the GUID on the other clients.
            string AppId = "{21224942-AC24-4D0D-B0C7-6107D79448DF}";
    
            // Contains context data that is sent by the BeginSendInitialContext method.
            Dictionary<ContextType, object> context = new Dictionary<ContextType, object>();
    
            public Page()
            {
                InitializeComponent();
                // Get the Conversation object.
                conversation = (Conversation)Microsoft.Lync.Model.LyncClient.GetHostingConversation();
                
                // Display the contextual data the IM control sends.
                textBox1.Text = startInstantMessaging.ContextualInformation.ApplicationData;
            }
    
            // Starts the BeginSendInitialContext method.
            // This is the event handler for the Click event on button1.
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                // Add context data to the Dictionary object.
                context.Add(ContextType.ApplicationId, AppId);
                context.Add(ContextType.ApplicationData, textBox2.text);
    
                try
                {
                    // Send the initial context data and write a message to the text box.
                    IAsyncResult res = conversation.BeginSendInitialContext(context, null, null);
                    textBox1.Text = "InitialContextSent data";
                    context.Clear();   //Clear the contents of the Dictionary object
                }
                catch(LyncClientException ex)
                {
                    textBox1.Text = ex.Message;
                }
            }
    
            // Start the BeginSendContextData method.
            // This is the event handler for the Click event on button2.
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                // Counter that is used to update context data.
                Counter = Counter + 1;
    
                // Compose the string that is sent as context data.
                AppData = "ContextDataSent data: " + "counter = " + Counter.ToString();
    
                // Send the context data and write a message to the text box.
                IAsyncResult res = conversation.BeginSendContextData(AppId, "text/plain", AppData, SendContextDataCallback, null);
                textBox1.Text = AppData;
            }
    
            // Callback method for the BeginSendContextData method.
            public void SendContextDataCallback(IAsyncResult res)
            {
                conversation.EndSendContextData(res);
            }
        }
    }
    
  4. Build the application.

  5. Register the application. For more information, see Register Contextual Conversation Packages.

    NoteNote

    Registry text examples appear later in this article in the “Sample Code” section.

Creating the Receiving Application

  1. Create a Lync 2010 Silverlight Application. In the Page.xaml file, delete the existing content of the Grid control and add the following XAML.

    <Button Click="button1_Click" Content="GetApplicationData" Height="23" HorizontalAlignment="Left" Margin="24,14,0,0" Name="button1" VerticalAlignment="Top" Width="155" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,49,0,0" Name="textBox1" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,49,0,0" Name="textBlock1" Text="GetApplicationData Method Data" VerticalAlignment="Top" Width="204" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,138,0,0" Name="textBox2" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,138,0,0" Name="textBlock2" Text="InitialContextReceived event" VerticalAlignment="Top" Width="175" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,172,0,0" Name="textBox3" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,172,0,0" Name="textBlock3" Text="ContextDataReceived event" VerticalAlignment="Top" Width="167" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,201,0,0" Name="textBox4" VerticalAlignment="Top" Width="209" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="239,201,0,0" Name="textBlock4" Text="Event Data" VerticalAlignment="Top" Width="109" />
    <Button Click="button2_Click" Content="Clear TextBoxes" Height="23" HorizontalAlignment="Left" Margin="235,14,0,0" Name="button2" VerticalAlignment="Top" Width="128" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,94,0,0" Name="textBox5" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,94,0,0" Name="textBlock5" Text="ConversationContextLinkClicked event" VerticalAlignment="Top" Width="232" />
    
  2. Add a project reference to Microsoft.Lync.Model.

  3. In the Page.xaml.cs file, add the following C# code.

    using Microsoft.Lync.Model.Conversation;
    
    namespace LyncSilverlightApplication1
    {
        public partial class Page : UserControl
        {
            Conversation _conversation;
    
            // This GUID must be registered and must match the GUID on the other clients.
            string AppId = "{21224942-AC24-4D0D-B0C7-6107D79448DF}";
    
            public Page()
            {
                InitializeComponent();
    
                // Get the Conversation object.
                _conversation = (Conversation)Microsoft.Lync.Model.LyncClient.GetHostingConversation();
    
                // Register event handlers.
                _conversation.InitialContextReceived += new EventHandler<InitialContextEventArgs>(_conversation_InitialContextReceived);
                _conversation.ContextDataReceived += new EventHandler<ContextEventArgs>(_conversation_ContextDataReceived);
            }
    
            // ContextDataReceived event handler.
            void _conversation_ContextDataReceived(object sender, ContextEventArgs e)
            {
                textBox3.Text = "context data event";
                textBox4.Text = e.ContextData;
            }
    
            // InitialContextReceived event handler.
            void _conversation_InitialContextReceived(object sender, InitialContextEventArgs e)
            {
                textBox2.Text = "initial context event";
                textBox4.Text = e.ApplicationData;
            }
    
            // Starts the GetApplicationData method.
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    if (_conversation != null)
                    {
                        string data = _conversation.GetApplicationData(AppId);
                        textBox1.Text = data;
                    }
    
                    else
                        textBox1.Text = "no";
                }
                catch (Exception ex)
                { textBox1.Text = ex.Message; }
            }
    
            // Clears text boxes.
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                textBox1.Text = "";
                textBox2.Text = "";
                textBox3.Text = "";
                textBox4.Text = "";
            }
        }
    }
    
  4. Build the application.

  5. Register the application, and ensure that you use the same GUID as the application on the sending computer.

  6. Close the application. The incoming Lync IM message will open this application in the Conversation Window Extension.

Important noteImportant

The following four sections should be completed in this order:

  1. Send initial context data.

  2. Use the BeginSendInitialContext method to update initial context data.

  3. Send context data.

  4. Update context data.

Sending Initial Context Data

  1. Ensure that you are signed in to the Lync 2010 client on both computers.

  2. On the sending computer, use the StartInstantMessagingButton control to send an instant message to the receiving computer.

  3. On the receiving computer you will probably see something like Figure 3. It seems like no data was received. Often in this scenario the InitialContextReceived event occurs before the application opens. For this reason, in case your application needs initial context data immediately, use the GetApplicationData method to obtain that initial data instead of relying on the event.

    Figure 3. InitialContextReceived event occurs before application opens

    Step one
  4. Click the GetApplicationData button. The value of the ConversationContextualInfo.ApplicationData property appears.

    Figure 4. Use the GetApplicationData method to retrieve initial context data

    Step one

Summary:

  • When a Lync 2010 contextual data message opens the application on the receiving computer, the InitialContextReceived event is not dependable because the application takes time to open. In this case, using the event to retrieve initial context data will fail.

  • You can always get initial context data by using the GetApplicationData method.

Using the BeginSendInitialContext Method to Update Initial Context Data

  1. On the computer that is used to send contextual data, a second instance of the sending application appears in the Lync 2010 Conversation Window Extension (CWE). In the CWE, type initial context data in the text box, and then click BeginSendInitialContext to send a second version of the initial context data. The first version was sent in the instant message. This second version was sent by the BeginSendInitialContext method. In Figure 5, the initial contextual data appears in the Lync 2010 client on the computer that receives the message.

    Figure 5. Lync 2010 client after the InitialContextReceived event occurs

    Step two

    In Figure 5, the InitialContextReceived event occurred, and the application displays the content of the InitialContextEventArgs.ApplicationData property.

  2. In Figure 5, click Clear TextBoxes, and then click GetApplicationData. In Figure 6, the earlier version of the initial context data is replaced by the new version.

    Figure 6. Use the GetApplicationData method to retrieve initial context data

    Step two
  3. Summary:

    1. In step 1, the InitialContextReceived event and the InitialContextEventArgs.ApplicationData property are used to retrieve initial contextual data.

    2. In step 2, the first version of the initial contextual data is replaced at run time by the second message that contains new initial context data.

    3. The GetApplicationData method always gets the current version of initial context data.

    4. You can use the BeginSendInitialContext method to update initial context data multiple times. Each time that the BeginSendInitialContext method is used, you can enter a different string on the sending computer. The initial context data that is stored on the receiving computer is updated every time, and the GetApplicationData method retrieves an updated version of the new initial context data.

Sending Context Data

  1. On the computer that is used to send contextual data, click BeginSendContextData. The contextual data appears in Figure 7.

    Figure 7. Use the ContextDataReceived event to get context data

    Step three
  2. Click Clear TextBoxes, and then click GetApplicationData. In Figure 8, the GetApplicationData method retrieved the new version of the initial context data.

    Figure 8. The GetApplicationData method retrieves the new initial context data

    Step three

Summary:

Caution noteCaution

Context data can easily be lost if it is sent immediately after you send the SIP INVITE to open the contextual channel, because the application is opening and the ContextDataReceived event can be missed.

Updating Context Data

  1. On the computer that is used to send contextual data, click BeginSendContextData. In Figure 9, the contextual data appears on the receiving computer.

    Figure 9. Use the BeginSendContextData method to update context data.

    Step four
  2. Click Clear TextBoxes, and then click GetApplicationData. In Figure 10, the updated contextual data appears on the receiving computer.

    Figure 10. Initial context data exists separate from context data

    Step four

Summary:

  • Context data can be updated, and the ContextEventArgs.ContextData property always contains the current version.

  • Initial context data is separate from context data. The initial context data is never altered by updates to contextual data.

Summary

The following methods and events are used to send and read contextual data.

GetApplicationData method

Gets the contextual conversation initial context data by using the given application ID. Only the registered application that has the same ID can call this method. GetApplicationData has a single string parameter, the application ID.

BeginSendInitialContext method

Sends initial contextual data in a Lync 2010 contextual conversation. Because of the use of the ContextType enumeration in initial contextual data, the contextData parameter requires a Dictionary object.

BeginSendContextData method

Sends contextual data in a Lync 2010 contextual conversation. Use the dataType parameter to indicate the MIME type of the data.

InitialContextReceived event

This event occurs when initial contextual data is received in a conversation. Use the InitialContextEventArgs.ApplicationData property to get initial contextual data.

ContextDataReceived event

This event occurs when contextual data is received in a conversation. Use the ContextEventArgs.ContextData property to get contextual data.

The following sections include sample code and registry entries for both computers.

Code for the Sending Application

The following Page.xaml code is used by the application that sends contextual data.

<UserControl x:Class="BasicContextData1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:controls="clr-namespace:Microsoft.Lync.Controls;assembly=Microsoft.Lync.Controls" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <StackPanel.Resources>
                <controls:ConversationContextualInfo 
      x:Key="contextualInfo" 
      ApplicationId="{}{21224942-AC24-4D0D-B0C7-6107D79448DF}"
      ApplicationData="ApplicationData data"
      Subject="Try out this customized subject!"
    />
            </StackPanel.Resources>
            <controls:StartInstantMessagingButton 
      x:Name="startInstantMessaging"
      Source="mary@contoso.com"
      ContextualInformation="{StaticResource contextualInfo}"
    />
            <StackPanel HorizontalAlignment="Left" Height="100" Name="stackPanel1" Width="200">
                <Button Click="button1_Click" HorizontalAlignment="Left" Content="BeginSendInitialContext" Height="23" Name="button1" Width="149" />
                <Button Click="button2_Click" HorizontalAlignment="Left" Content="BeginSendContextData" Height="23" Name="button2" Width="148" />
            </StackPanel>
            <TextBox Height="23" Name="textBox1" Width="205" />
            <TextBox Height="23" Name="textBox2" Width="204" />
        </StackPanel>
    </Grid>
</UserControl>

The Page.xaml.cs code that is used by the application that sends contextual data appears in the next example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Lync.Model.Conversation;
using Microsoft.Lync.Model;

namespace ContextSample1
{
    public partial class Page : UserControl
    {
        Conversation conversation;
        string AppData;
        int Counter = 0;
        
        // The following GUID must be registered, and match the GUID on the other clients.
        string AppId = "application GUID – must match the GUID on other clients in this conversation";

        // Contains context data sent by the BeginSendInitialContext method.
        Dictionary<ContextType, object> context = new Dictionary<ContextType, object>();

        public Page()
        {
            InitializeComponent();
            // Get the Conversation object.
            conversation = (Conversation)Microsoft.Lync.Model.LyncClient.GetHostingConversation();
            
            // Display the contextual data that is sent by the IM control.
            textBox1.Text = startInstantMessaging.ContextualInformation.ApplicationData;
        }

        // Starts the BeginSendInitialContext method.
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // Add context data to the Dictionary object.
            context.Add(ContextType.ApplicationId, AppId);
            context.Add(ContextType.ApplicationData, "InitialContextSent data");
            context.Add(ContextType.ApplicationData, textBox2.Text);

            try
            {
                // Send the initial context data and write a message to the text box.
                IAsyncResult res = conversation.BeginSendInitialContext(context, null, null);
                textBox1.Text = "InitialContextSent data";
                context.Clear();        
            }
            catch(LyncClientException ex)
            {
                textBox1.Text = ex.Message;
            }
        }

        // Starts the BeginSendContextData method.
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            // Counter used to update context data.
            Counter = Counter + 1;

            // Compose the string sent as context data.
            AppData = "ContextDataSent data: " + "counter = " + Counter.ToString();

            // Send the context data and write a message to the text box.
            IAsyncResult res = conversation.BeginSendContextData(AppId, "text/plain", AppData, SendContextDataCallback, null);
            textBox1.Text = AppData;
        }

        // Callback method for the BeginSendContextData method.
        public void SendContextDataCallback(IAsyncResult res)
        {
            conversation.EndSendContextData(res);
        }
    }
}

Registry Entry on the Sending Computer

Registry text for the sending application appears in the next example.

[HKEY_CURRENT_USER\Software\Microsoft\Communicator\ContextPackages\{your application GUID}]
"InternalURL"="C:\\Data\\ContextSample1\\ContextSample1.Web\\ContextSample1TestPage.html"
"Name"="DataSample"

Code for the Receiving Application

The following Page.xaml code is used by the application that receives contextual data.

<UserControl x:Class="LyncSilverlightApplication1.Page"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:controls="clr-namespace:Microsoft.Lync.Controls;assembly=Microsoft.Lync.Controls" 
  mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
    <Button Click="button1_Click" Content="GetApplicationData" Height="23" HorizontalAlignment="Left" Margin="24,14,0,0" Name="button1" VerticalAlignment="Top" Width="155" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,49,0,0" Name="textBox1" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,49,0,0" Name="textBlock1" Text="GetApplicationData Method Data" VerticalAlignment="Top" Width="204" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,138,0,0" Name="textBox2" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,138,0,0" Name="textBlock2" Text="InitialContextReceived event" VerticalAlignment="Top" Width="175" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,172,0,0" Name="textBox3" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,172,0,0" Name="textBlock3" Text="ContextDataReceived event" VerticalAlignment="Top" Width="167" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,201,0,0" Name="textBox4" VerticalAlignment="Top" Width="209" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="239,201,0,0" Name="textBlock4" Text="Event Data" VerticalAlignment="Top" Width="109" />
    <Button Click="button2_Click" Content="Clear TextBoxes" Height="23" HorizontalAlignment="Left" Margin="235,14,0,0" Name="button2" VerticalAlignment="Top" Width="128" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="24,94,0,0" Name="textBox5" VerticalAlignment="Top" Width="166" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="235,94,0,0" Name="textBlock5" Text="ConversationContextLinkClicked event" VerticalAlignment="Top" Width="232" />
  </Grid>
</UserControl>

The Page.xaml.cs code that is used by the application that receives contextual data appears in the next example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Lync.Model.Conversation;

namespace LyncSilverlightApplication1
{
    public partial class Page : UserControl
    {
        Conversation _conversation;

        // This GUID must be registered and must match the GUID on the other clients.
        string AppId = "application GUID – must match the GUID on other clients in this conversation";

        public Page()
        {
            InitializeComponent();

            // Get the Conversation object.
            _conversation = (Conversation)Microsoft.Lync.Model.LyncClient.GetHostingConversation();

            // Register event handlers.
            _conversation.InitialContextReceived += new EventHandler<InitialContextEventArgs>(_conversation_InitialContextReceived);
            _conversation.ContextDataReceived += new EventHandler<ContextEventArgs>(_conversation_ContextDataReceived);
        }

        // ContextDataReceived event handler.
        void _conversation_ContextDataReceived(object sender, ContextEventArgs e)
        {
            textBox3.Text = "context data event";
            textBox4.Text = e.ContextData;
        }

        // InitialContextReceived event handler.
        void _conversation_InitialContextReceived(object sender, InitialContextEventArgs e)
        {
            textBox2.Text = "initial context event";
            textBox4.Text = e.ApplicationData;
        }

        // Starts the GetApplicationData method.
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (_conversation != null)
                {
                    string data = _conversation.GetApplicationData(AppId);
                    textBox1.Text = data;
                }

                else
                    textBox1.Text = "no";
            }
            catch (Exception ex)
            { textBox1.Text = ex.Message; }
        }

        // Clears text boxes.
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text = "";
            textBox2.Text = "";
            textBox3.Text = "";
            textBox4.Text = "";
        }
    }
}

Registry Entry on the Receiving Computer

Registry text for the receiving application appears in the next example.

[HKEY_CURRENT_USER\Software\Microsoft\Communicator\ContextPackages\{your application GUID}]
"InternalURL"="C:\\Data\\LyncSilverlightApplication1\\LyncSilverlightApplication1.Web\\LyncSilverlightApplication1TestPage.html"
"Name"="DataSample"

In this article two sample applications demonstrate the following:

  • Initial context data and context data is held as separate data stores.

  • Both initial context data and context data can be updated. Updating one does not affect the other, they are separate.

  • To return initial context data, use the GetApplicationData method. After the application is started, you can also use the InitialContextReceived event to get the value of the InitialContextEventArgs.ApplicationData property.

  • To return context data, use the ContextDataReceived event to get the value of the ContextEventArgs.ContextData property.

John Clarkson is a programming writer with the Microsoft Lync product team.

Show:
© 2014 Microsoft