What’s in This Chapter?
In this chapter, you learn how to build solutions for Lync Online in Office 365. Using the Lync 2010 SDK, you see how to integrate presence and click-to-communicate functionality into WPF and Silverlight applications, and also in Silverlight Web Parts in SharePoint Online. You also learn how to use the Lync 2010 Managed API to interact with conversations and program against the Lync object model. Finally, you build extensibility applications that run inside a Lync conversation window.
Lync Online provides a cloud-hosted instant messaging, presence, and peer-to-peer voice solution. Users can connect to Lync Online using the Lync 2010 client for Windows or Mac.
In this section, you learn about the different types of solutions that you can build for Lync Online, and how they differ from the solutions that you can build for Lync on-premises. You also learn about the tools for developing solutions for Lync Online—specifically the Microsoft Lync 2010 SDK, which includes the Lync Controls for WPF and Silverlight, and the Lync 2010 API.
Microsoft Lync Server 2010 is an enterprise presence, instant messaging, online meeting, and voice solution. When taking full advantage of the voice features available in Lync, a company can use it to completely replace its phone system, allowing people to use their computers and other Lync-supported phone devices to make and receive calls.
From a functionality point of view, Lync Online includes only a subset of the functionality available in Lync on-premises—this includes presence, instant messaging, online meetings, and peer-to-peer voice. Peer-to-peer voice is only a subset of the full voice capabilities of Microsoft Lync Server 2010. In an on-premises deployment, you can use Lync to dial any phone number, for example +1 (425) 555-1212, and also to place a peer-to-peer Lync call to somebody else who runs the Lync client. In Lync Online, you can make peer-to-peer Lync calls only to other people in your organization (or organizations that yours is federated with).
From a development point of view, Lync solutions are typically divided into client-side and server-side solutions. In a client-side solution, code runs in a client application such as a custom WPF application, a Silverlight Web Part in SharePoint, or directly in a Lync conversation window. Client-side solutions reuse the connection that the Lync client has with the underlying Lync Server infrastructure—you are not responsible for programming the connectivity of these applications back to the Lync server.
In server-side solutions, the application code runs directly on the Lync server. Examples of server-side solutions include call centers and Interactive Voice Response (IVR) solutions. In a Lync-based call center, callers are greeted, put through an IVR to gather some information such as the purpose of their call, possibly placed on hold, and finally connected with an available customer service agent with the appropriate skills to assist them. The call center software can include functionality that enables supervisors in the call center to monitor these calls and provide coaching to agents when necessary. To build such applications, developers use the Unified Communications Managed API 3.0 (UCMA), which is a server-side API that interacts closely with the underlying Lync Server infrastructure. UCMA-based applications are not supported in Lync Online.
Other SDKs such as the Lync Server 2010 SDK allow you to interact directly with the Lync Server—these SDKs are not supported in Lync Online.
A good rule of thumb is that, in Lync Online, you can build only client-side applications. Lync Online is a multitenant environment, so applications that interact directly with the Lync Server infrastructure are not supported. In the next section, you learn about building client-side solutions for Lync Online using the Lync 2010 SDK.
The Lync 2010 SDK includes the Lync controls and the Lync API. The Lync controls enable you to easily integrate presence and click-to-communicate functionality into Silverlight and WPF applications. The Lync API enables you to program directly against the Lync object model, which means you can programmatically interact with the user’s running instance of the Lync client.
In this section, you learn how to set up your development environment to work with the Lync SDK. You also learn about the different type of client-side Lync solutions that you can build using the Lync controls and Lync API. Before you install the Microsoft Lync 2010 SDK, take a moment to ensure that you have the right prerequisites installed and configured in your development environment.
The user’s machine must have the Lync client installed and running to use the Lync controls and Lync API in your applications. Lync acts as an endpoint that provides a communication channel back to the Microsoft Lync Server 2010 infrastructure. You can use the Lync API to programmatically sign the user into Lync; however, the Lync controls appear grayed out if the user is not signed in.
Visual Studio 2008 SP1 and Visual Studio 2010 are supported for developing applications with the WPF Lync controls. You can use the WPF controls in both C# and Visual Basic .NET applications targeting either .NET Framework 3.5 SP1 or .NET Framework 4. The Silverlight Lync controls are supported only in Visual Studio 2010 and Silverlight 4. You can use the Silverlight controls in both C# and Visual Basic .NET applications targeting .NET Framework 4.
Visual Studio 2008 SP1 and Visual Studio 2010 are supported for developing applications with the Lync API. You can use the Lync API in .NET applications targeting either .NET Framework 3.5 SP1 or .NET Framework 4. The Lync API for Silverlight is supported only in Visual Studio 2010 and Silverlight 4. You can use the Lync API in Silverlight applications targeting .NET Framework 4.
The Lync controls are supported only in Silverlight 4. Be sure to install the Silverlight 4 Tools for Visual Studio before beginning development. If the appropriate Silverlight tools are not installed in your development environment, you cannot use the Visual Studio Silverlight project templates available with the Lync SDK.
When building Silverlight applications using the Lync SDK—leveraging either the Lync controls or Lync API—be sure to add the website that hosts the Silverlight application to the user’s Trusted Sites collection in the security settings in Internet Explorer. Because of this requirement, the Lync SDK is not supported in Silverlight applications running out of browser.
In a default installation, the Lync SDK is installed at C:Program Files (x86)Microsoft LyncSDK. The installer deploys the necessary assemblies for Silverlight and WPF, some sample applications, and Visual Studio project templates.
The Microsoft Lync 2010 SDK installation directory contains an Assemblies folder where you can find assemblies compiled for Silverlight and WPF. If you do not use the Visual Studio project templates available with the SDK, you should reference the assemblies from this location.
A good practice is to include the necessary assemblies in a lib folder in your Visual Studio solution and reference them directly from there. This is particularly useful if you use Microsoft Team Foundation Server — or any other build automation software — to perform automated builds of your application, because you don’t need to install the Microsoft Lync 2010 SDK directly on the build server.
Now that you have installed the Lync SDK and configured your development environment for Lync development, it’s time to build your first application for Lync Online.
This section introduces you to the types of applications that you can build for Lync Online, which include the following:
In this section, you learn how to build these types of applications for Lync Online. Learning how to build each of these types of applications warrants its own chapter; each section covers the basics.
The Lync controls enable you to replicate functionality found in the Lync client using little to no code. Controls are available to show the presence of contacts, group them into lists, and search for contacts and display the results. Other controls allow you to easily start instant message and audio or video applications directly from your WPF and Silverlight applications.
The Lync controls are easy to integrate into your applications; in this section, you walk through building a simple Silverlight application that displays the current user’s presence and contact list. After building the Silverlight application, you create a SharePoint solution and integrate the Lync controls Silverlight application into a SharePoint Silverlight Web Part. Finally, you upload the SharePoint solution to SharePoint Online to see the Lync controls working in SharePoint Online and Lync Online.
The first step is to create a Silverlight project that uses the Lync controls. After installing the Lync SDK, you can see some new project templates in Visual Studio, as shown in Figure 7-1. The Lync WPF Application and Lync Silverlight Application project templates take care of adding the appropriate Lync SDK assembly references and get you started building Lync applications.
Choose the option for Visual Studio 2010 to create an ASP.NET Web Application to host your application; this is useful for testing before you integrate the Silverlight application into a SharePoint solution.
As you can see in Figure 7-2, the necessary assembly references for the Lync SDK were created by the Lync Silverlight Application project template in Visual Studio.
These assembly references include the following:
The project template also creates a default XAML page, defines the appropriate XAML namespaces for the Lync controls, and places a sample control on the page. The controls XAML prefix is used to integrate the Lync controls in the XAML on the page in the Silverlight application.
<UserControl x:Class="LyncContactList.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">
code snippet LyncControlsLyncContactListPage.xaml
Finally, the project template adds a PresenceIndicator control to the page to demonstrate how to use the Lync controls in XAML. To run the project, first change the Source property of the PresenceIndicator control to your Lync Online address; for example, sip:[email protected]. Run the project; you see the PresenceIndicator control showing the signed-in user’s current presence, as shown in Figure 7-3.
Now that you have a simple Silverlight application that uses the Lync controls, you can add some additional controls to the application and explore their functionality.
<Grid x:Name="LayoutRoot" HorizontalAlignment="Left"> <StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top"> <controls:MyStatusArea /> <controls:ContactList ShowFrequentContacts="False" ShowFriendlyName="True" GroupViewBySetting="Status" ContactLayoutView="TwoLines"/> </StackPanel> </Grid>
code snippet LyncControlsLyncContactListPage.xaml
Now that you have a simple working Silverlight application that uses the Lync controls, create a SharePoint solution that integrates your Lync controls Silverlight application into a SharePoint Silverlight Web Part.
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Module Name="Silverlight" Url="SLXAPs"> <File Path="LyncContactList.xap" Url="LyncContactList.xap" /> </Module> </Elements>
code snippet LyncControlsLyncContactList.WebPartSilverlightElements.xml
If you deploy the SharePoint project as-is to your on-premises SharePoint 2010 development environment, you can download LyncContactList.xap at http://yoursite/SLXAPs/LyncContactList.xap.
You can manually upload the Silverlight application XAP into a SharePoint Document Library, create a page, and add a Silverlight Web Part to it. However, it’s more fun to automate this as part of your solution. In this section, you create a site page that automatically provisions a Silverlight Web Part containing the Lync controls Silverlight application.
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Module Name="CustomPages" Url="SitePages"> <File Url="LyncContactList.aspx" Path="CustomPages/LyncContactList.aspx" Type="Ghostable" /> </Module> </Elements>
Of particular interest is the AllUsersWebPart item under the File element. This syntax provisions a web part of the specified type—a Silverlight Web Part—into the specified web part zone. The Url property of the web part points to the XAP file at ~site/SLXAPs/LyncContactList.xap.
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Module Name="CustomPages" Url="SitePages"> <File Url="LyncContactList.aspx" Path="CustomPages/LyncContactList.aspx" Type="Ghostable"> <AllUsersWebPart WebPartOrder="1" WebPartZoneID="Left" ID="LyncContactListSLWP"> <![CDATA[ <webParts> <webPart xmlns="http://schemas.microsoft.com/WebPart/v3"> <metaData> <type name=" Microsoft.SharePoint.WebPartPages.SilverlightWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <importErrorMessage> Cannot import this Web Part. </importErrorMessage> </metaData> <data> <properties> <property name="HelpUrl" type="string" /> <property name="AllowClose" type="bool">True</property> <property name="ExportMode" type="exportmode">All</property> <property name="Hidden" type="bool">False</property> <property name="AllowEdit" type="bool">True</property> <property name="Direction" type="direction">NotSet</property> <property name="TitleIconImageUrl" type="string" /> <property name="AllowConnect" type="bool">True</property> <property name="HelpMode" type="helpmode">Modal</property> <property name="CustomProperties" type="string" null="true" /> <property name="AllowHide" type="bool">True</property> <property name="Description" type="string"> A web part to display a Silverlight application. </property> <property name="CatalogIconImageUrl" type="string" /> <property name="MinRuntimeVersion" type="string" null="true" /> <property name="ApplicationXml" type="string" /> <property name="AllowMinimize" type="bool">True</property> <property name="AllowZoneChange" type="bool">True</property> <property name="CustomInitParameters" type="string" null="true" /> <property name="Height" type="unit">400px</property> <property name="ChromeType" type="chrometype">Default</property> <property name="Width" type="unit">350px</property> <property name="Title" type="string">Lync Contact List</property> <property name="ChromeState" type="chromestate">Normal</property> <property name="TitleUrl" type="string" /> <property name="Url" type="string"> ~site/SLXAPs/LyncContactList.xap </property> <property name="WindowlessMode" type="bool">True</property> </properties> </data> </webPart> </webParts> ]]> </AllUsersWebPart> </File> </Module> </Elements>
code snippet LyncControlsLyncContactList.WebPartCustomPagesElements.xml
After testing the SharePoint solution in your SharePoint 2010 on-premises SharePoint deployment, package it and upload it to the Solution Gallery of your SharePoint Online site. Browse to the site’s feature management screen, and activate the Lync Contact List Web Part feature, as shown in Figure 7-8.
Browse to https://yoursite.sharepoint.com/SitePages/LyncContactList.aspx. You can see that the LyncContactList.aspx was provisioned into the Site Pages library as specified by the SharePoint solution. The Lync Contact List Silverlight application was also automatically provisioned into a Silverlight Web Part on the page, as shown in Figure 7-9.
The Lync 2010 Managed API (Lync API) is part of the Lync SDK; it provides functionality for developers to interact with and automate the running instance of the Lync client. Like the Lync controls, any code that uses the Lync API requires that the Lync client is installed and running, because it reuses the connection that the Lync client has with the underlying Lync Server infrastructure.
The Lync API provides an easy-to-use, managed API that you can work with in your WPF, Windows Forms, and Silverlight applications. Using the Lync API, you can programmatically sign in to Lync, subscribe to and handle presence events for contacts and groups, and start conversations in different modalities.
In this section, you learn how to use the Lync API to sign in to the running instance of the Lync client. You also learn how to easily start conversations from your application.
Because the Lync API relies on the Lync client running on the user’s machine, your application should check if the Lync client is running and programmatically sign the user in if he or she isn’t signed in already. The status of the Lync client can change; for example, the user may sign out of Lync—your application should gracefully react to these state changes.
The LyncClient class in the Microsoft.Lync.Model namespace is what you use to interact with the Lync client. Create a module-level variable of this type.
private Microsoft.Lync.Model.LyncClient _lyncClient;
code snippet LyncEventsLoggerWindow1.xaml.cs
When your application starts, call the static GetClient method of the LyncClient class to get a handle to the Lync client. Wrap this code in a try/catch block; the method call throws an exception if the Lync client is not running.
try { _lyncClient = Microsoft.Lync.Model.LyncClient.GetClient(); } catch { MessageBox.Show( "Microsoft Lync is not running.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); Close(); }
code snippet LyncEventsLoggerWindow1.xaml.cs
Now that you have a handle to the running instance of the Lync client, you can programmatically sign the user in. However, you should first check if the user is already signed in—do this by checking the State property of the LyncClient object. The State property is an enum called ClientState that has the following values:
To sign the user in, call the BeginSignIn method of the LyncClient class. The first three parameters of the BeginSignIn method are the user’s URI, domain name, username, and password. Leaving these as null signs the current user in using the credentials with which he or she logged into Windows.
The BeginSignIn method is asynchronous; you need to define an asynchronous callback function that executes when the operation completes. You can also use a lamba expression and handle the asynchronous callback directly within the method call.
if (_lyncClient.State != ClientState.SignedIn) { _lyncClient.BeginSignIn( null, null, null, result => { if (result.IsCompleted) { _lyncClient.EndSignIn(result); // Setup application logic here } else { // Count not sign in to Lync } }, "Local user signing in" as object); }
code snippet LyncEventsLoggerWindow1.xaml.cs
The asynchronous callback in the lamba expression checks to see if the operation has completed and then calls EndSignIn to complete the sign in process. Because the user may sign in and out of Lync while your application is running, this is a good place to set up some application-specific logic that the application should execute when the user signs in to Lync.
Now that your application has signed the current user in to Lync, it also needs to monitor the state of the Lync client and react accordingly. In the next section, you learn how to monitor changes in the state of the Lync client.
If your application includes functionality that depends on the state of the Lync client, it needs to monitor it and enable/disable features as necessary. For example, users shouldn’t be able to start a conversation from the application if they are not signed in to Lync.
Use the StateChanged event of the LyncClient class to subscribe to events that fire when the status of the Lync client changes.
lyncClient.StateChanged += new EventHandler<ClientStateChangedEventArgs> (LyncClient_StateChanged);
code snippet LyncEventsLoggerWindow1.xaml.cs
The instance of ClientStateChangedEventArgs in the StateChanged event handler exposes OldState and NewState properties that tell you about the previous and current state of the Lync client. Your application can perform specific logic based on the state of the Lync client; for example, clean up any Lync API resources if the user is signing out.
void LyncClient_StateChanged (object sender, ClientStateChangedEventArgs e) { switch (e.NewState) { case ClientState.SigningOut: Cleanup(); break; }; }
code snippet LyncEventsLoggerWindow1.xaml.cs
Automation, a feature of the Lync API, enables you to quickly and easily start conversations in different modalities such as an instant message or video call. Automation automates the running instance of the Lync client, hence the name.
In this section, you learn how to handle Automation, how to start instant message and video calls, and how to get a handle to the conversation after starting it.
The Automation functionality is exposed by the Microsoft.Lync.Model.Extensibility.Automation class. Create a module level variable of this type so you can leverage the functionality throughout your application.
To initialize Automation in your application, call LyncClient.GetAutomation().
_automation = LyncClient.GetAutomation();
code snippet LyncEventsLoggerWindow1.xaml.cs
You can now use your _automation module-level variable to start conversations throughout your application.
Starting conversations using Lync Automation follows a simple pattern:
To start a conversation using Automation, call Automation.BeginStartConversation and specify the conversation modality, participants, and any context data to embed into the conversation. You also need to specify a callback function that can run when the asynchronous operation completes.
var contextData = new Dictionary<AutomationModalitySettings, object>(); contextData.Add( AutomationModalitySettings.FirstInstantMessage, imText.Text); contextData.Add( AutomationModalitySettings.SendFirstInstantMessageImmediately, true); _automation.BeginStartConversation( AutomationModalities.InstantMessage, myContactList.SelectedContactUris, contextData, StartConversationCallback, _automation);
code snippet LyncEventsLoggerWindow1.xaml.cs
You don’t need to specify any context to start an instant message conversation; however, it can be useful to accomplish something such as automatically embedding the first instant message to send. To do so, follow these steps:
When the conversation starts, you can see in Figure 7-10 how the first instant message is immediately sent to all the participants in the conversation.
You don’t need to set any specific AutomationModalitySettings to start a simple audio or video conversation; you can simply pass null to the contextData parameter of the BeginStartConversation function.
_automation.BeginStartConversation( AutomationModalities.Video, myContactList.SelectedContactUris, null, StartConversationCallback, _automation);
code snippet LyncEventsLoggerWindow1.xaml.cs
You may have noticed _automation being passed as the last parameter of the BeginStartConversation method. This parameter represents the asynchronous state of the operation; you can reference it in the start conversation callback to get a handle to the conversation window (and conversation) started as a result of the method call.
void StartConversationCallback(IAsyncResult ar) { ConversationWindow conversationWindow = null; if (ar.IsCompleted) { conversationWindow = ((Automation)ar.AsyncState).EndStartConversation(ar); var conversation = conversationWindow.Conversation; // do something with the conversation } }
code snippet LyncEventsLoggerWindow1.xaml.cs
After you get a handle to the conversation window, you can dock it into your WPF or Windows Forms application. You can also access the underlying conversation using the Conversation property of the conversation window, allowing you to subscribe to events on the conversation.
A Lync extensibility application is an application that runs directly in the Lync conversation window. An example of a Lync extensibility application is a conversation translator application that translates instant message text from one language to another before injecting it into the conversation flow. In a Lync-based call center where agents field calls using Lync, an extensibility application can perform a reverse-lookup on customers and load their customer profile data from CRM into the Lync conversation window. Injecting the context of the conversation into an extensibility application running in the Lync conversation window can reduce unnecessary switching between applications because the participants already have all the data they need in the Lync conversation window.
In this section you learn how to build a Silverlight application that runs in the Lync extensibility application. The companion code to this section includes a WPF application shown in Figure 7-11 that allows you to browse a list of Fabrikam’s customers and sales information and start a conversation with the account manager for a particular account. When the account manager picks up the incoming conversation, a Silverlight version of the application opens directly in the Lync conversation window and displays a chart of the account’s recent sales.
A Lync extensibility application is a type of contextual application in that it contains data related to the context of the conversation—in the case of the Fabrikam CRM application, the selected account.
To start an extensibility application and pass it the necessary context data, you need to:
A contextual application package is a Windows Registry file that contains the information necessary to run the Lync extensibility application. To run the Lync extensibility application, a user must run the Windows Registry file on their machine. This registers the application with the Lync Server infrastructure, allowing Lync to run the extensibility window in the user’s Lync conversation window.
Running a Windows Registry file to register a contextual application package with Lync Server is referred to as Install Registration. There are other techniques to register contextual application packages; however, this section focuses on Install Registration.
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USERSoftwareMicrosoftCommunicatorContextPackages] [HKEY_CURRENT_USERSoftwareMicrosoftCommunicatorContextPackages {6B7BACE8-3968-4A1E-9BB5-F4BD666E36FB}] "Name"="Fabrikam CRM" "Parameters"="%AppData%" "InternalURL"="http://crm.fabrikam.com/Default.aspx" "ExternalURL"="https://crm.fabrikam.com/Default.aspx" "ExtensibilityWindowSize"=dword:00000000
code snippet LyncExtensibilityApplicationFabrikam.CRM.WPFPackageRegistration_FabrikamCRM.reg
The contextual application package includes the following elements:
Now that you have registered the contextual application package, you can attach context to the Lync controls to start contextual conversations.
After running the Windows Registry file to register the contextual application package with the Lync Server infrastructure, your application can start a contextual conversation that launches the extensibility application in the Lync conversation window. A contextual conversation is a Lync conversation that has application context attached to it; in this section you learn how to attach context to a conversation so that the recipient can process it.
To specify the context to attach to a conversation, follow these steps:
// Create application context var context = new ConversationContextualInfo(); context.Subject = account.AccountName; context.ApplicationId = _applicationGuid; context.ApplicationData = String.Concat("AccountId:", account.Id.ToString()); // Attach context accountManager.ContextualInformation = context;
code snippet LyncExtensibilityApplicationFabrikam.CRM.WPFMainWindow.xaml.xs
After you set the ContextualInformation property of the ContactCard Lync control to the instance of ConversationContextualInfo, any conversation you start from the ContactCard control includes the context. When the account manager receives the conversation, the Silverlight extensibility application is automatically loaded into the Lync conversation window.
A Silverlight extensibility application running in the Lync conversation window can access the conversation it is hosted in and extract any data that was passed in with the conversation. When an account manager receives a conversation initiated from the Fabrikam CRM application, you can retrieve the account ID from the context provided in the conversation and use that to load the sales data for the account.
Conversation conversation = null; conversation = LyncClient.GetHostingConversation() as Conversation; if (conversation != null) { _appData = conversation.GetApplicationData(_applicationGuid); this.Dispatcher.BeginInvoke( new Action(() => { int accountId = Convert.ToInt32(_appData.Split(new char[] { ':' })[1]); Account account = _accounts.Where(a => a.Id == accountId).First(); this.accountName.Text = account.AccountName; ((BarSeries)accountSalesChart.Series[0]).ItemsSource = account.GetSalesByYear(DateTime.Now.Year); })); }
code snippet LyncExtensibilityApplicationFabrikam.CRM.SilverlightPage.xaml.xs
You can call LyncClient.GetHostingConversation to access the conversation that the Silverlight extensibility application runs in. If the returned value is not null, you can confirm that the Silverlight extensibility application is actually running in the Lync conversation window.
You can then extract the application data from the conversation by calling Conversation.GetApplicationData and providing the GUID of the contextual application. Finally, you can use the application data to take the appropriate action in the Silverlight extensibility application; for example, to display a chart of the account’s sales as shown in Figure 7-12.
When developing communications solutions for Lync Online, you are limited to developing client-side applications using the Lync SDK. You can integrate the Lync controls into Silverlight Web Parts that run in SharePoint Online, build applications that interact with the running instance of the Lync client via the Lync API, and build extensibility applications that run in the Lync conversation window.
In the next chapter, you start learning about Windows Azure—Microsoft’s foray into cloud computing.