本文章是由機器翻譯。

雲端共同作業

利用 Silverlight 網頁組件將 SharePoint 連接到 Windows Azure

Steve Fox

對於穩定的開發人員平臺這一稱譽,Microsoft SharePoint 2010 是受之無愧的。通過對話方塊框架和 Silverlight 提供新的服務、API、資料可程式設計性和 UI 支援,這一改進的平臺有很多優勢可以吸引開發人員。

隨著人們對雲計算的興趣不斷提高,越來越多的使用者向我詢問開發人員如何將 SharePoint 應用程式和基於雲的技術集成起來。上述很多功能都可以通過某種方式與作為平臺的 Windows Azure 相集成。此外,通過 OData、REST、Web 2.0 社交應用程式(如 Twitter 或 Facebook)API 等其他技術,也可以實現 SharePoint 與雲的集成,當然,通過採用 SOAP 或 Windows Communication Foundation (WCF) 服務的服務型體系結構也可以實現。

我們已經知道,雲和 SharePoint 之間存在諸多集成可能,在本文中,我將介紹一下 SharePoint 和 Windows Azure 之間的一些具體集成點。同時,我會介紹實現集成的步驟。

平臺基礎知識

Windows Azure 平臺由三部分組成。第一部分是 Windows Azure 本身,負責提供資料和管理功能。第二部分是 SQL Azure,負責在雲中提供高可用性的交易資料。第三部分是 Windows Azure AppFabric,負責提供能夠實現更高級直接服務調用方案的服務匯流排。

使用 Windows Azure,您可以實現多種集成方式。例如,您可以先將構建的 WCF 服務部署到雲中,然後將該服務集成到 SharePoint 中。也可以從 Windows Azure 中獲取資料,然後在 SharePoint 中對資料進行建模。另外,您還可以使用 Windows Azure AppFabric 服務匯流排來實現更複雜的服務方案,用於連接 SharePoint Online 與內部 SharePoint。

無論哪種集成,您都需要瞭解有哪些方法是可行的。图 1 列出了可用於實現 SharePoint 和 Windows Azure 集成的不同方式,我們將以此為起點。此表特定于 SharePoint 2010。其中某些可選方式需要比其他方式進行更多編碼工作。

图 1 常见集成点

Azure 集成 方式
SharePoint 用戶端 
物件模型 在清單中與 Windows Azure 資料交互。
業務連接 
服務 (BCS) 對 Windows Azure 的資料進行建模或向 SQL Azure 構建外部清單。
Silverlight 創建 Windows Azure 服務或資料的 UI。
沙箱解決方案/
SharePoint Online 通過 Silverlight 應用程式利用部署到網站集合的 Windows Azure。
Office 自訂用戶端 直接使用 Windows Azure 的資料或使用公開資料的 BCS 清單。
標準/可視 
Web 部件 利用 Windows Azure 的服務和資料。
Open XML 在文檔中管理 Windows Azure 資料。
REST 使用 REST 與 SharePoint 集成的 Windows Azure 資料交互。
Office Server 服務 與 Open XML 結合使用,以便在伺服器上自動生成文檔(如 PDF)。
工作流/
事件接收器 與 Windows Azure 服務、工作流或資料關聯的狀態或事件。
LINQ 用於查詢 Windows Azure 資料物件。
搜索 聯合搜索以包括 Windows Azure 資料。

無論選擇何種方式,您都應該注意,本文所述的 SharePoint 在與 Windows Azure 集成後仍具備消耗性,未進行託管。換句話說,SharePoint 不是 Windows Azure 承載的服務,而是使用 Windows Azure 資料或服務的應用程式。Windows Azure 提供 SharePoint 專案(如 Web 部件或 Silverlight 應用程式)將使用的應用程式或資源。在本文中,我將通過一個具體的示例,介紹在利用 Windows Azure 中部署的自訂 WCF 服務的 SharePoint 中,如何集成 Silverlight 應用程式。

