Overview

With Windows Phone 7 becoming more pervasive, one of the key questions facing enterprise developers is how can we create applications that integrate SharePoint and Windows Phone 7. You may have seen an earlier post by Paul Stubbs that talks through some of the issues and shows how you can accomplish this.

In this post, I wanted to walk you through another way in which you can integrate Windows Phone 7 with SharePoint. To do this, I’ll leverage the SharePoint and Windows Azure developer primer we recently released and make a couple of adjustments to the code to support integration of SharePoint and Windows Phone 7. (Thanks to Todd and Ravi who worked on this dev primer for us…some great stuff here!)

Getting the Basics in Place

To work through this blog, you’ll need your development environment set up for SharePoint, Windows Azure and Windows Phone 7. This means having SharePoint, a Windows Azure account, Windows Phone 7 tools, and Visual Studio 2010 set up and ready to go. In my environment, I have two machines:

  • The server, which is a Windows Server 2008 R2 set up with VS 2010, SP Server (natively installed), Windows Azure tools and SDK, and SQL Server 2008 R2 as the core components.
  • The client, which is a Windows 7 box with Windows Phone 7 tools and emulator installed on it along with VS 2010—the free dev express version.

You’ve also need a Windows Azure account, but if you haven’t got one set up yet you can go here to get a trial account and get up and running: http://www.microsoft.com/windowsazure/free-trial/sharepoint-integration/.

In the SharePoint and Windows Azure developer primer reference above, you’ll note in Module 4 an exercise that walks you through how to create an on-premises service that can be called by a WCF service deployed to Windows Azure. These two services communicate via the Windows Azure AppFabric Service Bus. (You can get an overview of Windows Azure AppFabric here.) Once you’ve deployed the WCF service to Windows Azure, you can use that service to communicate with the on-premises service via different devices or applications. For example, if you look at the follow high-level diagram, note that the on-premises service (GetEmployees) is a worker or listener service that waits to be called by the WCF service deployed to Windows Azure AppFabric—the ‘service bus.’ This provides a direct service-to-service connection which is authenticated using your service bus credentials or using Windows Azure Access Control Service (ACS). The GetEmployees service then pulls information from SharePoint and then exposes that to the WCF service in the cloud—and subsequently any application or device that is consuming that service. You now have SharePoint not only interacting cross-device, but also cross-platform—so you can now access SharePoint on-premises using the service bus and do it from any application, device or programming language that is conversant with WCF services.

clip_image002

High-level architecture of Windows Phone 7 accessing SharePoint via Windows Azure AppFabric

After You’ve Deployed the WCF Service to Windows Azure, What Now?

After you’ve walked through the module from the developer primer and deployed the WCF service that talks to the on-premises service, you’re now ready to use the Windows Azure-deployed service for your Windows Phone 7 application. So, let’s get into how this is done.

The first thing you need to do, then, is create a list in your SharePoint site; this will contain the data that you’ll pull from SharePoint and expose in your Windows Phone 7 device.

clip_image004

Employees list in SharePoint

Next, open up Module 4 in the SharePoint and Windows Azure dev primer and go back to the code you created in Lab 2. In the lab, you worked through how to do most of what you need to accomplish getting the service into Windows Azure and then communicating across the service bus namespace you set up. In the lab, though, it shows you how to create a Silverlight application to integrate with the Windows Azure service. While this is interesting (because you can use the Silverlight application both on-premises and in SharePoint Online), you don’t need this client application here. What you need to do is open the EmployeeInfoSvc.cs file and then amend as per the following code snippet. The bolded code, replacing the commented-out code, enables you to read the Employees list in SharePoint using the server object model. It will then return the data from the SharePoint list using the same data structures that were created for the services so the integrity of your serialization remains intact.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using Shared;

using System.Xml.Serialization;

using System.IO;

using Microsoft.SharePoint;

namespace EmployeeInfoService

{

public class EmployeeInfoSvc : IEmployeeInfoSvc

    {

List<Employee> IEmployeeInfoSvc.GetEmployees()

