March 2011

Volume 26 Number 03

SharePoint Online - Cloud-Based Collaboration with SharePoint Online

By Chris Mayo | March 2011

With the release of Office 365, Microsoft will present the next version of Microsoft Online Services, a cloud-based collaboration and communication service based on SharePoint 2010, Exchange 2010 and Lync Server 2010. Office 365, currently in beta, will provide SharePoint, Exchange and Lync as a subscription-based Software as a Service (SaaS) offering, hosted in cloud datacenters managed by Microsoft.

SharePoint Online—the cloud-based version of SharePoint 2010—will provide users with many of the same features of SharePoint 2010, but without the need to manage the hardware or software required for a scalable and secure collaboration solution. In this article, I’ll provide an overview of how SharePoint Online development is similar to and different from SharePoint 2010 development by building solutions that run in SharePoint Online.

With the next release of SharePoint Online, SharePoint developers will be able to develop collaboration solutions using the same skills and tools they use in developing for SharePoint 2010, including Visual Studio 2010, SharePoint Designer 2010, C# or Visual Basic and the SharePoint APIs and SDKs. There are many similarities between developing for SharePoint on-premises and in the cloud, but there are also significant differences that will impact how you build solutions.

Understanding these differences will help you understand what solutions can be created to run in SharePoint Online and how to develop those solutions.

SharePoint Online Customization Similarities

In SharePoint 2010 development, you have the ability to customize SharePoint using the browser and SharePoint Designer 2010 and by building solutions using Visual Studio 2010. With SharePoint Online, customization with the browser and SharePoint Designer 2010 is largely the same as SharePoint 2010 (given the feature differences mentioned in the next section). Developing SharePoint Online solutions using Visual Studio 2010 is also largely the same. Development is done in Visual Studio 2010 against a local instance of SharePoint 2010 (either running locally in Windows 7 or Windows Server 2008 R2 or in a virtual machine, or VM), leveraging the integrated debugging experience for iterative development. When development is complete, the solution is uploaded to SharePoint Online using the same Solution Gallery provided in SharePoint 2010.

SharePoint Online Customization Key Differences

Although SharePoint Online is based on SharePoint 2010, there are some key differences to keep in mind as you develop solutions that will run in the former. First, SharePoint Online only supports Site- and Web-scoped solutions. It runs in a multi-tenant cloud, where multiple tenancies run on a shared datacenter infrastructure, so it make sense that solutions with Farm scope (where a feature is activated for the entire farm) aren’t supported. Likewise, in SharePoint Online, the highest level of access to your SharePoint tenancy is at the site-collection level, so WebApplication-scoped features (where a feature runs in every Web site in a Web application) aren’t supported either.

Second, only partial-trust solutions are supported in SharePoint Online. Full-trust solutions, where your solution would have access beyond the site-collection level or could be granted permission to run with admin-level privileges on the farm, also aren’t supported.

Finally, although SharePoint Online is based on SharePoint 2010, it doesn’t have 100 percent feature parity with its on-premises counterpart. For a complete feature-by-feature comparison between SharePoint 2010 and SharePoint Online, refer to the Microsoft SharePoint Online Beta Service Description, available from the Office 365 Beta Service Descriptions page at bit.ly/bBckol.

The feature-by-feature list shows that a majority of SharePoint customization features are supported. The lack of support for Business Connectivity Services (BCS), External Lists and the ability to call Web services outside SharePoint Online (which isn’t supported in partial-trust solutions) will have a significant impact on building solutions that run in SharePoint Online. BCS support is planned for a future release, however.

With these similarities and differences in mind, let’s look at some examples of the types of solutions you can build to run in SharePoint Online, including sandboxed solutions and the SharePoint client object model (OM). Other solution types, such as automating business processes via declarative workflow solutions, will be covered in future articles.

Developing for SharePoint Online with Sandboxed Solutions

From the previous section, you know that SharePoint Online solutions must be scoped to site or Web features, are restricted to data in the site collection and must run in partial trust. Developing solutions that run as sandboxed solutions meet all these criteria while letting SharePoint Online administrators easily deploy a solution by uploading it directly to the Solution Gallery.