如果是初次體驗,您需要確保已安裝了適當的開發環境。開發環境至少需要包含以下軟體:

  • Visual Studio 2010
  • Windows Azure SDK 和工具
  • SharePoint Server 2010
  • Office 2010 Professional Plus
  • SQL Server 2008 R2
  • Silverlight 運行時、SDK 和工具

對於 Windows Azure,您還需要確保已設置開發人員帳戶,以便創建一個開發人員門戶來管理雲應用程式、資料和服務。microsoft.com/windowsazure/getstarted 提供了構建這些應用程式和服務所需的所有 Windows Azure 工具。請注意,您可以將上述軟體安裝在現有開發電腦上,也可以從 tinyurl.com/33bgpy6 下載一個預配置了上述軟體(Windows Azure 工具除外)的虛擬機器。(另外,您還可以選擇安裝 code.msdn.microsoft.com/vsixforsp 提供的 Silverlight Web 部件 Visual Studio 擴展。)

設置開發環境後,您就可以開始開發第一個集成專案了。在本文中,我將執行三個步驟:

  1. 創建和部署自訂的 Windows Azure WCF 服務。
  2. 創建一個可以使用自訂 Windows Azure 服務且支援 Silverlight 的 Web 部件。
  3. 在 SharePoint 網站中部署和使用支援 Silverlight 的 Web 部件。

下麵,我們逐步完成這些步驟。

創建 WCF 服務

假設,您希望將某個服務部署到整個銷售部門,同時希望在雲中託管該服務。該服務將檢索競爭對手資訊,它支援兩種方法:獲取特定 競爭對手資訊,以及返回包含所有 競爭對手資訊的清單。您將創建這兩種方法,不過只實現批量返回競爭對手資訊。閱讀本文之後,您可以擴展這些代碼,對特定競爭對手資訊的檢索請求進行回應。

若要創建 WCF 服務,請打開 Visual Studio 2010,啟動新專案。在新建專案嚮導中,選擇“雲”範本。提供一個專案名稱(我的名稱是 Competitors),然後按一下“確定”。選擇“WCF 服務 Web 角色”專案,按一下“確定”。

Visual Studio 會創建一個新的解決方案,其中包含大量資源,包括 Windows Azure 角色設定檔和 WCF 服務代碼和約定。在本示例中,將使用駐留記憶體的物件,因此,請按右鍵 WCF 專案,選擇“添加”,然後選擇“類”。提供類名稱 (Competitor),將以下代碼添加到類檔中:

namespace WCFServiceWebRole1 {
  public class Competitor {
    public string svcCompeteID { get; set; }
    public string svcCompeteName { get; set; }
    public string svcCompeteFY09 { get; set; }
    public string svcCompeteFY10 { get; set; }
  }
}

代碼包含四個屬性(競爭對手 ID、名稱及 2009 財年和 2010 財年的銷售業績)。

Silverlight 還將用作展示層,因此,需要在專案中添加一個用戶端訪問策略檔,以支援 Silverlight 跨域調用 Windows Azure 服務。 為此,請按右鍵 WCF 專案,選擇“添加”,然後再按一下“新建專案”。 在“新建專案”對話方塊中,選擇“資料”類別,然後選擇“XML”。 將新檔命名為 clientaccesspolicy.xml,然後按一下“添加”。 用下麵的代碼替換新檔中的 XML 代碼:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

然後,為 WCF 服務創建服務約定。 在本示例中,為簡單起見,只創建兩個操作約定。 第一個操作用於獲取單個競爭對手(getACompetitor 方法),第二個操作用於獲取所有競爭對手(getAllCompetitors 方法)。 請注意,如果要獲取特定競爭對手記錄,需要傳遞 ID (custID)。 图 2 是這兩個約定的摘要。

图 2 服务约定

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCFServiceWebRole1 {
  [ServiceContract]
  public interface IService1 {
    [OperationContract]
    string[] getACompetitor(string custID);

    [OperationContract]
    List<Competitor> getAllCompetitors();
    }
}

