更新 SharePoint 中的外接程序 Web 组件

更新加载项 Web 组件的先决条件:

更新加载项 Web 中的 SharePoint 组件

所有部署到加载项 Web 的 SharePoint 组件都包含在加载项包的 Web 范围功能中。 因此,更新这些组件实际上是更新一个或多个这样的功能。 自 SharePoint 2010 起,此过程并未改变,收录在 SharePoint 2010 SDK 中的向现有功能中添加元素内。

升级功能节点中的其他文章可能也会有所帮助,但鉴于加载项不得包含在 SharePoint 服务器上运行的自定义代码,因此在 SharePoint 2010 中功能升级的某些方面与更新加载项并不相关。例如,升级 SharePoint 加载项的功能时,不能使用 CustomUpgradeAction 元素。

能和不能以声明方式执行的操作

在 SharePoint 托管加载项中,只能使用 XML 标记更新加载项;对于如何在更新过程中以声明方式更改加载项,还需要遵循一些限制。 在提供程序托管加载项中,可以实现 UpdatedEventEndpoint 处理程序,执行不能以声明方式完成的操作。

向加载项添加组件很简单。 加载项中可以包含的所有组件也都能在更新过程中进行添加(有关详细信息,请参阅 SharePoint 加载项中可以包含的 SharePoint 组件类型)。 不过,若要以声明方式修改现有组件,请注意以下几点。

  • 初始部署后,在任何情况下都不能更改列表或内容类型字段(列)的数据类型。 特别是,请勿在加载项更新过程中更改字段的数据类型(更不能以编程方式更改)。 作为备选方法,也可以添加新字段。 如果加载项包含自定义项创建、编辑或查看表单,请务必在这些表单中进行相应的更改。 例如,添加新字段的 UI,并删除旧字段的 UI。 (在提供程序托管加载项中,可以编程方式将旧字段中的数据移到新字段中,然后再删除旧字段。)

  • 不能在更新标记中删除列表、列表实例、内容类型或字段。

  • 不能在更新标记中从外接程序 Web 删除文件。 但是,您可以更改任何文件的内容。

  • 更新 SharePoint 外接程序时不能使用 CustomUpgradeActionMapFile 元素,尽管它们在 Visual Studio 智能感知中可能显示为可用。

首次更新外接程序 Web

本部分中的过程说明了如何添加或更新外接程序 Web 中的内容类型、列表、文件和其他 SharePoint 组件。 为简单起见,我们假定所有组件都是外接程序 Web 单个功能的一部分,但是外接程序 Web 可以有多个功能,您可以在同一更新中更新多个功能。

Microsoft Visual Studio 的 Office 开发人员工具旨在新建加载项,而且此工具的默认行为有时也并非更新加载项时的理想之选。 为了能够更好地控制此过程,应先按照下面的过程操作,禁用功能设计器,以便可以直接编辑原始功能 XML。

编辑功能 XML 的具体步骤

  1. 在“解决方案资源管理器”中,打开 {FeatureName}.features 文件。 此文件在功能设计器中打开。

  2. 打开“清单”选项卡,并展开“编辑选项”

  3. 选择“覆盖生成的 XML,并在 XML 编辑器中编辑清单”

  4. 在提示禁用设计器的对话框中,选择“是”

  5. 在打开的视图中,选择“在 XML 编辑器中编辑清单”。 此时,{FeatureName}.Template.xml 文件打开。

图 1. 打开 Feature XML 编辑器

用于打开功能 XML 编辑器的步骤

谨慎

请勿将 "<!-- -->" 注释添加到 {FeatureName}.features 文件。 升级基础结构不支持注释。如果文件中有注释,升级将会失败。 本文中的标记示例使用注释只是为了指明标记应在的位置。

