用于 SharePoint 开发的 Visual Studio 2010 工具 (转)
对许多开发人员来说,SharePoint 开发有些神秘,这些开发人员认为使用该平台进行开发很是复杂不便,超出了他们的能力。开发人员社区在使用工具集方面也存在差异。例如,一些开发人员将类库、带有 XML 配置文件的手动项目文件夹和生成后输出事件结合使用,以此生成 SharePoint 的功能和解决方案。而其他开发人员使用 STSDEV(一款社区工具)或 Visual Studio Extensions for Windows SharePoint Services (VSeWSS) 构建各种应用程序和解决方案,然后将它们部署到 SharePoint。换句话说,开发人员可能会通过多种途径将功能和解决方案包部署到 SharePoint。尽管面临挑战,SharePoint 开发人员社区人数仍显著增加 — 目前大约 600,000 名开发人员 — 并且还将继续增加。展望未来,借助现成的新 SharePoint 工具,Visual Studio 2010 将为开发人员打开进入 SharePoint 开发的大门。
作为开发平台,SharePoint 2010 向前进了一大步,这不仅在于平台可支持丰富的功能集,还因为投巨资研发了工具套件,旨在使开发过程更加高效,各个技能水平的开发人员都可以进行访问。SharePoint 2010 的两大核心开发人员工具是 SharePoint Designer 2010 和 Visual Studio 2010。(面向设计人员的配套工具集是 Expression 套件。)本文让您先来一睹 SharePoint 2010 开发,向您介绍 Visual Studio 2010 中的 SharePoint 工具(包括对新项目模板的简要介绍),并举例说明如何创建和部署示例可视化 Web 部件。
Visual Studio 2010 中的 SharePoint 工具
Visual Studio 2010 中有许多面向 SharePoint 开发人员的内容值得一提。首先,您可获得现成的 SharePoint 项目模板,因此立即便可开始进行解决方案开发。其次,已按 Windows SharePoint Package (WSP) 打包标准对工具进行标准化,因此当您将解决方案导入或部署到 SharePoint 时,Visual Studio 会将其视为解决方案包。再次,Visual Studio 2010 的 SharePoint 工具中附带了一些很棒的部署和打包功能,例如,解决方案收回和自定义部署配置。最后一点,新 SharePoint Explorer 提供本机查看和存在于 SharePoint 服务器上的自定义项目(例如,列表和工作流)。当然,这只是表示旨在进入社区并使 SharePoint 开发人员掌握和使用起来更轻松的 Visual Studio 工具集重要扩展的一个简要功能清单。
同样值得一提的是一些 SharePoint 2010 增强功能,这些功能绝对可在 Visual Studio 2010 的环境中使用。例如,使用新客户端对象模型,您可以通过引用的 DLL 而非 Web 服务调用访问 SharePoint 对象。(而在 SharePoint 2007 中不同,例如,通过使用 ASP.NET Web 服务访问 SharePoint 列表数据。)SharePoint 的 LINQ 还将 LINQ 的强大功能引入 SharePoint,例如,使您能够将列表处理为强类型化对象。此外,SharePoint 2010 中提供对 Silverlight(特别是在与客户端对象模型一起使用时)的本机支持 — 不用再浪费时间考虑 web.config 来开始进行此开发。经过沙箱处理的解决方案也提供了一种构建 SharePoint Web 部件并将其部署到站点而无需管理干预的方式 — 也就是说,无论是在 SharePoint 内部部署实例中还是在使用 SharePoint 托管版本的云中,都可以将 Web 部件部署到 SharePoint 站点并在该站点环境中运行。最后,外部数据列表使得与业务线系统之间的交互变为一个读取/写入过程,尽管这看起来不起眼,但却是一个巨大的飞跃,为您提供了工具支持,使您可快速有效地构建业务线集成。对于 SharePoint 2010 中的每项创新,Visual Studio 2010 都通过项目模板或 API 为专业开发人员提供了一些支持措施。如果说要挑个时机学习使用 SharePoint 开发,现在正合适。
开发可视化 Web 部件项目
开发人员在 SharePoint 中构建并部署的一种最常见的项目是 Web 部件。鉴于 Web 部件是 SharePoint 的核心构建模块之一,这很有意义。因为 SharePoint 在 ASP.NET 的顶层构建,Web 部件从 ASP.NET Web 部件体系结构继承关键功能。
Visual Studio 2010 中的其中一个新项目模板是 Visual Web Part(可视化 Web 部件)项目模板,开发人员使用它能直观地设计可以部署到 SharePoint 的 Web 部件。如果您是刚刚接触 SharePoint,这是开始构建 SharePoint 2010 的自定义应用程序的最佳方式。我将演示的可视化 Web 部件包含一些自含式代码,用于计算产品成本并在简单 Web 部件 UI 中列出信息。
图 1 新 SharePoint 项目模板
图 2 可视化 Web 部件的设计器视图
请确保在 64 位版本的 Windows Server 2008 上安装了 Visual Studio 2010 Beta 2 和 SharePoint 2010 Beta 2。打开 Visual Studio 2010,单击“文件”,“新建项目”,然后导航到“已安装模板”部分的 SharePoint 节点。图 1 显示了不同类型的可用项目模板。例如,Import VSeWSS Project(导入 VSeWSS 项目)模板提供了从当前 VSeWSS 项目升级的途径;工作流模板可用于创建工作流项目并将其部署到 SharePoint;Site Definition(站点定义)模板提供了可以扩建和部署的站点级基础结构;Import SharePoint Solution Package(导入 SharePoint 解决方案包)是可用于导入 WSP 以重新部署到本地服务器实例的模板。对于此演练,选择 Visual Web Part(可视化 Web 部件)项目模板,提供项目名称(例如,SampleWebPartProject)和位置,然后单击“OK”(确定)。
创建完项目后,Visual Studio 2010 会创建许多默认文件。在 Solution Explorer(解决方案资源管理器)中展开项目节点查看文件。将在本文中使用的密钥文件位于 SampleWebPartProject 节点。请注意,默认可视化 Web 部件名为“VisualWebPart1”。要更改此名称,在 Solution Explorer(解决方案资源管理器)中右键单击 VisualWebPart1 节点,选择“Rename”(重命名),然后输入 Web 部件的新名称。
还应注意,在 Solution Explorer(解决方案资源管理器)中是否存在功能和包节点。这对使用 SharePoint 功能打包 SharePoint 解决方案的 Visual Studio 2010 来说属于新内容。对于不熟悉 SharePoint 的开发人员,功能以 SharePoint 能够理解的方式组织您的应用程序。例如,可在站点级别或 Web 级别将功能部署到 SharePoint。功能是通过一组 XML 配置文件构造的,也引用了(取决于应用程序的信任级别)全局程序集缓存 (GAC) 中的程序集。尤其是,每项功能在 SharePoint 文件夹层次结构中都有自己的文件夹,配置文件位于该文件夹内并为此功能提供必需的元数据。包中包含各项功能及其他资产,将解决方案部署到 SharePoint 时使用包。包也是确定程序集部署位置的地方。Visual Studio 2010 引入了包设计器,使查看和管理包更为简单。双击“Package node”(包节点),设计器即会打开。使用设计器,您可以在可部署的包中添加和删除各项功能。在帮助开发人员使用增加的功能打造 SharePoint 解决方案方面,此设计器是一步重大进展。
切换回 Solution Explorer(解决方案资源管理器)视图,右键单击 ProductInfoUserControl.ascx 文件,然后在“Designer”(设计器)中选择“View”(视图)。这将打开可在其中将控件从工具箱拖放到 Web 部件设计器界面的视图。您会注意到有三种视图:设计、拆分和代码。在此示例中,我添加了(通过键入)标题和某些控件(包括文本框和按钮)来计算产品的成本。还为添加到此页的控件键入了标签(请参见图 2)。
完成可视化 Web 部件布局后,可以为按钮添加事件处理程序。不过,在此之前,让我们快速看一下可视化 Web 部件的源代码。从图 3 的代码中可以看到,Visual Studio 将一些自动样式以 CSS 语法的形式添加到 UI。您还可以看到组成 UI 的实际控件(如果是下拉列表,则看到多个项的集合)。请注意,为简便起见,我已经删除了自动生成并包含在源顶部的指令。
要将事件处理程序添加到 Web 部件,可双击按钮。这样将显示后置代码。还将向 ASCX 控件设计添加 onClick 事件。例如,请注意图 3 中包含在 btnCalcPrice 中的 onclick="btnCalcPrice_Click" 事件。图 4 中列出的后置代码包含一些简单代码,借助它们可以计算列表框中选中的产品的价格。此代码的关键部分是类级别的变量(双精度),表示用于计算产品成本的一般方式;产品集合的列表(包含多个添加到列表框的产品对象);以及 btnCalcPrice_Click 事件。在 SharePoint 中加载此页时,此代码将调用用于填充列表框的 generateProductList 方法。btnCalcPrice_Click 事件随后将根据用户所选内容计算特定产品的成本并在 UI 的列表框内显示信息。
图 3 SalaryCalcWebPartUserControl.ascx 的源代码
- <style type="text/css">
- .style1
- {
- font-family: Calibri;
- font-size: medium;
- font-weight: bold;
- }
- .style2
- {
- font-family: Calibri;
- font-size: small;
- font-weight: bold;
- }
- </style>
- <p class="style1">
- Product Catalog</p>
- <p class="style2">
- Product:
- <asp:DropDownList ID="dropdwnProducts"
- runat="server" Height="20px"
- style="margin-left: 21px" Width="200px">
- <asp:ListItem>Helmet</asp:ListItem>
- <asp:ListItem>Stick</asp:ListItem>
- <asp:ListItem>Skates</asp:ListItem>
- <asp:ListItem>Elbow Pads</asp:ListItem>
- <asp:ListItem>Kneepads</asp:ListItem>
- </asp:DropDownList>
- </p>
- <p class="style2">
- Description: <asp:TextBox ID="txtbxDescription" runat="server"
- Width=”200px” Enabled=”False”></asp:TextBox>
- </p>
- <p class="style2">
- SKU:
- <asp:TextBox ID="txtbxSKU" runat="server" style="margin-left: 48px"
- Width="200px" Enabled="False"></asp:TextBox>
- </p>
- <p class="style2">
- Price:<asp:TextBox ID="txtbxPrice" runat="server"
- style="margin-left: 48px"
- Width="200px" Enabled="False"></asp:TextBox>
- </p>
- <p class="style2">
- Quantity:
- <asp:TextBox ID="txtbxQuantity" runat="server"
- Width="200px" Enabled="False"></asp:TextBox>
- </p>
- <p class="style1">
- <asp:Button ID="btnCalcPrice" runat="server"
- onclick="btnCalcPrice_Click"
- Text="Calc." />
- </p>
当用户单击按钮时,Web 部件将实现回发以执行事件 — 此处是计算产品成本。图 4 中的代码实际上相当简单,比此代码更有趣的是 Web 部件在实际 Web 部件中显示此代码的方式。假定我们所做的是为包含皮肤和后置代码的 Web 部件创建 ASP 用户控件,项目结构仍有必须显示此控件的实际 Web 部件。为此,Visual Studio 将创建一个称为 _ascxPath 的字符串,此字符串表示位于 SharePoint 2010 文件夹层次结构内的 ASCX 用户控件的路径。还应注意,在 CreateChildControls 方法中,创建了控件的实例并设置了用户控件的路径(使用 LoadControl 方法)。接着使用 Add 方法将其添加到 Controls 集合中。这使得 Web 部件可以显示 SharePoint 中的 Web 部件内的 ASP 用户控件。图 5 显示了相应代码。
图 4 ProductInfoUserControl.ascx.cs 的源代码
- using System;
- using System;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Collections.Generic;
- using System.Data;
- namespace SampleWebPartProject.ProductInfo
- {
- public partial class ProductInfoUserControl : UserControl
- {
- double tax = .11;
- double totalCost = 0.0;
- List<Products> lstOfProducts = new List<Products>();
- protected void Page_Load(object sender, EventArgs e)
- {
- generateProductList();
- }
- private void generateProductList()
- {
- lstOfProducts.Add(new Products()
- { strName = "Helmet", strDescr = "Hockey helmet.", strSKU =
- "KLSONHELMT1224", dblPrice = 59.00, intQuantity = 28 });
- lstOfProducts.Add(new Products()
- { strName = "Skates", strDescr = "Hockey skates.", strSKU =
- "SKATWOKSH0965", dblPrice = 438.00, intQuantity = 88 });
- lstOfProducts.Add(new Products()
- { strName = "Stick", strDescr = "Composite hockey stick.",
- strSKU = "STIK82910JJKS", dblPrice = 189.99, intQuantity =
- 35 });
- lstOfProducts.Add(new Products()
- { strName = "Elbow Pads", strDescr = "Hockey elbow pads.",
- strSKU = "ELBOP563215NN", dblPrice = 34.00, intQuantity =
- 12 });
- lstOfProducts.Add(new Products()
- { strName = "Knee Pads", strDescr = "Hockey knee pads.",
- strSKU = "KPDS7827NNJS1", dblPrice = 47.99, intQuantity =
- 44 });
- }
- protected void btnCalcPrice_Click(object sender, EventArgs e)
- {
- double dblCost = 0;
- string strPrice = "";
- if (dropdwnProducts.SelectedValue == "Helmet")
- {
- dblCost = lstOfProducts[0].dblPrice;
- totalCost = dblCost + (dblCost * tax);
- System.Math.Round(totalCost, 2);
- strPrice = "$" + totalCost.ToString();
- txtbxDescription.Text = lstOfProducts[0].strDescr.
- ToString();
- txtbxSKU.Text = lstOfProducts[0].strSKU.ToString();
- txtbxPrice.Text = strPrice;
- txtbxQuantity.Text = lstOfProducts[0].intQuantity.
- ToString();
- }
- else if (dropdwnProducts.SelectedValue == "Skates")
- {
- dblCost = lstOfProducts[1].dblPrice;
- totalCost = dblCost + (dblCost * tax);
- System.Math.Round(totalCost, 2);
- strPrice = "$" + totalCost.ToString();
- txtbxDescription.Text = lstOfProducts[1].strDescr.
- ToString();
- txtbxSKU.Text = lstOfProducts[1].strSKU.ToString();
- txtbxPrice.Text = strPrice;
- txtbxQuantity.Text = lstOfProducts[1].intQuantity.
- ToString();
- }
- else if (dropdwnProducts.SelectedValue == "Stick")
- {
- dblCost = lstOfProducts[2].dblPrice;
- totalCost = dblCost + (dblCost * tax);
- System.Math.Round(totalCost, 2);
- strPrice = "$" + totalCost.ToString();
- txtbxDescription.Text = lstOfProducts[2].strDescr.
- ToString();
- txtbxSKU.Text = lstOfProducts[2].strSKU.ToString();
- txtbxPrice.Text = strPrice;
- txtbxQuantity.Text = lstOfProducts[2].intQuantity.
- ToString();
- }
- else if (dropdwnProducts.SelectedValue == "Elbow Pads")
- {
- dblCost = lstOfProducts[3].dblPrice;
- totalCost = dblCost + (dblCost * tax);
- System.Math.Round(totalCost, 2);
- strPrice = "$" + totalCost.ToString();
- txtbxDescription.Text = lstOfProducts[3].strDescr.
- ToString();
- txtbxSKU.Text = lstOfProducts[3].strSKU.ToString();
- txtbxPrice.Text = strPrice;
- txtbxQuantity.Text = lstOfProducts[3].intQuantity.
- ToString();
- }
- else if (dropdwnProducts.SelectedValue == "Knee Pads")
- {
- dblCost = lstOfProducts[4].dblPrice;
- totalCost = dblCost + (dblCost * tax);
- System.Math.Round(totalCost, 2);
- strPrice = "$" + totalCost.ToString();
- txtbxDescription.Text = lstOfProducts[4].strDescr.
- ToString();
- txtbxSKU.Text = lstOfProducts[4].strSKU.ToString();
- txtbxPrice.Text = strPrice;
- txtbxQuantity.Text = lstOfProducts[4].intQuantity.
- ToString();
- }
- }
- }
- }
图 5 ProductInfo.cs 的源代码
- using System;
- using System.ComponentModel;
- using System.Runtime.InteropServices;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using Microsoft.SharePoint;
- using Microsoft.SharePoint.WebControls;
- namespace SampleWebPartProject.ProductInfo
- {
- public class ProductInfo : WebPart
- {
- private const string _ascxPath =
- @"~/CONTROLTEMPLATES/SampleWebPartProject/ProductInfo/" +
- @"ProductInfoUserControl.ascx";
- public ProductInfo()
- {
- }
- protected override void CreateChildControls()
- {
- Control control = this.Page.LoadControl(_ascxPath);
- Controls.Add(control);
- base.CreateChildControls();
- }
- protected override void Render(HtmlTextWriter writer)
- {
- base.RenderContents(writer);
- }
- }
- }
图 6 ProductInfo.webpart XML 文件
- <?xml version="1.0" encoding="utf-8"?>
- <webParts>
- <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
- <metaData>
- <type name="SampleWebPartProject.ProductInfo.ProductInfo,
- SampleWebPartProject, Version=1.0.0.0, Culture=neutral,
- PublicKeyToken=db3a9f914308c42a" />
- <importErrorMessage>
- $Resources:core,ImportErrorMessage;
- </importErrorMessage>
- </metaData>
- <data>
- <properties>
- <property name="Title" type="string">
- Product Info Web Part</property>
- <property name="Description" type="string">Provides some
- information about hockey products.</property>
- </properties>
- </data>
- </webPart>
- </webParts>
现在,您已经构建了可视化 Web 部件,可将其部署到您的 SharePoint 服务器。创建项目后,配置项目,使其与特定服务器实例相关联。此处的含义,是指利用某些编程缝合工作将您刚刚编写的代码与 SharePoint 服务器整合到一起。如果您在 Solution Explorer(解决方案资源管理器)中查看文件,将看到协助此集成的多个 XML 文件。例如,Feature.xml 文件(请参见下列代码)提供功能的定义。在该 XML 文件中您可以看到,该文件引用了其他几个 XML 文件,这些文件同样提供有关 Web 部件的特定信息。在此处,可以看到引用的是 Elements.xml 和 ProductInfo.webpart:
- <?xml version="1.0" encoding="utf-8"?>
- <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
- Id="416172c1-cfa7-4d7a-93ba-fe093b037fab"
- ImageUrl="" Scope="Site" Title="SampleWebPartProject Feature1">
- <ElementManifests>
- <ElementManifest Location="ProductInfo\Elements.xml" />
- <ElementFile Location="ProductInfo\ProductInfo.webpart" />
- </ElementManifests>
Elements.xml 提供有关包含在功能中的核心程序集的信息,ProductInfo.webpart 定义与 Web 部件有关的元数据,例如其标题和说明。例如,图 6 显示了默认 Title 和 Description 属性。您可以更新这些属性以确保在 Web 部件库中公开的 Web 部件元数据直观、有意义。对于本例中这个 Web 部件,您很可能希望将标题修改为产品信息 Web 部件,将说明更改为类似如下的内容,“提供计算的产品定价和信息的 Web 部件”。
图 7Web 部件页面中的 Web 部件
还有其他 XML 配置文件,如果您不熟悉 SharePoint 开发,我鼓励您查看项目中的每个文件以更深入地了解它们的用途。现在,让我们继续完成向您的 SharePoint 服务器部署 Web 部件的过程。
部署可视化 Web 部件项目
在 SharePoint 2010 之前,通常用命令行驱动管理工具 Stsadm 将应用程序部署到 SharePoint。Visual Studio 2010 中不需要使用此工具(并且引入 Windows PowerShell,但此主题值得另写一篇文章来说明)。由于您的项目已与您的 SharePoint 服务器相关联,并且此关联具有已定义的信任级别,因此只需右键单击项目并选择“Build”(构建)以确保解决方案构建,然后右键单击并选择“Deploy”(部署)。当然,调试 SharePoint 解决方案时,使用 F5 键也奏效。执行此操作后,调试体验包括附加到相应的过程和重置 IIS 等步骤。
成功部署 Web 部件后,您需要打开 SharePoint 站点并创建新的 Web 部件页面。如果单击 F5 调试应用程序,默认情况下将调用创建 Web 部件页面。否则,单击“View All Site Content”(查看所有网站内容),然后单击“Create”(创建)。单击“Web Part Page”(Web 部件页面)选项,然后提供请求的关于该特定 Web 部件页面的信息。例如,为此页提供名称和布局模板。输入此信息后,单击“Create”(创建),SharePoint 将创建您的 Web 部件页面。
现在,您需要将创建并部署的可视化 Web 部件添加到服务器。为此,导航到 Web 部件页面,单击“Site Actions”(网站操作),然后单击“Edit Page”(编辑页面)。单击您要在其中放置可视化 Web 部件的 Web 部件区域,单击“Insert”(插入)选项卡,然后单击“Insert”(插入)选项卡上的“Web Part”(Web 部件)。
完成上述操作后,SharePoint 公开多种 Web 部件类别,您可以浏览以选择特定 Web 部件并将其添加到此页中选定的 Web 部件区域。导航到自定义类别,在 Web 部件窗格中,您将看到创建并部署的可视化 Web 部件。如果您采用本文的代码,单击“ProductInfo Web Part”(ProductInfo Web 部件),然后单击“Add”(添加)按钮。
Web 部件现在添加到 Web 部件页面的 Web 部件区域中,如图 7 所示。此时,您可以通过“Tools”(工具)窗格配置 Web 部件选项,也可以只需接受默认选项并单击“Stop Editing”(停止编辑)。
投身于 SharePoint 开发
对于 SharePoint 开发人员,Visual Studio 2010 不仅提供了本机工具套件,还为他们投身于 SharePoint 开发提供了意想不到的机会。我鼓励您了解一下这些工具。对于那些要控制其代码的开发人员,以及那些希望感受在 SharePoint 中构建和部署出色的解决方案设计体验的开发人员,这些工具提供了一些极好的选择。