完成約定後,就可以添加一些代碼來實現約定了。 與服務約定對應的服務代碼如圖 3 所示。 這段代碼包含一個用於獲取單個競爭對手記錄的方法 (getACompetitor)、一個用於獲取所有競爭對手資訊的方法 (getAllCompetitors),以及一個用來生成競爭對手資訊的方法 (generateCompeteData)。 這些代碼很簡單,就是利用駐留記憶體的資料結構(如清單集合和陣列)和 LINQ 創建資料,然後將資料傳遞給調用應用程式。 在本示例中,調用應用程式是將要部署在 SharePoint 中的 Silverlight 應用程式。

圖 3 服務代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCFServiceWebRole1 {
  public class Service1 : IService1 {
    List<Competitor> myCompetitors = new List<Competitor>();

    public string[] getACompetitor(string custID) {
      generateCompeteData();

      string[] returnCompete = new string[4];

      var returnListOfData = (
        from compete in myCompetitors
        where  compete.svcCompeteID  == custID
        select compete).ToArray();

      foreach (var competeRecord in returnListOfData) {
        returnCompete[0] = competeRecord.svcCompeteID;
        returnCompete[1] = competeRecord.svcCompeteName;
        returnCompete[2] = competeRecord.svcCompeteFY09;
        returnCompete[3] = competeRecord.svcCompeteFY10; 

      };

      return returnCompete;
    }

    public List<Competitor> getAllCompetitors() {
      generateCompeteData();
      List<Competitor> returnlistOfCompetitors = 
        new List<Competitor>();

      var returnListOfData = (
        from customer in myCompetitors
        select customer).ToArray();

      foreach (var compete in returnListOfData) {
        Competitor tempCompeteRecord = new Competitor();
        tempCompeteRecord.svcCompeteID = compete.svcCompeteID;
        tempCompeteRecord.svcCompeteName = compete.svcCompeteName;
        tempCompeteRecord.svcCompeteFY09 = compete.svcCompeteFY09;
        tempCompeteRecord.svcCompeteFY10 = compete.svcCompeteFY10;
        returnlistOfCompetitors.Add(tempCompeteRecord);
      };

      return returnlistOfCompetitors;
    }

    private void generateCompeteData() {
      Competitor compete1 = new Competitor();
      compete1.svcCompeteID = "BR-CAN-8909";
      compete1.svcCompeteName = "Bauer - Canada";
      compete1.svcCompeteFY09 = "$45,093,028.00";
      compete1.svcCompeteFY10 = "$50,493,820.00";
      myCompetitors.Add(compete1);

      Competitor compete2 = new Competitor();
      compete2.svcCompeteID = "NK-USA-8665";
      compete2.svcCompeteName = "Nike - USA";
      compete2.svcCompeteFY09 = "$50,492,331.00";
      compete2.svcCompeteFY10 = "$52,019,828.00";
       myCompetitors.Add(compete2);

      Competitor compete3 = new Competitor();
      compete3.svcCompeteID = "GF-EU-9912";
      compete3.svcCompeteName = "Graf - Europe";
      compete3.svcCompeteFY09 = "$24,403,920.00";
      compete3.svcCompeteFY10 = "$24,001,926.00";
      myCompetitors.Add(compete3);

      Competitor compete4 = new Competitor();
      compete4.svcCompeteID = "CCM-USA-8843";
      compete4.svcCompeteName = "CCM Hockey";
      compete4.svcCompeteFY09 = "$12,209,105.00";
      compete4.svcCompeteFY10 = "$10,092,813.00";
      myCompetitors.Add(compete4);

    }
  }
}

此時,就創建好了 WCF 服務,差不多可以開始 SharePoint 部分的集成工作了。不過,在此之前,您需要將該服務部署到 Windows Azure。

若要部署該服務,您必須設置 Windows Azure 開發人員帳戶。完成後,只需按右鍵 Windows Azure 專案,然後選擇“發佈”。