Visual Studio 2010 provides great support for sandboxed solutions, including project template and project item template support, the SharePoint Customization Wizard for creating new projects as sandboxed solutions, IntelliSense support for the site collection-scoped SharePoint APIs, and debugging and packaging support. To get started building a solution for SharePoint Online, you’ll develop and debug the solution locally against SharePoint 2010. You’ll need either Windows 7 64-bit or Windows Server 2008 R2 installed along with SharePoint 2010 and Visual Studio 2010. Another great way to get started is to use the 2010 Information Worker Demonstration and Evaluation Virtual Machine (RTM), which provides a virtualized SharePoint 2010 development environment. I also recommend the Visual Studio 2010 SharePoint Power Tools (bit.ly/azq882), which add compile-time support for the sandbox and a sandboxed Visual Web Part project item template.

In the examples in this article, I’ll build a solution using the simple scenario of providing the employees of the fictional Contoso Corp. with the ability to request purchases that aren’t supported in their procurement system. To get started, I’ll create a site collection and site in my on-premises SharePoint 2010 development environment. I’m using the VMs mentioned previously, so I’ve created http://o365dpe.contoso.com/sites/spomsdnmag/purchasing. My first solution will deploy the list used to track these non-standard purchases. I’ll open Visual Studio 2010, select File | New Project, and in the New Project dialog I’ll select Empty SharePoint Project and name the project PurchasingMgr.

In the SharePoint Customization Wizard dialog, for “What local site … ,” I’ll enter the URL of my site, http://o365dpe.contoso.com/sites/spomsdnmag/Purchasing/, select “Deploy as a sandboxed solution” and click Finish as seen in Figure 1.

image: Specify the Site and Trust Level for PurchasingMgr

Figure 1 Specify the Site and Trust Level for PurchasingMgr

Next, I’ll select the PurchasingMgr project in Solution Explorer, right-click and select Add | New Item. In the Add New Item dialog, I’ll select SharePoint 2010 in the Installed Templates node to the supported SharePoint item templates. Not all of these templates are supported under sandboxed solutions and therefore in SharePoint Online. Figure 2 shows the item templates supported under sandboxed solutions.

Figure 2 Item Templates Supported in Sandboxed Solutions

Item Template Sandbox Compatible? Notes
Visual Web Part No Requires ASCX file be installed on SharePoint Servers
Visual Web Part (Sandboxed) Yes Provided by installing the Visual Studio 2010 SharePoint Power Tools
Web Part Yes  
Sequential Workflow No Requires workflow solution be deployed as Farm Solution
State Machine Workflow No Requires workflow solution be deployed as Farm Solution
Business Data Connectivity Model No Requires BCS solution be deployed as a full-trust solution; feature not supported in SharePoint Online
Application Page No Requires ASPX page be deployed to SharePoint Server
Event Receiver Yes  
Module Yes  
Content Type Yes  
List Definition from Content Type Yes  
List Definition Yes  
List Instance Yes  
Empty Element Yes  
User Control No Requires ASCX file to be installed on SharePoint Servers

To build my list, I’ll define Site Columns and a Content Type for the list by selecting the Content Type item template and entering NonStandBusPurchaseRequestsCT for the name.

In the SharePoint Customization Wizard, I’ll select Item as the base content type and click Finish. The Content Type will have a Title column, a Description column and a Price column, which I’ll define declaratively by replacing the contents of the Elements.xml created with the XML in Figure 3.

Figure 3 NonStandBusPurchaseRequestsCT Definition via Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field SourceID="http://schemas.microsoft.com/sharepoint/v3"
    ID="{A74E67E5-8905-4280-90C9-DEBFFC30D43D}"
    Name="RequestDescription"
    DisplayName="Description"
    Group="Purchasing Manager Custom Columns"
    Type="Note"
    DisplaceOnUpgrade="TRUE" />
  <Field SourceID="http://schemas.microsoft.com/sharepoint/v3"
    ID="{CB5054F5-0C60-4DBE-94D2-CEFBFB793C7F}"
    Name="Price"
    DisplayName="Price"
    Group="Purchasing Manager Custom Columns"
    Type="Currency"
    DisplaceOnUpgrade="TRUE" />
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x010078a81c8413f54917856495e56e7c09ed"
    Name="Purchasing Manager - Non-Standard Business Purchase Requests Content Type"
    Group="Purchasing Manager Content Types"
    Description=
      "Non-Standard Business Purchase Requests Content Type 
       for the Purchasing Manager Solution"
    Inherits="TRUE"
    Version="0">
    <FieldRefs>
      <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title"    
        DisplayName="Title" />
      <FieldRef ID="{A74E67E5-8905-4280-90C9-DEBFFC30D43D}" 
        Name="RequestDescription"  
        Required="TRUE" />
      <FieldRef ID="{CB5054F5-0C60-4DBE-94D2-CEFBFB793C7F}" Name="Price" 
        Required="TRUE" />
    </FieldRefs>
  </ContentType>