        {

   List<Employee> myReturnEmployees = new List<Employee>();

   Console.WriteLine("GetEmployees was called.");

   //XmlSerializer xs = new XmlSerializer(typeof(List<Employee>));

   //object employeeList = null;

   //using (FileStream fs = new FileStream("EmployeeList.xml", FileMode.Open))

   //{

   //    employeeList = xs.Deserialize(fs);

   //}

   //return (List<Employee>)employeeList;

   using (SPSite mySite = new SPSite("http://blueyonderdemo"))

              {

       using (SPWeb myWeb = mySite.OpenWeb())

                {

         SPList oList = myWeb.Lists["Employees"];

         SPQuery camlQuery = new SPQuery();

                 camlQuery.ViewXml = "<View/>";

         SPListItemCollection collListItems = oList.GetItems(camlQuery);

         foreach (SPListItem listItem in collListItems)

                    {

                Employee tempEmployee = new Employee();

                        tempEmployee.FirstName = listItem["Title"].ToString();

                        tempEmployee.LastName = listItem["Last Name"].ToString();

                        tempEmployee.Salary = double.Parse(listItem["Salary"].ToString());

                        myReturnEmployees.Add(tempEmployee);

                    }

                }

            }

         return myReturnEmployees;

        }

    }

}

Creating the Windows Phone 7 Client Application

Now you can put this aside for the moment and jump into the Windows Phone 7 tools. Go ahead and open the tools and create a new project called SharePointEmployeeApp—as per the below figure.

clip_image006

New Windows Phone 7 application

The Windows Phone 7 application will be straightforward to create. First, you’ll create the UI, second you’ll add a service reference to the Windows Azure-deployed WCF service and third you’ll create the code-behind that handles the return package from the WCF service call (i.e. the SharePoint data).

The following code is the UI code. Note that I’ve defined a data template that I then use to bind the employee data coming back from the SharePoint on-premises site. The main UI controls are a button and listbox, which uses the data template to data-bind to three textblock controls within the listbox control.

<phone:PhoneApplicationPage

x:Class="SharePointEmployeesApp.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

FontFamily="{StaticResource PhoneFontFamilyNormal}"

FontSize="{StaticResource PhoneFontSizeNormal}"

Foreground="{StaticResource PhoneForegroundBrush}"

SupportedOrientations="Portrait" Orientation="Portrait"

mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"

shell:SystemTray.IsVisible="True">

<phone:PhoneApplicationPage.Resources>

<DataTemplate x:Key="EmployeeData">

<Grid Width="360">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="90"></ColumnDefinition>

<ColumnDefinition Width="140"></ColumnDefinition>

<ColumnDefinition Width="100"></ColumnDefinition>

</Grid.ColumnDefinitions>

<TextBlock Text="{Binding FirstName}" FontSize="24" Grid.Column="0" Height="50"/>

<TextBlock Text="{Binding LastName}" FontSize="24" Grid.Column="1" Height="50"/>

<TextBlock Text="{Binding Salary}" FontSize="24" Grid.Column="2" Height="50"/>

</Grid>

</DataTemplate>

</phone:PhoneApplicationPage.Resources>

<!--LayoutRoot contains the root grid where all other page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

<TextBlock x:Name="ApplicationTitle" Text="Employee Information" Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="employees" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentGrid" Grid.Row="1">

<Button Content="Get Employees" Height="72" HorizontalAlignment="Left" Margin="123,512,0,0" Name="btnGetEmployees"

VerticalAlignment="Top" Width="226" Click="btnGetEmployees_Click" />

<ListBox Height="462" HorizontalAlignment="Left"

Margin="11,32,0,0" Name="lstbxEmployees" VerticalAlignment="Top" Width="460"

ItemsSource="{Binding}"

ItemTemplate="{StaticResource EmployeeData}">

</ListBox>

</Grid>

</Grid>

</phone:PhoneApplicationPage>

To add the service, you need to have your WCF service endpoint URI to which you’ve deployed to Windows Azure, e.g. http://yourazurenamespace.cloudapp.net/CloudToOnPremForwarder.svc. Adding the service is trivial: right-click the project, select Add Service Reference, add the service URI in the Address field, and click Go. Then provide a namespace for your service (e.g. AzureServiceProxy).