發佈服務時,會出現對話方塊,供您提供憑據。如圖 4 所示,您可以選擇只創建服務包(Visual Studio 在本地資料夾中創建兩個需要添加到 Windows Azure 開發人員門戶的核心檔),或通過預配置資訊自動部署服務。在本示例中,按一下“僅創建服務包”,然後按一下“確定”。

图 4 服务发布选项

此操作會創建兩個檔,即 Competitors 和 ServiceConfiguration。Competitors 是服務包檔(實質上是資源存檔),ServiceConfiguration 是 XML 設定檔。

現在,可以導航到 Windows Azure 開發人員門戶,將這些檔添加到服務。為此,請導航到服務,按一下“部署”(如果已經部署過服務,要對服務進行升級,則按一下圖 5 所示的“升級”)。然後,可以流覽到這兩個檔,按一下“確定”。上傳服務檔可能需要幾分鐘時間。

圖 5 將服務手動部署到 Windows Azure

出現“就緒”消息後,可以按一下該網頁上顯示的連結來測試服務端點。請注意,您可能需要在服務 URL 的末尾添加服務名稱,如:

  http://serviceendpoint.azure.com/Service1.svc.

此時,就可以拋開 Windows Azure 去處理 SharePoint 了。

創建支援 Silverlight 的 Web 部件

您可以通過兩種方式為 SharePoint 創建 Silverlight Web 部件。一種方式是,在 Visual Studio 中只創建 Silverlight 應用程式,然後將 XAP 檔部署到 SharePoint(例如將其上傳到文件庫),最後使用 SharePoint 2010 的本機 Silverlight Web 部件載入 Silverlight 應用程式。這是在 SharePoint 上部署 Silverlight 應用程式最快的方式,涉及的編碼也較少。

另一種方法稍微有趣一些,即,使用 Silverlight 和 SharePoint Web 部件專案範本 (code.msdn.microsoft.com/vsixforsp)。這種方法會自動將 Silverlight 應用程式打包到 Web 部件中,這就意味著,您只需創建 Silverlight 應用程式,然後將它以 Web 部件的形式部署到 SharePoint。這種方式使您能夠更好地控制代碼,此外,還可將真正的 Web 部件部署到 SharePoint。

若要使用範本,請導航到 Codeplex 網站,按一下 Silverlight 和 SharePoint VSIX 連結,然後下載並解壓縮檔。解壓縮檔後,只需通過按兩下安裝 .vsix 檔,然後重新開機 Visual Studio 2010。

安裝 Silverlight Web 部件範本後,返回 Visual Studio 解決方案,依次按一下“檔”、“添加”、“新建專案”,然後在“解決方案”欄位中選擇“添加到解決方案”。導航到 SharePoint 2010 資料夾,然後選擇 Silverlight Web 部件專案範本。提供 Web 部件名稱(我使用的是 CompetitorSPWebPart),然後按一下“確定”。

按一下“確定”後,系統會提示您輸入 SharePoint 網站 URL。在此處添加網站 URL,然後選擇“部署為場解決方案”。此時,系統會提示輸入多個項,包括 Silverlight 專案的名稱、版本、XAP 檔的部署位置,以及 Web 部件的標題和說明(請參見圖 6)。完成這部分嚮導後,按一下“完成”。(請注意,您可以使用 Silverlight 3 或 4 來處理專案範本,Microsoft 目前正在升級範本,準備在 Codeplex 上重新發佈。)

圖 6 配置 Silverlight Web 部件

現在,有了含 Silverlight 應用程式的 SharePoint Web 部件,可以使用 Silverlight 應用程式來構建 Web 部件的 UI 和功能。

首先,在 Silverlight 專案中,按右鍵“引用”,選擇“添加服務引用”,添加對 Windows Azure 服務的引用。為服務提供命名空間名稱(我使用的是 GetCompeteAzureService),然後按一下“確定”。這和在應用程式中使用任何其他服務引用的方法是一樣的,只是在本例中,端點指向的是 Windows Azure 服務。