</Elements>

Next, I’ll define a list based on that content type by right-clicking PurchasingMgr in Solution Explorer and selecting Add New Item. I’ll select the List Definition from Content Type item template and name the list definition NonStandBusPurchaseRequestsListDefn and click Add.

In the SharePoint Customization Wizard, I’ll select the content type created earlier and check the “Add a list instance” box. The Elements.xml created for the NonStandBusPurchaseRequestsListDefn is shown in Figure 4.

Figure 4 NonStandBusPurchaseRequestsListDefn Definition via Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Do not change the value of the Name attribute below. 
    If it does not match the folder name of the List Definition project item,
    an error will occur when the project is run. -->
    <ListTemplate
      Name="NonStandBusPurchaseRequestsListDefn"
      Type="10051"
      BaseType="0"
      OnQuickLaunch="TRUE"
      SecurityBits="11"
      Sequence="410"
      DisplayName="Purchasing Manager – 
        Non-Standard Business Purchase Requests List Definition"
      Description=
        "Non-Standard Business Purchase Requests List Definition 
         for the Purchasing Manager Solution"
      Image="/_layouts/images/itgen.png"/>
</Elements>

Note that each list definition in my feature needs to be identified by a unique Type value greater than 10,000 (to avoid conflicts with lists defined by SharePoint), and that I use that value in defining any list instance based on that definition.

To add the custom columns to the list view, I’ll open Schema.xml created and add the FieldRef elements to the default view, as seen in Figure 5.

Figure 5 Adding Custom Columns to the NonStandBusPurchaseRequestsListDefn Default View

<View BaseViewID="1" Type="HTML" WebPartZoneID="Main"  
  DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" 
  DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" 
  SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" 
  Url="AllItems.aspx">
  <Toolbar Type="Standard" />
  <XslLink Default="TRUE">main.xsl</XslLink>
  <RowLimit Paged="TRUE">30</RowLimit>
  <ViewFields>
    <FieldRef Name="Attachments">
    </FieldRef>
    <FieldRef Name="LinkTitle">
    </FieldRef>
    <FieldRef ID="{A74E67E5-8905-4280-90C9-DEBFFC30D43D}" 
      Name="RequestDescription" />
    <FieldRef ID="{CB5054F5-0C60-4DBE-94D2-CEFBFB793C7F}" Name="Price" />
  </ViewFields>
  <Query>
    <OrderBy>
      <FieldRef Name="ID">
      </FieldRef>
    </OrderBy>
  </Query>
  <ParameterBindings>
    <ParameterBinding Name="NoAnnouncements"   
      Location="Resource(wss,noXinviewofY_LIST)" />
    <ParameterBinding Name="NoAnnouncementsHowTo"   
      Location="Resource(wss,noXinviewofY_DEFAULT)" />
  </ParameterBindings>
</View>

Finally, I’ll define an instance of the list by selecting ListInstance1 under NonStandBusPurchaseRequestsListDefn and rename it NonStandBusPurchaseRequestsListInstance. I’ll open Elements.xml and add the following XML to base the list on the content type and to provide helpful descriptions for users:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Non-Standard Business Purchase Requests"
    OnQuickLaunch="TRUE"
    TemplateType="10051"
    Url="Lists/NonStandBusPurchaseRequestsListInstance"
    Description=
      "Non-Standard Business Purchase Requests List 
       for the Purchasing Manager Solution">
  </ListInstance>
</Elements>

In Visual Studio 2010, I’ll select Debug and then Start Debugging to test the solution. The solution is packaged and deployed to my on-premises site, as seen in Figure 6.

image: Debugging the PurchasingMgr Solution

Figure 6 Debugging the PurchasingMgr Solution

Now that I’ve tested the PurchasingMgr solution, I’m ready to deploy it to SharePoint Online. I’ll create a new site collection in SharePoint Online named Purchasing using the Team Site template. Back in Visual Studio 2010, I’ll package the solution by right-clicking on the PurchasingMgr project in the Solution Explorer and selecting Package. To deploy the solution to SharePoint Online, I’ll just need to upload it to the Solution Gallery and activate the site features (I’ll need site collection administrator privileges to do so). To do this, I’ll log in to SharePoint Online and navigate to my site Collection and select Site Actions | Site Settings, and then Solutions to access the Solutions Gallery. In the Solution Gallery, 
I’ll click the Solutions tab and select Upload Solution in the ribbon, then browse to the PurchasingMgr.wsp file in bin\Debug and click OK and then Activate. You’ll see your solution in the Solution Gallery as seen in Figure 7.

