Office 365 – Share Outlook contacts with Lync Online contextual conversations
At first glance Microsoft Lync can, to most people, look like just another instant messaging application. However, upon closer inspection it can mean so much more for organizations especially if they start to integrate it into their current day-to-day business systems. For example, if you’re an insurance firm running a system that maintains all your clients and their policies and you want to give your employees the ability to discuss a client without having to send e-mails. You could integrate with Lync and add a feature to start a contextual Lync conversation based on the currently selected client the user has open in your management system.
To illustrate my point we’ll create a simple WPF application with which users can share and discuss their Microsoft Outlook contacts.
Start by creating a new WPF Application project in Visual Studio 2010.
Open MainWindow.xaml and drag a Listview control onto the designer surface. Set the window’s height to 520 and width to 850 and change the xaml for the listview to the following:
<ListView Height="287" HorizontalAlignment="Left" Name="contactListview" VerticalAlignment="Bottom" Width="489" Margin="12,0,0,183" Grid.ColumnSpan="2"> <ListView.View> <GridView> <GridViewColumn Width="150" Header="Name" /> <GridViewColumn Width="150" Header="Company"/> <GridViewColumn Width="170" Header="E-mail"/> </GridView> </ListView.View> </ListView>
You should now see a listview on your form with 3 columns, as illustrated below.
Next drag a ContactCard control onto your form. You should see the ContactCard control under the Lync SDK Controls tab in the Visual Studio Toolbox. If you don’t see the control or toolbox tab you probably do not have the Lync SDK installed. Download it from the Microsoft Download Center.
Finally, add a GroupBox control with three Textbox controls, labels and a button to the form. The completed form design should be similar to the following image:
Add a new class to your project and call it SimpleOutlookContact.
public class SimpleOutlookContact { public string FullName { get; set; } public string CompanyName { get; set; } public string Email { get; set; } }
Switch to the MainWindow.xaml.cs file and add the LoadContacts method:
private void LoadContacts() { List<SimpleOutlookContact> contacts = null; Outlook.Application outlookApp = null; Outlook.NameSpace nameSpace = null; Outlook.MAPIFolder contactsFolder = null; try { contacts = new List<SimpleOutlookContact>(); outlookApp = new Outlook.Application(); nameSpace = outlookApp.GetNamespace("MAPI"); contactsFolder = nameSpace.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderContacts); for (int i = 1; i < contactsFolder.Items.Count + 1; i++) { Outlook.ContactItem outlookContact = contactsFolder.Items[i] as Outlook.ContactItem; if (outlookContact != null) { SimpleOutlookContact contact = new SimpleOutlookContact(); contact.FullName = outlookContact.FullName; contact.CompanyName = outlookContact.CompanyName; contact.Email = outlookContact.Email1Address; contacts.Add(contact); Marshal.ReleaseComObject(outlookContact); } } } finally { if (contactsFolder != null) Marshal.ReleaseComObject(contactsFolder); if (nameSpace != null) Marshal.ReleaseComObject(nameSpace); if (outlookApp != null) Marshal.ReleaseComObject(outlookApp); } this.contactListview.ItemsSource = contacts; }
This method will retrieve all Outlook contacts and add it to a generic list of SimpleOutlookContacts. The next step is to set the listview on the form’s ItemsSource property equal to the list. Then, we need to hook up the listview’s data binding; to do this, change its XAML to:
<ListView.View> <GridView> <GridViewColumn Width="150" Header="Name" DisplayMemberBinding="{Binding FullName}"/> <GridViewColumn Width="150" Header="Company" DisplayMemberBinding="{Binding CompanyName}"/> <GridViewColumn Width="170" Header="E-mail" DisplayMemberBinding="{Binding Email}"/> </GridView> </ListView.View>
Change the Window’s constructor to call the LoadContacts method and compile and run your application.
public MainWindow() { InitializeComponent(); LoadContacts(); }
Add the following class level declarations:
LyncClient lyncClient; ConversationManager conversationManager; ApplicationRegistration appRegistration; string appId = "{3DF30DE6-84DA-45B2-A621-31DAF0CBB63E}"; string appName = "LyncOutlookContactShare"; string contactCardSource = "anotherperson@yourdomain.com";
You need to add a reference to Microsoft.Lync.Model.dll to get access to the Lync specific objects. Generate a new GUID for the appId variable and change the contactCardSouce variables’ value to one of the contacts you have in your Lync contact list. Change the windows’ constructor to call the LoadContacts method and compile and run your application.
public MainWindow() { InitializeComponent(); LoadContacts(); }
If all goes well, you should see a list of your Outlook contacts in the listview.
Next, create an event handler for the Window’s Loaded event by double-clicking the event in the events list in the Visual Studio Properties window.
Add the following code to the Window’s Loaded event handler:
private void Window_Loaded(object sender, RoutedEventArgs e) { contactCard.Source = contactCardSource; lyncClient = LyncClient.GetClient(); conversationManager = lyncClient.ConversationManager; appRegistration = lyncClient.CreateApplicationRegistration(appId, appName); appRegistration.AddRegistration(); }
The code above sets the Lync ContactCard controls’ source to the contactCardSource variable we’ve declared earlier and it gets a reference to the current open Lync Client. The CreateApplicationRegistration is used to register your application and tell Lync that it can be trusted for contextual conversations.
We also need to specify what data should be sent as part of the Lync context. To do this add a new event handler for the listview’s SelectionChanged event and add the following code:
private void contactListview_SelectionChanged(object sender, SelectionChangedEventArgs e) { SimpleOutlookContact outlookContact = (SimpleOutlookContact)contactListview.SelectedItem; ConversationContextualInfo contextInfo = new ConversationContextualInfo(); contextInfo.Subject = "Discuss Contact : " + outlookContact.FullName; contextInfo.ApplicationId = appId; contextInfo.ApplicationData = outlookContact.ToString(); contactCard.ContextualInformation = contextInfo; }
We first need to create an instance of a SimpleOutlookContact object from the currently selected item in the listview and then specify what the Lync conversation window’s title should display by setting the Subject property. I’ve over-ridden the SimpleOutlookContact object’s ToString method, it now returns the data of the client in a comma delimited string. This string will be passed via the conversation context to the person you’re having a conversation with.
Up to this point our code will send the context and update the Lync Conversation window with the value we’ve specified. Next we need to add code to run when the user receiving the context, clicks on the link in the Lync conversation window that will open the Outlook contact.
To do this, add an event handler for the conversation manager by adding the following to the Window’s Loaded event:
conversationManager.ConversationAdded += conversationManager_ConversationAdded;
In the ConversationAdded event handler, add the following to create an event handler for when the user clicks the context link in the conversation window:
void conversationManager_ConversationAdded(object sender, ConversationManagerEventArgs e) { e.Conversation.ConversationContextLinkClicked += Conversation_ConversationContextLinkClicked; }
In the ConversationContextLinkClicked event handler add the following:
void Conversation_ConversationContextLinkClicked(object sender, InitialContextEventArgs e) { this.Dispatcher.Invoke( DispatcherPriority.Input, new Action(() => { string contactXML = e.ApplicationData; DisplayContact(contactXML); })); }
The DisplayContact method looks like the following:
private void DisplayContact(string contactData) { SimpleOutlookContact receivedContact = new SimpleOutlookContact(contactData); txtName.Text = receivedContact.FullName; txtCompany.Text = receivedContact.CompanyName; txtEmail.Text = receivedContact.Email; }
I’ve overloaded the SimpleOutlookContact object’s constructor to take a string value that contains the data for the contact and load it into the object.
We need to add one more item to the project before we can test it. Add a new text file to your solution and call it registryEntry.reg. Add the following text to the file:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Communicator\ContextPackages] [HKEY_CURRENT_USER\Software\Microsoft\Communicator\ContextPackages\{3DF30DE6-84DA-45B2-A621-31DAF0CBB63E}] "Name"="LyncOutlookContactShare" "Path"="C:\\Development\\LyncOutlookContactShare\\LyncOutlookContactShare\\bin\\Debug\\LyncOutlookContactShare.exe" "Parameters"="%AppData%" "DefaultContextPackage"=dword:00000000
The GUID should be the same value as the appId variable you’ve declared earlier. The Name value must be the same as what you’ve declared in the code and make sure you point the Path value to your application’s executable in the bin\Debug folder.
Save the file and open the project folder in Windows Explorer and double-click the registryEntry.reg file to add the values to your registry. You would need to do this for all the PCs you would like the application to run on.
When I run the application, I selected a contact from the list and clicked on the “Send Instant Message” button on my colleague Bob’s contact card. A Lync Conversation window opened and after I typed a message to Bob it will send the selected Outlook contact as part of the conversation context to Bob. Notice that the title of the conversation window changed to include the selected contact’s name.
Bob will see a similar window on his PC and as soon as he clicks on the contextual link in the conversation window will see the contact’s details in his application.
Bob can then click on the Create in Outlook button and the contact will be added to his Outlook Contacts.
Please see the attached project for a complete listing of all the code used in this post. I hope this has given you a clearer idea of what Lync contextual conversation is and how you can use it to provide your customers with a richer user experience.
Thank you for reading. Until next time, keep coding.