首次更新加载项 Web 功能的具体步骤

  1. 如果在加载项清单中递增了版本号,但 Visual Studio 的 Office 开发人员工具尚未这样做,递增 Feature 元素的 Version 属性(此工具不会在所有方案中都这样做,所以需要进行验证)。

    应对功能使用与加载项相同的版本号。 如果加载项的其他组件更新,而不是加载项 Web 功能本身更新,也应考虑递增功能版本。 如果加载项版本和功能版本始终相同,那么 VersionRange 元素的逻辑(加载项 Web 的后续更新部分中进行了介绍)管理起来就更容易。

  2. 请勿从文件的 ElementManifests 部分中删除任何内容。 此部分中的所有内容从未遭删除。

  3. 向文件添加以下元素(如果还没有它们的话):

    • Feature 元素的 UpgradeActions 子元素。 请向此元素添加 ReceiverAssemblyReceiverClass 属性。 这些属性对更新 SharePoint 加载项没有任何用处。 (这些属性引用 SharePoint 加载项不支持的自定义程序集。如果在加载项中添加自定义程序集,SharePoint 就不会安装加载项。)

    • UpgradedActions 元素的 VersionRange 子元素。 请勿向此元素添加 BeginVersionEndVersion 属性。 当加载项首次更新时,这些属性毫无用处。 加载项 Web 的后续更新部分中介绍了这些属性的用途。

    • VersionRange 元素的 ApplyElementManifests 子元素。

此时,文件应如下面的示例所示。

重要

Visual Studio 的 Office 开发人员工具可能已添加上述标记,并将 ElementManifests 部分中的一些元素复制到了 ApplyElementManifests 部分,以作举例说明之用。 请删除这些内容。 尽管最终可能会在后续步骤中重新添加其中部分内容,但从空的 ApplyElementManifests 部分入手更为容易和安全。 未变化的组件的冗余项会带来不良后果,包括可能会延长更新过程,导致更新超时和失败。

 <Feature <!-- Some attributes omitted --> 
                Version="2.0.0.0">
   <ElementManifests>
     <!-- ElementManifest elements omitted -->
   </ElementManifests>
   <UpgradeActions>
    <VersionRange>
      <ApplyElementManifests>

      </ApplyElementManifests>
    </VersionRange>
   </UpgradeActions>
 </Feature>