此時,可以針對 Windows Azure 服務編寫代碼。如前所述,您需要在 SharePoint 應用程式中使用 getAllCompetitors 方法。

應用程式需要一個 UI。我創建的是一個簡單的 UI,可以呈現 Windows Azure 服務調用命令返回的資料。其核心控制項是一個清單方塊控制項,其中包含一些圖像以顯生動。有關詳細資訊,請參閱本文的代碼下載部分。

接下來,將自訂類 Competitor 添加到 Silverlight 應用程式。Competitor 有四個屬性,它們對應于圖 3 所示服務代碼定義的競爭對手資料:

namespace CompetitorDisplayApp {
  public class Competitor {
    public string competeID { get; set; }
    public string competeName { get; set; }
    public string competeFY09 { get; set; }
    public string competeFY10 { get; set; }
  }
}

現在,可以在 XAML 隱藏代碼中添加一些代碼來實現 getAllCustomers 方法。在圖 7 中,可以看到,我是用清單集合 myCompetitors 來存儲 Windows Azure 服務調用命令返回的資料的。這裡沒有什麼繁重的任務;代碼使用 Competitor 物件填充要與清單方塊 (competeList) 綁定的 myCompetitors 清單集合。

圖 7 自訂 Competitor 物件

using CompetitorDisplayApp.GetCompeteAzureService;

namespace CompetitorDisplayApp {
  public partial class MainPage : UserControl {
    public string SiteUrl { get; set; }

    List<Competitor> myCompetitors = new List<Competitor>();

    public MainPage() {
      InitializeComponent();

      this.Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e) {
      LoadAzureData();
    }

    private void LoadAzureData() {
      GetCompeteAzureService.Service1Client azureSvcProxy = 
        new Service1Client();
      azureSvcProxy.getAllCompetitorsAsync();
      azureSvcProxy.getAllCompetitorsCompleted += 
        new EventHandler<getAllCompetitorsCompletedEventArgs>(
        azureSvcProxy_getAllCompetitorsCompleted);
    }

    void azureSvcProxy_getAllCompetitorsCompleted(
      object sender, getAllCompetitorsCompletedEventArgs e) {

      var competeData = e.Result;
      foreach (var item in competeData) {
        Competitor tempRecord = new Competitor();
        tempRecord.competeID = item.svcCompeteID;
        tempRecord.competeName = item.svcCompeteName;
        tempRecord.competeFY09 = item.svcCompeteFY09;
        tempRecord.competeFY10 = item.svcCompeteFY10;
        myCompetitors.Add(tempRecord);
      }

      competeList.ItemsSource = myCompetitors;
    }
  }
}

此時,編碼任務就完成了。不過,大致看一下通過 Silverlight Web 部件範本創建的預設代碼,瞭解為什麼這樣的方式比只使用 SharePoint 提供的預設 Silverlight Web 部件更有效,會對我們有所説明。

图 8 是在 Visual Studio 創建 Silverlight Web 部件專案時創建的預設 Web 部件代碼。可以看到,該包裝代碼創建了 SilverlightPluginGenerator 物件,並且為 Web 部件設置了屬性。這些屬性是在設計時管理的(這與通過 SharePoint 的“工具”窗格打開 Web 部件、編輯高度和寬度的方式不同)。另外,如果該 Web 部件部署到 Web 部件庫中,您不必執行複製和粘貼操作,這是因為,已經有了呈現 Silverlight 應用程式的功能。

圖 8 預設 Web 部件代碼

[ToolboxItemAttribute(false)]
public class SilverlightWebPart : WebPart {
  private SilverlightPluginGenerator _silverlightPluginGenerator = null;