image: PurchasingMgr Solution Deployed to SharePoint Online

Figure 7 PurchasingMgr Solution Deployed to SharePoint Online

Next, to activate the feature that contains my site columns, content type and list, I’ll navigate to the Purchasing site and select Site Actions | Site Settings | Manage Site Features. I’ll select the Purchasing Manager - Content Types and Lists feature and select Activate. At this point you should see the Non-Standard Business Purchase Requests lists in your SharePoint Online site.

The Purchasing Manager is just one example of what you can accomplish in SharePoint Online with sandboxed solutions. Keep in mind the limitations in sandboxed solutions and in the SharePoint Online supported features, and you can create solutions that will run in SharePoint 2010 or SharePoint Online.

Creating Client-Side Solutions with Silverlight

The client OM, also introduced with SharePoint 2010, provides an object-oriented, client-side API for SharePoint clients built using the Microsoft .NET Framework, Silverlight and ECMAScript (including JavaScript and JScript) that run on remote computers (including the browser for Silverlight and ECMAScript). The API is consistent with the Microsoft.SharePoint server-side namespace, so it’s easy to learn. The API is also consistent across the supported client types, so it’s easy to apply that knowledge across different client solutions. The client OM API is supported in SharePoint Online and is a valuable tool for cloud development.

For example, I can use the client OM to create a Silverlight 4 application to add items to my list and host the application in a sandboxed Web Part. To do this, I’ll open Visual Studio 2010, select File | New Project and in the New Project dialog select Empty SharePoint Project. I’ll name the project PurchasingMgrWP and click OK. Again, I’ll create the solution as a sandboxed solution and point it at my on-premises Purchasing site. To create the Silverlight 4 application, I’ll right-click on the PurchasingMgrWP solution, select Silverlight under Installed Templates, select Silverlight Application and name the solution NonStandBusPurchaseReqsSLOM. In the New Silverlight Application dialog, I’ll uncheck “Host the Silverlight application in a new Web Site” (we’ll test by hosting the application in SharePoint) and select Silverlight 4 for the Silverlight Version.

To reference the Silverlight client OM API, I’ll add references to Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin. Next, I’ll create the Silverlight UI by opening MainPage.xaml and replacing the XAML with the code in Figure 8.

Figure 8 NonStandBusPurchaseReqsSLOM MainPage.xaml

<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
  x:Class="NonStandBusPurchaseReqsSLOM.MainPage"
  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"
  mc:Ignorable="d"
  d:DesignHeight="300" d:DesignWidth="400">
  <Grid x:Name="LayoutRoot" Background="White">
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
      </Grid.RowDefinitions>
        
      <sdk:Label Content="Title:" Grid.Column="0" Grid.Row="0" Margin="3"/>
      <sdk:Label Content="Description:" Grid.Column="0" Grid.Row="1" Margin="3"/>
      <sdk:Label Content="Price:" Grid.Column="0" Grid.Row="2" Margin="3"/>
        
      <TextBox Name="Title" Grid.Column="1" Grid.Row="0" Margin="3"/>
      <TextBox Name="Description" Grid.Column="1" Grid.Row="1" Margin="3"/>
      <TextBox Name="Price" Grid.Column="1" Grid.Row="2" Margin="3"/>
        
      <Button Content="Add" Grid.Column="1" Grid.Row="3" Margin="3"     
        Name="addNonStanPurchaseReq" HorizontalAlignment="Right" 
        Height="25" Width="100" Click="addNonStanPurchaseReq_Click" />
  </Grid>
</UserControl>

The XAML in Figure 8 defines text boxes and a button to collect information to add to my list as seen in Figure 9.

image: MainPage.xaml in Designer

Figure 9 MainPage.xaml in Designer

Double-click the button in the designer and replace the class with the code in Figure 10.

