将自定义 Azure 服务与业务连接服务集成
如何创建自定义 Azure 服务,然后将其与业务连接服务 (BCS) 集成
在这篇博客文章中,我将逐步讲解如何创建自定义 Azure 服务,然后将此服务与 SharePoint 2010 中的新功能——业务连接服务 (BCS) 集成。您将遵循的流程是:
- 创建自定义 Azure 服务;
- 将 Azure 服务部署到您的托管账户;
- 创建新的 BCS 应用程序;以及
- 将 BCS 应用程序部署到 SharePoint 2010。
将 BCS 应用程序部署到 SharePoint 后,您将在外部列表中看到您的 Azure 服务清单中的服务调用。
让我们开始吧。
创建自定义 Azure 服务
要创建 Azure 服务,您必须设置好开发环境。这意味着要安装 SharePoint、Visual Studio 2010 以及 Azure 工具和 SDK。您还可以选择安装 Silverlight,但本次练习不需要它。
- 打开 VS 2010,点击“文件”、“新建”、“项目”,然后选择“云”。
- 选择“Windows Azure 云服务”,为您的服务提供一个名称,然后点击“确定”。
- 选择 WCF Worker Role 并将其添加到右侧窗格,然后点击“确定”。
- 当 VS 2010 创建项目结构时,右键点击项目,选择“添加”,然后选择“类”。
- 将该类命名为 Customer 并确保其结构如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WCFServiceWebRole1 { public class Customer { public string tempCustID { get; set; } public string tempCustTitle { get; set; } public string tempCustFirstName { get; set; } public string tempCustLastName { get; set; } public string tempCustEmail { get; set; } public string tempCustPhone { get; set; } } }
- 在 Service1.svc 类中,添加以下代码:
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<Customer> myCustomerList = new List<Customer>(); public string[] getACustomer(int custID) { generateCustomerData(); string strCustID = custID.ToString(); string[] returnCustomer = new string[6]; var returnListOfData = (from customer in myCustomerList where customer.tempCustID == strCustID select customer).ToArray(); foreach (var cust in returnListOfData) { returnCustomer[0] = cust.tempCustID; returnCustomer[1] = cust.tempCustTitle; returnCustomer[2] = cust.tempCustFirstName; returnCustomer[3] = cust.tempCustLastName; returnCustomer[4] = cust.tempCustEmail; returnCustomer[5] = cust.tempCustPhone; }; return returnCustomer; } public List<Customer> getAllCustomers () { generateCustomerData(); List<Customer> returnListOfCustomers = new List<Customer>(); var returnListOfData = (from customer in myCustomerList select customer).ToArray(); foreach (var cust in returnListOfData) { Customer tempCustomer = new Customer(); tempCustomer.tempCustID = cust.tempCustID; tempCustomer.tempCustTitle = cust.tempCustTitle; tempCustomer.tempCustFirstName = cust.tempCustFirstName; tempCustomer.tempCustLastName = cust.tempCustLastName; tempCustomer.tempCustEmail = cust.tempCustEmail; tempCustomer.tempCustPhone = cust.tempCustPhone; returnListOfCustomers.Add(tempCustomer); }; return returnListOfCustomers; } private void generateCustomerData() { Customer cust1 = new Customer(); cust1.tempCustTitle = "Dr."; cust1.tempCustID = "1"; cust1.tempCustFirstName = "Jane"; cust1.tempCustLastName = "Doe"; cust1.tempCustEmail = "jane.doe@acme.com"; cust1.tempCustPhone = "425-332-1092"; myCustomerList.Add(cust1); Customer cust2 = new Customer(); cust2.tempCustTitle = "Dr."; cust2.tempCustID = "2"; cust2.tempCustFirstName = "John"; cust2.tempCustLastName = "Doe"; cust2.tempCustEmail = "john.doe@acme.com"; cust2.tempCustPhone = "425-367-2928"; myCustomerList.Add(cust2); Customer cust3 = new Customer(); cust3.tempCustTitle = "Dr."; cust3.tempCustID = "3"; cust3.tempCustFirstName = "Ken"; cust3.tempCustLastName = "James"; cust3.tempCustEmail = "kenj@blueyonder.com"; cust3.tempCustPhone = "425-009-2890"; myCustomerList.Add(cust3); Customer cust4 = new Customer(); cust4.tempCustTitle = "Mrs."; cust4.tempCustID = "4"; cust4.tempCustFirstName = "Kerry"; cust4.tempCustLastName = "Smith"; cust4.tempCustEmail = "ksmith@fabrikam.com"; cust4.tempCustPhone = "425-289-1002"; myCustomerList.Add(cust4); Customer cust5 = new Customer(); cust5.tempCustTitle = "Ms."; cust5.tempCustID = "5"; cust5.tempCustFirstName = "Kendra"; cust5.tempCustLastName = "Anouille"; cust5.tempCustEmail = "kendra@acme.com"; cust5.tempCustPhone = "425-555-3391"; myCustomerList.Add(cust5); Customer cust6 = new Customer(); cust6.tempCustTitle = "Mrs."; cust6.tempCustID = "6"; cust6.tempCustFirstName = "Shanique"; cust6.tempCustLastName = "Smith"; cust6.tempCustEmail = "ssmith@acme.com"; cust6.tempCustPhone = "425-998-2091"; myCustomerList.Add(cust6); Customer cust7 = new Customer(); cust7.tempCustTitle = "Dr."; cust7.tempCustID = "7"; cust7.tempCustFirstName = "Ahmed"; cust7.tempCustLastName = "Singh"; cust7.tempCustEmail = "ahmeds@contoso.com"; cust7.tempCustPhone = "425-334-0900"; myCustomerList.Add(cust7); Customer cust8 = new Customer(); cust8.tempCustTitle = "Dr."; cust8.tempCustID = "8"; cust8.tempCustFirstName = "Sam"; cust8.tempCustLastName = "James"; cust8.tempCustEmail = "sam.james@contoso.com"; cust8.tempCustPhone = "425-442-8910"; myCustomerList.Add(cust8); Customer cust9 = new Customer(); cust9.tempCustTitle = "Mr."; cust9.tempCustID = "9"; cust9.tempCustFirstName = "Steve"; cust9.tempCustLastName = "Smith"; cust9.tempCustEmail = "steve.smith@acme.com"; cust9.tempCustPhone = "425-223-0657"; myCustomerList.Add(cust9); Customer cust10 = new Customer(); cust10.tempCustTitle = "Dr."; cust10.tempCustID = "10"; cust10.tempCustFirstName = "Yeo"; cust10.tempCustLastName = "Park"; cust10.tempCustEmail = "y.park@contoso.com"; cust10.tempCustPhone = "425-221-0288"; myCustomerList.Add(cust10); } } }
- 修改服务契约,使其如下所示:
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[] getACustomer(int custID); [OperationContract] List<Customer> getAllCustomers(); } }
- 完成后,点击“构建”以确保解决方案成功构建。
- 现在右键点击项目,选择“发布”。
- Visual Studio 将打开您的 Windows Azure 开发者门户。
- 您可以使用现有服务,或者点击“新建服务”创建一个新服务。如果您正在升级现有服务,请点击“升级”。
- 浏览到 ..\bin\Publish 目录以升级服务包文件和云服务配置文件。
- 点击“部署”,然后当服务部署完成后,点击“运行”。
- 服务将显示“准备就绪”并为您提供一个有效的 URL 以供使用。
- 导航到该 URL(并附加 Service1.svc – 例如 http://contoso.cloup.net/Service1.svc)。
- 浏览到 ..\bin\Publish 目录以升级服务包文件和云服务配置文件。
至此,您已经构建并部署了一个自定义 Azure 服务。该服务是自包含的——这意味着它不依赖于外部的任何东西(例如实体数据模型)。首先,这很好,也是一个快速启动和运行的简单方法。从长远来看,这并不完全现实,因为您可能需要将依赖项与 Azure 服务或应用程序一起部署。一个例子是利用 SQL Azure 作为您的后端数据存储,从而将数据连接或实体数据模型与部署的服务集成。
注意:有一个本地云开发结构允许您构建和部署服务。我发现创建一个测试客户端应用程序(例如简单的 WinForm 应用程序)以确保您的服务按预期工作,这在您部署自定义服务之前很有用。
重要提示:对于当前发布的 Azure,您需要确保在为 SharePoint 构建自定义服务时进行两次修复。首先是安装 Azure QFE 修复,以便您可以在服务器上运行服务。您可以在这里找到更多信息:http://code.msdn.microsoft.com/wcfazure/Wiki/View.aspx?title=KnownIssues&referringTitle=Home。为了节省您的时间,您需要:1)首先安装 QFE(您可以在此处下载 Windows 2008 R2 版本),以及 2)您需要确保修改 web.config 服务文件中的配置设置(在部署之前)以包含以下内容:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="LoadBalancedBehavior"> <serviceMetadata httpGetEnabled="true" /> <useRequestHeadersForMetadataAddress> <defaultPorts> <add scheme="http" port="81" /> <add scheme="https" port="444" /> </defaultPorts> </useRequestHeadersForMetadataAddress> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
Azure 服务完成后(即步骤 1 和 2 完成),您现在可以进入开发过程的步骤 3 和 4。
在 SharePoint 中使用 Azure 服务
在这篇文章的这一部分,您将使用 Visual Studio BDC 元数据模型模板来与您的自定义 Azure 服务集成。这种集成的有趣之处在于,一旦您利用 BDC 模板,您还可以向解决方案添加其他模板——例如 Silverlight 项目——以使用您部署到 SharePoint 的数据模型。
让我们继续演练。
- 打开 Visual Studio 2010,点击“文件”、“新建”和“项目”。
- 选择“SharePoint”,然后选择“业务数据连接模型”。
- 提供名称和位置,然后点击“确定”。
- 打开 Entity1.cs 文件,并将代码替换为以下内容:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AzureBDCDataModel.AzureCustomers { public partial class Entity1 { public string Identifier1 { get; set; } public string tempCustTitle { get; set; } public string tempCustFirstName { get; set; } public string tempCustLastName { get; set; } public string tempCustEmail { get; set; } public string tempCustPhone { get; set; } } }
- 右键点击“服务引用”,然后选择“添加服务引用”。
- 在“服务地址”字段中添加 URL,然后点击“前往”以浏览到 Azure 服务 URL。
- 点击该服务并为您的服务添加一个名称,然后点击“添加引用”。
- 打开 Entity1Service.cs 文件,并将代码替换为以下内容:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using myAzureSvc = AzureBDCDataModel.AzureCustomerService; namespace AzureBDCDataModel.AzureCustomers { public class Entity1Service { public static Entity1 ReadItem(string id) { myAzureSvc.Service1Client myWCFProxy = new myAzureSvc.Service1Client(); string[] returnedData = new string[6]; returnedData = myWCFProxy.getACustomer(Int32.Parse(id)).ToArray(); Entity1 entity1 = new Entity1(); entity1.Identifier1 = returnedData[0]; entity1.tempCustTitle = returnedData[1]; entity1.tempCustFirstName = returnedData[2]; entity1.tempCustLastName = returnedData[3]; entity1.tempCustEmail = returnedData[4]; entity1.tempCustPhone = returnedData[5]; myWCFProxy.Close(); return entity1; } public static List<Entity1> ReadList() { myAzureSvc.Service1Client myWCFProxy = new myAzureSvc.Service1Client(); var salesData = myWCFProxy.getAllCustomers(); List<Entity1> mySalesInfoList = new List<Entity1>(); foreach (var item in salesData) { Entity1 tempEntity = new Entity1(); tempEntity.Identifier1 = item.tempCustID; tempEntity.tempCustTitle = item.tempCustTitle; tempEntity.tempCustFirstName = item.tempCustFirstName; tempEntity.tempCustLastName = item.tempCustLastName; tempEntity.tempCustEmail = item.tempCustEmail; tempEntity.tempCustPhone = item.tempCustPhone; mySalesInfoList.Add(tempEntity); } myWCFProxy.Close(); return mySalesInfoList; } } }
- 打开 BDC 资源管理器,并确保 Entity1 节点中的 TypeDescriptors 映射到 Entity1 对象——请参见下图。您可以通过右键点击节点并选择“添加 TypeDescriptor”来添加 TypeDescriptors。请确保在添加 TypeDescriptor 时,其名称与 Entity1 类中的名称一致,并且类型也匹配(例如,字符串变量为 System.String)。
- 右键点击项目,选择“部署”。
- 当项目成功部署后,导航到您的 SharePoint 站点。
- 点击“网站操作”,然后“查看所有站点内容”。选择“创建”,然后点击“列表”。
- 选择“外部列表”,然后点击“创建”。
- 为外部列表提供一个名称,然后浏览到外部内容类型。
- 您将在外部内容类型列表中找到您刚刚添加的新外部内容类型。
- 选择其中一个外部内容类型后,点击“确定”。结果应该与下面类似——一个包含虚构客户姓名和联系信息的列表。
至此,您已经构建并部署了一个简单的 Azure 服务,并且您已将该服务集成到 BCS 应用程序中,然后将其部署到 SharePoint。有几点需要注意。您可能会发现,当您将 BCS 应用程序部署到 SharePoint 后,首次加载外部列表时可能不会显示。这是因为 BCS 具有一组独立的权限,可供您控制该列表的读/写权限。
为确保您拥有适当的权限级别,请导航到 SharePoint 管理中心,选择“管理服务应用程序”和“业务数据连接服务”。
在这里,您将看到已部署到 SharePoint 的服务列表。点击您刚刚部署的服务,然后选择“设置对象权限”。
然后,您可以通过在相应字段中添加别名(Active Directory 别名)并点击“添加”来在此处添加权限。然后,您将特定的权限级别与该人员关联。
现在在此示例中,您正在调用一个只具有只读操作的服务。但是,您最终将利用 SQL Azure(它具有一组单独的用户名和密码凭据),在这种情况下,还需要在安全存储服务 (SSS) 中创建一个服务实例来管理您与 SQL Azure 的通信。
注意:我将在未来的文章中提供一些详细信息,但在此期间,您可以查看我之前的一篇文章,其中包含一些粗略的演示笔记:http://blogs.msdn.com/b/steve_fox/archive/2010/06/09/sharepoint-2010-amp-windows-azure-how-they-play-together.aspx。
至此,您的第一个自定义 Azure 服务集成就完成了。虽然您在这篇文章中使用了 BDC 元数据模型,但请记住还有许多其他方法可以与 SharePoint 集成。事实上,一旦您构建并部署了自定义 Azure 服务,您就可以使用相同的服务并将其与其他应用程序和 SharePoint 工件集成。例如,您可以创建一个 Visual Web 部件项目,然后调用 getAllCustomers 方法并将结果绑定到 Datagrid 对象。下图展示了一些与 SharePoint 2010 集成的更常见方式。

正如我将发布更多关于 Azure 和 SharePoint 的内容一样,当结合这两种技术时,您会看到巨大的潜力。随着更多公司向云发展,您将看到许多与 SharePoint 完美结合的不同解决方案。
编码愉快!