  public SilverlightWebPart() {
    this._silverlightPluginGenerator = 
      new SilverlightPluginGenerator {

      Source = new Uri(
        "/XAPS/Silverlight/CompetitorDisplayApp/CompetitorDisplayApp.xap",
        UriKind.Relative),
        Width = new Unit(400, UnitType.Pixel),
        Height = new Unit(300, UnitType.Pixel),
        BackGround = Color.White,
        Version = SilverlightVersion.v3,
        AutoUpgrade = true,
        OnError = "onSilverlightError",
    };
  }

  protected override void CreateChildControls() {
    base.CreateChildControls();

    this.Controls.Add(new LiteralControl(
      @"<script type=""text/javascript"">" + 
      Resources.onSilverlightErrorHandler + 
      "</script>"));

    this._silverlightPluginGenerator.InitParams.Add(new InitParam(
      "SiteUrl", SPContext.Current.Site.Url));

    this.Controls.Add(new LiteralControl(
      this._silverlightPluginGenerator.ToString()));
  }

  protected override void RenderContents(HtmlTextWriter writer) {
    base.RenderContents(writer);
  }
}

最後,在執行初始配置嚮導時,已設置了 Web 部件的屬性。例如,如果打開 .webpart 檔,可以看到 Web 部件的名稱和說明(如果需要,可以在此進行修改):

<?xml version="1.0" encoding="utf-8"?>
<webParts>
  <webPart xmlns="https://schemas.microsoft.com/WebPart/v3">
    <metadata>
      <type name="CompetitorSPWebPart.SilverlightWebPart.SilverlightWebPart, $SharePoint.Project.AssemblyFullName$" />
      <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
    </metadata>
    <data>
      <properties>
        <property name="Title" type="string">Compete Information</property>
        <property name="Description" 
          type="string">This Web Part provides compete information.</property>
      </properties>
    </data>
  </webPart>
</webParts>

完成 Silverlight Web 部件後,就可以將 Web 部件部署到 SharePoint 上使用了。

部署 Web 部件

若要部署,請按右鍵 Web 部件專案(我的示例中是 CompetitorSPWebPart),然後選擇“部署”。部署 Web 部件時,Silverlight 應用程式會部署到 XAPS 文件庫中,Web 部件中會自動生成指向該 XAP 檔的連結。(如果您選擇使用 Silverlight 應用程式替代 Silverlight Web 部件範本,只需將 XAP 檔上載到 XAPS 文件庫,然後使用 SharePoint 中的本機 Silverlight Web 部件。)

現在,打開 SharePoint 網站,導航到(或創建)新的 Web 部件頁。(請注意,通過依次按一下“網站操作”、“查看所有網站內容”、“創建”和“Web 部件頁”,可以創建新的 Web 部件頁。)依次按一下“網站操作”、“編輯頁”和“添加 Web 部件”。導航到“自訂”類別,選擇 Web 部件(本示例中為 Compete Information),然後按一下“添加”。添加後,按一下“停止編輯”。結果類似于圖 9 的內容。

圖 9 最終用於調用 Windows Azure 服務的 Silverlight Web 部件

總結

SharePoint 和 Windows Azure 的集成是一個新事物,方式有很多種。在本例中,我介紹了如何創建自訂 Windows Azure 服務,如何通過自訂的基於 Silverlight 的 Web 部件利用該服務。通過這個簡單示例可以看到,通過 Windows Azure 服務和使用該服務的 Web 部件,可以實現更複雜的解決方案。

有關更多示例和演練,請訪問我的博客 blogs.msdn.com/b/steve_fox。獲取更多有關如何集成 SharePoint 和 Windows Azure 的代碼和文檔。

Steve Fox  是 Microsoft 的一名高級推廣經理。他在 IT 行業已工作了 15 年,其中 10 年在 Microsoft 從事自然語言、搜索以及 SharePoint 和 Office 開發工作。Fox 撰寫了很多文章和書籍,包括最近發佈的《Beginning SharePoint 2010 Development》(Wrox,2010)。

衷心感謝以下技術專家對本文的審閱: Paul Stubbs