使用 Silverlight Web 部件将 SharePoint 连接到 Windows Azure
如何将 SharePoint 应用与基于云的技术集成。
Microsoft SharePoint 2010 作为稳健的开发平台,受到了应有的赞誉。通过新的服务、API、数据可编程性以及通过对话框框架和 Silverlight 实现的用户界面支持,开发人员有许多选择来深入研究这个进化的平台。
然而,随着人们对云计算兴趣的增长,我越来越多地收到关于开发人员如何将他们的 SharePoint 应用与基于云的技术集成的疑问。作为一个平台,上述许多功能都可以以某种方式与 Windows Azure 集成。此外,您还可以通过一系列其他技术将 SharePoint 与云集成,例如 OData、REST、用于 Twitter 或 Facebook 等应用程序的 Web 2.0 社交 API,当然,还可以通过面向服务的体系结构使用 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 Service Bus 来生成更复杂的服务场景,将 SharePoint Online 与本地 SharePoint 连接起来。
对于任何集成,您都需要了解其可能性。图 1 提供了一个起点,列出了您可以将 SharePoint 与 Windows Azure 集成的不同方式。此表特定于 SharePoint 2010,其中一些选项比其他选项需要更多的编码。
Azure 集成 | 如何 |
SharePoint 客户端对象模型 | 在列表中与 Windows Azure 数据进行交互。 |
业务连接服务 (BCS) | 为 Windows Azure 中的数据建模或为 SQL Azure 构建外部列表。 |
Silverlight | 创建针对 Windows Azure 服务或数据的用户界面。 |
沙盒解决方案/SharePoint Online | 利用 Windows Azure 的 Silverlight 应用程序部署到网站集。 |
Office 自定义客户端 | 直接从 Windows Azure 或暴露数据的 BCS 列表消费数据。 |
标准/Visual Web 部件 | 利用 Windows Azure 中的服务和数据。 |
Open XML | 在文档中管理 Windows Azure 数据。 |
REST | 使用 REST 与 Windows Azure 数据交互以集成到 SharePoint。 |
Office 服务器服务 | 与 Open XML 结合,在服务器上自动生成文档(如 PDF)。 |
工作流/事件接收器 | 与 Windows Azure 服务、工作流或数据关联的状态或事件。 |
LINQ | 用于查询 Windows Azure 数据对象。 |
搜索 | 联合搜索以包含 Windows Azure 数据。 |
无论选择哪种集成方式,都重要的是要注意,在本文中,当与 Windows Azure 集成时,SharePoint 是作为消费者,而不是被托管者。换句话说,SharePoint 不是由 Windows Azure 托管的服务,而是消费 Windows Azure 数据或服务的应用程序。Windows Azure 提供 SharePoint 构件(如 Web 部件或 Silverlight 应用程序)将消费的应用程序或资源。在本文中,您将看到一个具体的示例,说明如何将 Silverlight 应用程序集成到 SharePoint 中,该应用程序利用部署到 Windows Azure 的自定义 WCF 服务。
如果您是全新开始,则需要确保设置了适当的开发环境。您的开发环境至少应包括以下内容:
- 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 工具。请注意,您可以将前面列出的项安装在现有的开发计算机上,也可以下载一个预先配置好的虚拟机,该虚拟机包含除 Windows Azure 工具之外的所有内容,链接为 tinyurl.com/33bgpy6。(此外,您还可以选择安装可在 code.msdn.microsoft.com/vsixforsp 获取的 Silverlight Web 部件 Visual Studio 扩展。)
在设置好开发环境后,就可以开始开发您的首次集成。在本文中,我将介绍三个步骤:
- 创建并部署自定义 Windows Azure WCF 服务。
- 创建一个支持 Silverlight 的 Web 部件,该部件可以消费自定义 Windows Azure 服务。
- 在您的 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 提供了协定的摘要。
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 应用程序。
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 开发者门户的两个核心文件),或者使用预先配置的信息自动部署您的服务。在此示例中,单击“仅创建服务程序包”并单击“确定”。
将创建两个文件:Competitors 和 ServiceConfiguration。Competitors 是一个服务程序包文件——本质上是一个资源存档——而 ServiceConfiguration 是一个 XML 配置文件。
现在,您可以导航到您的 Windows Azure 开发者门户并将这些文件添加到您的服务中。为此,请导航到您的服务并单击“部署”(如果您已部署并且正在升级服务,请单击“升级”,如图 5 所示)。然后,您可以浏览到这两个文件并单击“确定”。您需要几分钟时间来上传您的服务文件。
当您看到“就绪”消息时,可以单击同一网页上显示的链接来测试服务终结点。请注意,您可能需要在服务 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 应用程序。这是最快地将 Silverlight 应用程序部署到 SharePoint 的方法,并且需要的编码最少。
第二种,也是更有趣的方式是使用 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 部件的标题以及 Web 部件的描述(请参阅图 6)。完成此向导部分后,单击“完成”。(请注意,您可以使用 Silverlight 3 或 4 与项目模板一起使用,Microsoft 目前正在升级该模板以在 Codeplex 上重新发布。)
现在您有了一个包装 Silverlight 应用程序的 SharePoint Web 部件,并且您可以使用 Silverlight 应用程序来构建 Web 部件的用户界面和功能。
首先,在 Silverlight 项目中,右键单击“引用”并选择“添加服务引用”,以添加对 Windows Azure 服务的引用。为您的服务的命名空间提供一个名称(在本例中为 GetCompeteAzureService),然后单击“确定”。这与在应用程序中消费任何其他服务引用相同,只是在这种情况下,终结点指向的是 Windows Azure 服务。
至此,您可以针对 Windows Azure 服务进行编码。如前所述,您将利用 SharePoint 应用程序中的getAllCompetitors 方法。
您的应用程序需要一个用户界面。我创建了一个简单的用户界面,用于呈现调用 Windows Azure 服务返回的数据。核心控件是一个列表框控件,并添加了一些图片以增加吸引力。有关详细信息,请参阅本文的代码下载。
接下来,向 Silverlight 应用程序添加一个名为 Competitor 的自定义类。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 对象来帮助填充 myCompetitors 列表集合,然后将其绑定到列表框(competeList)。
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 部件设置了属性。这些属性是在设计时管理的(与打开 Web 部件,然后通过 SharePoint 中的“工具”窗格编辑高度和宽度相反)。此外,您可以避免复制粘贴,因为此 Web 部件已部署到 Web 部件库中——并且已准备好渲染 Silverlight 应用程序。
[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="http://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 中的内容。
总结
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