Figure 10 addNonStanPurchaseReq_Click

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.SharePoint.Client;
namespace NonStandBusPurchaseReqsSLOM
{
  public partial class MainPage : UserControl
  {
    private string webUrl;
    public MainPage(string url)
    {
      webUrl = url;
      InitializeComponent();
    }
    private void addNonStanPurchaseReq_Click(object sender, RoutedEventArgs e)
    {   
      ClientContext clientContext = new ClientContext(webUrl);
      Web webSite = clientContext.Web;
      ListCollection webLists = webSite.Lists;
      List nonStandBusPurList = 
        clientContext.Web.Lists.GetByTitle(
        "Non-Standard Business Purchase Requests");
      ListItem newListItem = 
        nonStandBusPurList.AddItem(new ListItemCreationInformation());
        newListItem["Title"] = Title.Text;
        newListItem["RequestDescription"] = Description.Text;
        newListItem["Price"] = Price.Text;
                        
        newListItem.Update();
        clientContext.Load(nonStandBusPurList, list => list.Title);
        clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
    }
    private void onQuerySucceeded(
      object sender, ClientRequestSucceededEventArgs args)
    {
      Dispatcher.BeginInvoke(() =>
      {
        MessageBox.Show("New item added.");
      });
    }
    private void onQueryFailed(object sender, 
      ClientRequestFailedEventArgs args)
    {
      Dispatcher.BeginInvoke(() =>
      {
        MessageBox.Show("Request failed. " + args.Message + "\n" + 
          args.StackTrace);
      });
    }
  }
}

The code in Figure 10 follows a common pattern in client OM code. First, I’ll get access to the client context via the ClientContext class (which is equivalent to the SPContext class). Next, I’ll access the site and list via the Web, ListCollection and List classes, respectively. Note the similarity to the SPWeb, SPListCollection and SPList classes. Finally, I’ll create a ListItem by calling the List.AddItem method, populate it with data from the UI and call the ListItem.Update method. The ListItem isn’t actually created until the ClientContext.Load and ClientContext.ExecuteQueryAsync methods are called to execute the query. Note that you can save roundtrips to the server by loading multiple queries via ClientContext.Load, calling the 
ClientContext.ExecuteQueryAsync method.

To deploy the Silverlight 4 application, I’ll add a module to deploy the application with my Web Part project. I’ll select PurchasingMgrWP in the Solution Explorer, right-click and select Add | New Item |Module and name the module ClientBin. I’ll replace the contents of Elements.xml created with this XML:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="ClientBin">
    <File Path="ClientBin\NonStandBusPurchaseReqsSLOM.xap"  
      Url="ClientBin/NonStandBusPurchaseReqsSLOM.xap" />
  </Module>
</Elements>

This XML deploys the NonStandBusPurchaseReqsSLOM.xap file to the ClientBin folder in my SharePoint site.

To deploy the output of the NonStandBusPurchaseReqsSLOM project with the ClientBin module, I’ll select the ClientBin module in Solution Explorer and open the Project Output References property dialog. I’ll click Add and select NonStandBusPurchaseReqsSLOM as the Project Name and ElementFile as the DeploymentType.

Next, I’ll add a custom Web Part to my SharePoint solution to host my Silverlight 4 application. I’ll select PurchasingMgrWP in the Solution Explorer, right-click and select Add | New Item, select Web Part and give the Web Part the name NonStandBusPurchaseReqsWP. I’ll use a custom Web Part in order to pass parameters to my Silverlight 4 application, such as the URL of the site used to create ClientContext. In order to do this, I’ll add a helper class called SilverlightObjectTagControl.cs and replace the body of that class with the code in Figure 11.

Figure 11 Adding the SilverlightObjectTagControl.cs Helper Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace PurchasingMgrWP
{
  class SilverlightObjectTagControl : WebControl
  {
    public string Source { get; set; }
    public string InitParameters { get; set; }
    protected override void CreateChildControls()
    {
      base.CreateChildControls();
      if (Source != null && Source != "")
      {
        string width = (this.Width == Unit.Empty) ? "400" : 
          this.Width.ToString();
        string height = (this.Height == Unit.Empty) ? "300" : 
          this.Height.ToString();
        this.Controls.Add(new LiteralControl(
          "  <div>" +
          "  <object data=\"data:application/x-silverlight-2,\" +
          "  type=\"application/x-silverlight-2\" width=\"" + width +         
          "  "\" height=\"" + height + "\">" +
          "  <param name=\"source\" value=\"" + Source + "\"/>" +
          "  <param name=\"onerror\" value=\"onSilverlightError\" />" +
          "  <param name=\"background\" value=\"white\" />" +
          "  <param name=\"minRuntimeVersion\" value=\"4.0.50826.0\" />" +
          "  <param name=\"autoUpgrade\" value=\"true\" />" +
          "  <param name=\"initparams\" value=\"" + InitParameters + "\" />" +
          "  <a href=\"http://go.microsoft.com/fwlink/?LinkID=" +
          "  149156&v=4.0.50826.0\" +
          "  style=\"text-decoration: none;\">" +
          "  <img src=\"http://go.microsoft.com/fwlink/?LinkId=161376\" +
          "  alt=\"Get Microsoft Silverlight\" style=\"border-style: none\"/>" +
          "  </a>" +
          "  </object>" +
          "  <iframe id=\"_sl_historyFrame\" +
          "  style=.visibility:hidden;height:0;width:0;border:0px.></iframe>" +
          "  </div>"
          ));
      }
    }
  }
}