The final step is to implement the service in your code behind and retrieve the data from SharePoint and surface it in the Windows Phone 7 application. To do this, you’ll need to add a class to the project (right-click the project, select Add and then select Class). The class should be called Employee, and the class properties should be set as follows:

using System;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Ink;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

namespace SharePointEmployeesApp

{

  public class Employee

   {

public string FirstName { get; set; }

public string LastName { get; set; }

public string Salary { get; set; }

   }

}

The MainPage.xaml.cs code behind then would look something like the following. The listofEmployees is a list collection that you populate with the return data from the service call which you then bind to the textblocks in the listbox using the DataContext property.

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.Phone.Controls;

using SharePointEmployeesApp.AzureServiceProxy;

namespace SharePointEmployeesApp

{

    public partial class MainPage : PhoneApplicationPage

    {

List<Employee> listOfEmployees = new List<Employee>();

public MainPage()

{

  InitializeComponent();

}

private void btnGetEmployees_Click(object sender, RoutedEventArgs e)

{

  CloudToOnPremForwarderClient client = new CloudToOnPremForwarderClient();

  client.GetEmployeesCompleted += new EventHandler<GetEmployeesCompletedEventArgs>(client_GetEmployeesCompleted);

  client.GetEmployeesAsync();

}

void client_GetEmployeesCompleted(object sender, GetEmployeesCompletedEventArgs e)

{

if (e.Error == null)

{

  var returnEmployeeData = e.Result;

  foreach (var item in returnEmployeeData)

  {

    Employee tempEmployee = new Employee();

    tempEmployee.FirstName = item.FirstName.ToString();

    tempEmployee.LastName = item.LastName.ToString();

    tempEmployee.Salary = item.Salary.ToString();

    listOfEmployees.Add(tempEmployee);

  }

  lstbxEmployees.DataContext = listOfEmployees;

}

else

{

   MessageBox.Show(e.Error.ToString());

}

   }

}

}

With the above complete, you can now access SharePoint data via the Windows Azure AppFabric service bus—using a WCF service deployed to Windows Azure. The optimal part of this is that this WCF service can be leveraged by multiple applications.

To get all of this working, you would do the following:

  1. On your server machine, right-click the amended EmployeeInfoService on-premises service and select Debug and Start New Instance. The service will connect to your service bus namespace and then be waiting for applications to call into it.
  2. On your client machine, F5 your Windows Phone 7 application. When the emulator loads, you can then click the Get Employees button. This will in turn call the WCF forwarder service that you deployed to Windows Azure that will connect to the on-premises service via the service bus.

After you do these two things, you should then see something similar to the following:

clip_image008

SharePoint Data in Windows Phone 7

You can download the code for the Windows Phone 7 app here.

Closing Thoughts

Some other thoughts and notes.

  1. I’ve chosen the path of least resistance to get an integrated solution between SharePoint and Windows Phone 7 working. The pattern works with the caveat that you may want to wrap a security layer around the service call. This can be done using ACS and claims-based authentication. There are some great exercises you can work through in the Windows Azure Developer Training Kit, which you’ll find here.
  2. You can also improve the serialization and presentation of data through adjusting the class data types in the lab exercise. For example, just having numbers is probably not an optimal way to display salary; you’d want to have it properly formatted.
  3. Ensure you adjust your DiagnosticConnections property in the Windows Azure service file. Often times, you’ll find a configuration error when deploying to Windows Azure. This is typically because you’ve got local development set to true. To get the service working properly in Windows Azure, you need to make sure you’ve got your storage account set up properly. David Aiken has a blog post providing some details on this here.
  4. Also, test out the deployed WCF service with other web apps and devices. Remember that once you get through the exercises in the lab, you know have a way to integrate with SharePoint on-premises through many different means—any WCF conversant app/language/device can implement this code. The possibilities in this sense make this pattern broadly accessible.
  5. Lastly, test out read and write operations against your SharePoint server. Remember that the code you insert inside of the service is what is called and executed. You’ll have to ensure your service contracts and operations map, but you can have read and write from a Windows Phone 7 application to update your SharePoint on-premises data.

Well, happy coding.

Steve