向加载项添加组件的具体步骤

  1. 向功能添加任何新组件,完全就像新建 SharePoint 加载项项目一样。

  2. 如果添加旧版加载项中没有的组件类型(如将列表添加到以前没有列表的加载项),Visual Studio 的 Office 开发人员工具便会在项目中添加 elements.xml 文件。 这是组件的元素清单。 应将加载项的新版本号添加到此文件中(例如,elements.2.0.0.0.xml)。 这样可有助于排查问题。 请务必在“解决方案资源管理器”中执行更改,以确保对文件的引用(如在 csproj 文件和功能 XML 中)也会随之更改。

  3. 对于每个新元素清单,将 ElementManifest 元素作为子元素同时添加到功能 XML 的 ElementManifestsApplyElementManifests 元素(在这两处添加的 ElementManifest 元素要完全相同)。 此元素的 Location 属性应指向 elements.2.0.0.0.xml 文件的相对路径。 例如,如果添加了名为 MyCustomList 的列表,ElementManifest 元素如下所示:

      <ElementManifest Location="MyCustomList\elements.2.0.0.0.xml" />
    
  4. 一些类型的组件会向项目添加文件。 例如,如果添加列表,将会创建 schema.xml 文件;如果添加页面,将会创建页面文件。 对于每个这样的文件,将 ElementFile 元素作为子元素添加到 ElementManifests 元素(请勿添加到 ApplyElementManifests 元素)。 Location 属性应指向文件的相对路径。 例如,如果添加了列表,schema.xml 的 ElementFile 元素如下所示:

      <ElementFile Location="MyCustomList\Schema.xml" />
    
  5. 如果再添加旧版加载项中已有的项类型,Visual Studio 的 Office 开发人员工具可以向现有元素清单添加对新项的引用(而不用新建清单)。 例如,向加载项 Web 添加页面的标准方法是,右键单击“解决方案资源管理器”中的“页面”节点,再依次转到“添加”>“新项”>“页面”>“添加”。 Visual Studio 的 Office 开发人员工具会在现有元素清单文件(通常称为 elements.xml)中,向“Pages”模块添加新 File 元素,而不是新建元素清单。

    这并非期望的结果。 最佳做法是在更新外接程序时尽可能避免编辑任何现有的元素清单文件(即,外接程序之前版本的任何元素清单)。 通常情况下,新项目应位于新的元素清单文件中(这些文件本身在 Feature XML 的 ApplyElementManifests 元素中引用。 (稍后将介绍此做法的一些例外情况。) 例如,若要添加新页面,请执行以下步骤:

    1. 新建一个名为“Pages.2.0.0.0”的模块。

    2. 从中删除 Visual Studio 的 Office 开发人员工具自动添加的 sample.txt 文件。

    3. 将新模块中的元素清单重命名为“elements.2.0.0.0.xml”

    4. 右键单击“Pages.2.0.0.0”模块,再依次转到“添加”>“新项”>“页面”>“添加”。 此时,新页面创建完成,并在 Pages.2.0.0.0(而不是 Pages)的元素清单中获得引用。

    5. 确保 Feature XML 的 ElementManifests 元素中具有新页面的 ElementsFile 元素,并确保 ElementManifestsApplyElementManifests 部分中具有 elements.2.0.0.0.xml 文件的 ElementManifest 元素。

      如果 Visual Studio 的 Office 开发人员工具已更改现有元素清单,在任何情况下,都还可以使用另一种方法,即手动新建 elements.2.0.0.0.xml 文件,并将已添加到旧清单的标记移到新清单中(如果需要,新清单可以与旧清单位于同一“解决方案资源管理器”节点中。)

  6. 如果在功能中向内容类型添加字段,请将 AddContentTypeField 元素添加到 VersionRange 部分中。 请务必向 ContentTypeIdFieldId 属性分配正确的值。 根据需要使用 PushDown 属性,指定是否应将新字段添加到派生的任何内容类型。 示例如下。

     <VersionRange>
       <AddContentTypeField 
         ContentTypeId="0x0101000728167cd9c94899925ba69c4af6743e"
         FieldId="{CCDD361F-A3FB-40D8-A272-3A3C858F4116}"
         PushDown="TRUE" />
       <!-- Other child elements of VersionRange -->
     </VersionRange>
    

修改加载项的现有组件的具体步骤

如果更改了元素清单文件中引用的文件(如 Default.aspx 文件),根本无需更改此文件的 ElementFile 元素。 不过,确实需要指示更新基础结构,使用新版文件替换旧版文件。 为此,请将模块的 ElementManifest 元素添加到 ApplyElementManifests 部分中。

由于 ElementManifests 部分中已有此类元素,因此直接将它复制(而不是移动)到 ApplyElementManifests 有时也不失为一种办法,但只有在清单中引用的每个文件都已改变的情况下,才建议采用这种方法。 按照一般做法,不得将没有变化的文件替换为它本身的副本。 在某些情况下,这样做可能会带来不良后果。 例如,如果页面已配置为支持用户自定义它,替换页面可能会撤消自定义。 (如果已更改页面,则不得不接受这样的后果,但并不希望也给客户造成这样毫无意义的不便)。

  1. 为了确保只替换模块中的已更改文件,请为模块再创建一个仅引用已更改文件的元素清单,并在 ApplyElementManifests 中应用第二个清单,具体步骤如下:

    1. 右键单击“解决方案资源管理器”中的模块节点,并添加名为“elements.2.0.0.0.xml”的 XML 文件(而不是页面)。

    2. 在“解决方案资源管理器”中选择新文件,调出其属性窗格,并将“部署类型”属性更改为“ElementManifest”。 对于确保 Visual Studio 的 Office 开发人员工具能够正确处理文件,这一点至关重要。

    3. 将原始清单的内容复制到新清单中,再从新清单中删除与更改文件对应的所有 File 元素。

    4. ElementManifest 元素添加到引用新清单文件的 ApplyElementManifests 部分中,如下面的示例所示。

            <ElementManifest Location="Pages\elements.2.0.0.0.xml" />
      

      注意

      请勿删除原始清单。 功能 XML 同时使用新旧两个版本的清单。 不要将任何 ElementFile 元素从 ElementManifests 部分复制到 ApplyElementManifests 部分,即使 ElementFile 中引用的文件已更改也是如此。

  2. 打开 ApplyElementManifests 部分中引用的每个元素清单文件,并确保所有 File 元素的 ReplaceContents 属性都已设置为 TRUE

    示例如下。 虽然 Visual Studio 的 Office 开发人员工具可能已完成此操作,但应进行验证。 甚至也要对旧版加载项中的元素清单这样做。 这是编辑现有元素清单文件的为数不多的好方法之一。

     <Module Name="Pages">
       <File Path="Pages\Default.aspx" Url="Pages/Default.aspx" ReplaceContent="TRUE" />
     </Module>
    
  3. 可以在页面中嵌入 Web 部件,如在加载项 Web 的网页中添加 Web 部件中所述。 如果更改包含 Web 部件的页面(或更改 Web 部件的属性),还需要执行下列额外步骤:必须将以下标记添加到页面,以防 SharePoint 向页面添加 Web 部件的第二个副本。 标记应该已被添加到 asp:Content 元素,ID 为 PlaceHolderAdditionalPageHead。 (虽然 Visual Studio 的 Office 开发人员工具可能已在页面首次创建时添加了此标记,但应验证其中是否有此标记)。

      <meta name="WebPartPageExpansion" content="full" />
    

    注意

    如果页面已配置为支持用户自定义它,此标记的缺点是会撤消这些自定义。 用户不得不重复进行此操作。 如果已按照在加载项 Web 的网页中添加 Web 部件中的说明操作,将 Web 部件添加到页面,那么 Web 部件标记就位于元素清单中,因此更改 Web 部件的属性是个例外,无需遵循不得在加载项更新过程中编辑元素清单文件的一般规则。

  4. 作为更改页面的备选方法,还可以根据需要重定向到新页面,具体步骤如下:

    1. 新建页面并配置更新标记,如上面的向加载项添加组件的具体步骤过程中所述。

    2. 打开旧页面,并从 ID 为 PlaceHolderAdditionalPageHeadasp:Content 元素中删除所有标记。

    3. 将以下标记添加到 asp:Content 元素,再将 {RelativePathToNewPageFile} 替换为新的路径和文件名。 下面的脚本将浏览器重定向到新页面,并添加查询参数。 它还将旧页面从浏览器历史记录中删除。

       <script type="text/javascript">
             var queryString = window.location.search.substring(1);
             window.location.replace("{RelativePathToNewPageFile}" + "?" + queryString);
       </script>
      
    4. 删除页面上的其他任何 asp:Content 元素。

    5. 如果您要替换的页面是外接程序的起始页面,请将外接程序清单中的 StartPage 元素更改为指向新页面。

  5. 如果加载项的加载项 Web 包含 CustomActionClientWebPart,并且在更新过程中修改它,那么必须修改元素清单,因为其中定义了这些组件。 (这是个例外,无需遵循不得在更新加载项时编辑旧版加载项的元素清单的一般规则。)还必须将 ElementManifest 元素从 ElementManifests 部分复制(而不是移动)到 ApplyElementManifests 部分。

首次升级加载项时的功能 XML 示例

下面的示例展示了首次更新加载项时的完整 {FeatureName}.Template.xml 文件。 此示例中更新的加载项修改了 Pages\Elements.xml 文件中引用的 Default.aspx 文件,并部署了 Scripts\Elements.xml 文件中引用的三个新 jQuery 文件。 请注意,所有 ElementFile 实例都是位于 ElementManifests 部分中,且 <ElementManifest Location="Pages\Elements.xml" /> 已从 ElementManifests 部分复制(而不是移动)到 ApplyElementManifests 部分中。

 <Feature xmlns="http://schemas.microsoft.com/sharepoint/" Title="MyApp Feature1" 
       Description="SharePoint Add-in Feature" Id="85d309a8-107e-4a7d-b3a2-51341d3b11ff" 
       Scope="Web" Version="2.0.0.0">
   <ElementManifests>
     <ElementFile Location="Pages\Default.aspx" />
     <ElementManifest Location="Pages\Elements.xml" />
     <ElementFile Location="Content\App.css" />
     <ElementManifest Location="Content\Elements.xml" />
     <ElementFile Location="Images\AppIcon.png" />
     <ElementManifest Location="Images\Elements.xml" />
     <ElementFile Location="Scripts\jquery-3.0.0.intellisense.js" />
     <ElementFile Location="Scripts\jquery-3.0.0.js" />
     <ElementFile Location="Scripts\jquery-3.0.0.min.js" />
   </ElementManifests> 
   <UpgradeActions>
       <VersionRange>      
         <ApplyElementManifests>
           <ElementManifest Location="Pages\Elements.xml" />
           <ElementManifest Location="Scripts\elements.2.0.0.0.xml" />
         </ApplyElementManifests>
       </VersionRange>
   </UpgradeActions>
 </Feature>

加载项 Web 的后续更新

第二次(或第三次,以此类推)更新 SharePoint 加载项时,必须考虑到一些客户可能还未进行上一次更新。 因此,在最新更新已部署到组织的加载项目录或 Office 应用商店后,如果用户响应“有可用更新”提示,加载项实例可能会在一次更新过程中更新多个版本。

这多半正是应发生的事情,即希望所有旧版加载项都更新到最新版本。 不过,并不一定希望对加载项的所有实例重复执行加载项 Web 功能的每个更新操作。 有一些更新操作不得对给定加载项实例多次执行。 例如,如果在一次更新中向内容类型添加了字段,则不希望在下一次更新中又添加此字段。 下面的过程介绍了如何使用 VersionRange 元素,根据要更新的功能版本控制要执行的更新操作。

在后续更新过程中更改加载项 Web 功能的具体步骤

  1. 如本文前面的编辑功能 XML 的具体步骤过程所述,打开 FeatureName.Template.xml 文件进行编辑,并递增 Feature 元素的 Version 属性。 应对功能使用与加载项相同的版本号。

    在接下来的示例中,假设之前是将加载项从版本 1.0.0.0 更新到版本 2.0.0.0,现在要将加载项更新到版本 3.0.0.0。所以,将 Version 属性设置为 3.0.0.0。

  2. 在现有所有 VersionRange 元素下添加一个新元素 VersionRange。 请向此元素添加 BeginVersionEndVersion 属性。

  3. 按照本文前面的首次更新加载项 Web 功能的具体步骤过程所述,填充 VersionRange 元素,以考虑对此更新后版本功能所做的更改。 只要此过程引用 ApplyElementManifests 部分,就视为引用的是刚刚添加的 VersionRange 元素的子元素 ApplyElementManifests,即功能 XML 文件中的最低一级。

  4. 转到旧 VersionRange 元素(在接下来的示例中,这是指上次将加载项从 1.0.0.0 更新到 2.0.0.0 时添加的元素),并向此元素添加 EndVersion 属性。 建议将此 VersionRange 中的升级操作应用于尚未应用这些操作的任何加载项版本(版本 1.0.0.0),但不建议向已应用这些操作的版本(版本 2.0.0.0)重复应用。 EndVersion不含界限值,所以将它设置为希望对其应用升级操作的最低版本。 在接下来的示例中,将它设置为“2.0.0.0”。 文件应如下所示。

    <Feature <!-- Some attributes omitted --> 
                   Version="3.0.0.0">
      <ElementManifests>
        <!-- ElementManifest elements omitted -->
      </ElementManifests>
      <UpgradeActions>
        <VersionRange EndVersion="2.0.0.0">
          <!--  Child elements for upgrade from 1.0.0.0 to 2.0.0.0 go here. -->
        </VersionRange>
        <VersionRange>
          <!--  Child elements for upgrade from 2.0.0.0 to 3.0.0.0 go here. -->
        </VersionRange>
      </UpgradeActions>
    </Feature>
    

    每次升级功能时,都请遵循同一模式。 为最新的更新操作添加新的 VersionRange。 将 EndVersion 元素添加到 以前的VersionRange 元素,并将其设置为以前的版本号。 在接下来的示例中,从 3.0.0.0 更新到 4.0.0.0 时的文件应如下所示。

    <Feature <!-- Some attributes omitted --> 
                    Version="4.0.0.0">
      <ElementManifests>
        <!-- Child elements omitted -->
      </ElementManifests>
      <UpgradeActions>
        <VersionRange EndVersion="2.0.0.0">
            <!-- Child elements for upgrade from 1.0.0.0 to 2.0.0.0 go here. -->
        </VersionRange>
        <VersionRange EndVersion="3.0.0.0">
            <!-- Child elements for upgrade from 2.0.0.0 to 3.0.0.0 go here. -->
        </VersionRange>
        <VersionRange>
            <!-- Child elements for upgrade from 3.0.0.0 to 4.0.0.0 go here. -->
        </VersionRange>
      </UpgradeActions>
    </Feature>
    

    请注意,最新的 VersionRange 元素没有 BeginVersionEndVersion 属性。 这样可以确保涉及此 VersionRange 元素的升级操作应用于功能所有之前的版本,这正是您希望的,因为所有最新更改都会在此 VersionRange 中引用,并且任何功能实例都未发生这些更改。

    另请注意,所有 VersionRange 实例都没有使用 BeginVersion 属性。 这是因为 BeginVersion 属性的默认值为 0.0.0.0,这也是所需的值,因为需要将所有升级操作都应用于低于 EndVersion 属性中指定版本的全部加载项实例。

    重要

    VersionRange 元素只确定向哪些功能版本应用升级操作。 并不确定哪些版本的加载项会收到通知“有可用更新”(此通知仅由加载项版本号触发)。 在组织的加载项目录或 Office 应用商店中发布新版加载项的 24 小时内,已安装的所有加载项实例(无论版本如何)在“网站内容”页上的磁贴中都会显示通知“有可用更新”。 VersionRange 不会影响新升级的功能或新更新的加载项的新版本号。 这两种版本号始终都会更改为最新版本号,无论在升级前功能所处的版本范围是什么。

    这是不使用 BeginVersion 属性的另一个充分理由。 BeginVersion 属性可用于阻止对某些加载项实例应用一些升级操作。 但它无法阻止功能或加载项版本升至最新版本。 因此,使用 BeginVersion 属性可能会导致加载项的两个实例具有相同的加载项版本号和加载项 Web 功能版本号,但加载项 Web 中的组件却不同。

验证加载项 Web 组件的部署

请按照以下步骤验证外接程序 Web 功能及其组件的部署。

验证加载项 Web 预配情况的具体步骤

  1. 打开主机 Web 的“网站设置”页。 在“网站集管理”部分中,选择“网站层次结构”链接。

  2. 在"网站层次结构"页上,您会看到按其 URL 列出的外接程序 Web。 不要启动它。 相反,请复制该 URL 并在其余步骤中使用该 URL。

  3. 转到 URL_of_app_web/_layouts/15/ManageFeatures.aspx,并在打开 的“网站功能 ”页上,验证该功能是否是按字母顺序排列的功能列表的成员,并且其状态是否为 “活动”。

  4. 如果外接程序 Web 功能包含自定义网站栏,请打开 URL_of_app_web/_layouts/15/mngfield.aspx,然后在打开 的“网站栏” 页上,验证是否已列出新的自定义网站栏。

  5. 如果外接程序 Web 功能包含任何自定义内容类型,请打开 URL_of_app_web/_layouts/15/mngctype.aspx,并在打开 的“网站内容类型” 页上验证是否已列出新的内容类型。

  6. 对于每个自定义内容类型,以及已向其中添加了列的所有内容类型,选择内容类型链接。 在随即打开的“网站内容类型”页上,验证内容类型是否包含应有的网站列。

  7. 如果外接程序 Web 功能包含任何列表实例,请打开 URL_of_app_web/_layouts/15/mcontent.aspx,并在打开 的“网站库和列表 ”页上,验证每个自定义列表实例是否有 自定义“name_of_list” 链接。

  8. 对于每个自定义列表实例,选择“自定义‘name_of_list’”链接,并在列表设置页上验证列表是否包含应有的内容类型和列。

    注意

    如果此页上没有“内容类型”部分,必须启用管理内容类型。 请选择“高级设置”链接。在“高级设置”页上,启用管理内容类型,再选择“确定”。 此时,将返回到上一页,现在就可以看到“内容类型”部分的列表了。

  9. 页面顶部附近是列表的“Web 地址”。 如果在列表实例定义中添加了示例项,请将地址复制并粘贴到浏览器的地址栏,再转到列表。 验证列表是否包含已创建的示例项。

后续步骤

请返回到更新加载项的主要步骤,或直接转到以下文章之一,了解如何更新 SharePoint 加载项的下一个主要组件。

另请参阅