The SilverlightObjectTagControl class in Figure 11 has two properties: Source is used to pass the URL of the Silverlight application to load in the Web Part, and InitParameters to pass initialization parameters to the Silverlight 4 application. These properties are used to build the <object /> tag for the Silverlight application in the CreateChildControls method. To use this class, open NonStandBusPurchaseReqsWP.cs and replace the code in that class with the code in Figure 12.

Figure 12 NonStandBusPurchaseReqsWP.cs

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace PurchasingMgrWP.NonStandBusPurchaseReqsWP
{
  [ToolboxItemAttribute(false)]
  public class NonStandBusPurchaseReqsWP : WebPart
  {
    protected override void CreateChildControls()
    {
      base.CreateChildControls();
      SilverlightObjectTagControl slhc = 
        new SilverlightObjectTagControl();
      slhc.Source = SPContext.Current.Site.Url + 
        "/ClientBin/NonStandBusPurchaseReqsSLOM.xap";
      slhc.InitParameters = "url=" + SPContext.Current.Web.Url;
        this.Controls.Add(slhc);
    }
  }
}

The code in Figure 12 creates an instance of SilverlightObjectTagControl, sets the Source property to the URL of the Silverlight application in ClientBin and sets the InitParameters property to hold the URL of the current site (where the Non-Standard Business Purchase Requests list can be found). To pass the URL to the constructor of the MainPage class in NonStandBusPurchaseReqsSLOM, open App.xaml.cs and add the following code to the Application_Startup event:

private void Application_Startup(object sender, 
    StartupEventArgs e)
  {
    string url = e.InitParams["url"];
    this.RootVisual = new MainPage(url);
  }

To test the Web Part, deploy the PurchasingMgr.wsp package to the on-premises Purchasing site to deploy the Non-Standard Business Purchase Requests list (the list was removed when the debug session listed earlier was ended), and then debug the PurchasingMgrWP solution from Visual Studio 2010. When added to \Purchasing\Home.aspx, the Web Part allows me to add items directly to the list from Silverlight, as seen in Figure 13 and Figure 14.

image: The NonStandBusPurchaseReqsWP in Action

Figure 13 The NonStandBusPurchaseReqsWP in Action

image: The Updated Non-Standard Business Purchase Requests List

Figure 14 The Updated Non-Standard Business Purchase Requests List

Developing and debugging against the on-premises site allows me to use Visual Studio 2010 to debug both the SharePoint and Silverlight 4 code until I have the solution tested completely. At that point, I’ll upload the PurchasingMgrWP.wsp to the Solution Gallery in SharePoint Online.

The SharePoint client OM provides a familiar and consistent object-oriented API for accessing lists and libraries in SharePoint Online. The API is a subset of the Microsoft.SharePoint API and is scoped to the site collection and below, which is perfectly aligned to SharePoint Online development.

SharePoint Solutions in the Cloud

Summing up, SharePoint Online provides SharePoint developers a unique opportunity to build SharePoint solutions for the cloud using the skills and tools they already have. By understanding SharePoint Online customization features (including what’s supported and what’s not), sandboxed solutions, the SharePoint client OM and declarative workflows built using SharePoint Designer 2010, you can build SharePoint solutions that run in the cloud with SharePoint Online. To keep up on SharePoint Online development throughout the beta process, check out the SharePoint Online Developer Resource Center (msdn.microsoft.com/office/dn448478).


Chris Mayo is a technology specialist focusing on Office 365 and SharePoint Online. He has experience as both a writer and a public speaker delivering technical content to audiences ranging in size from small groups to thousands. He coauthored “Programming for Unified Communications with Microsoft Office Communications Server 2007 R2” (Microsoft Press, 2009). He’s been with Microsoft for 10 years. Prior to joining Microsoft, he served as a developer and architect in the IT departments of Fortune 500 companies in the retail and finance industries. Keep up with Mayo at his blog, blogs.msdn.com/b/cmayo.

Thanks to the following technical experts for reviewing this article: George Durzi, Steve Fox, AJ May and Christina Storm