最近,我们在生产服务器场遇到了严重的内容类型问题。我想首先解释一下这个问题的背景。
我们为生产和测试服务器场中的内容类型安装提供了良好的工作功能。我们在Visual Studio中开发并部署(使用wsps)此SharePoint功能。我们正在使用publishing pages使用页面布局和内容类型来帮助内容编辑者快速发布网页。遗憾的是,一些内容类型和网站列已由生产中的某些人手动更新/添加,因此每当我(开发人员)对现有内容类型进行一些更改(使用Visual Studio和功能激活/停用)时,SharePoint会删除一个或内容类型中的两列(在功能激活/停用期间);或者没有以最佳实践方式添加的列。我认为最佳做法是使用Visual Studio更新内容类型。
现在,我希望确保在功能激活/停用时不会从内容类型中删除网站列。
注意:我们的内容类型激活/停用功能在feature.xml
中不包含任何激活依赖项答案 0 :(得分:5)
推荐方法
基于所有这些因素,我的建议是:
•创建两个功能:一个用于原始标记,另一个用于进行更改。 (或者你可以把它们放在同一个功能中;我只想区分你做什么。)
•原始功能应包含站点列和内容类型的CAML。这可确保ID已在类型之前分配并保持不变。
•如果要通过更改几乎任何有关它的字段类型来更新站点列,除了字段类型,请使用功能接收器进行更新。通过执行此操作,您可以调用Update方法并传入一个布尔值,指示您是否希望从该站点继承的所有现有资产都更新为(通过CAML无法执行此操作。)
•您还可以将现有站点列(通过CAML功能配置)添加到现有内容类型(通过CAML功能配置)。如果Column之前不是该Content Type的一部分,那么这很有用。
•在我刚才在上一个要点中提到的场景中,在调用功能接收器之前,必须停用CAML功能并设置新的资产(以配置新资产)。这对网站意味着什么?由于站点列表中的所有站点列和内容类型都使用与站点集合根目录中相同的ID,因此从站点集合中删除其父项不会更改它。它可能暂时使其成为孤儿(即,该项目与网站集根目录中的项目之间不存在任何关系,但它将以其始终具有的相同方式运行,因为它实际上是原始项目的完全功能的副本)直到您重新激活将项目放回网站集的功能。这就像父母在停用功能时正在度假,并在您再次激活功能时回家。 您可以选择如何维护CAML和Feature Receiver,因为您有两种方案:现有网站集和新网站集。
•您可以制定一项政策,即每次在功能接收器中编写代码以更新站点列或内容类型时,您都必须在CAML中进行更改。这意味着每次在“新鲜”网站集中激活CAML功能时,CAML都将是最新且准确的;没有必要运行“更新程序”功能。 (在功能接收器中,您应该确保进行一些额外的检查,以确保站点列在添加之前不属于内容类型等,以防在代码执行之前已经存在更改。)这种方法意味着您只需在创建新的网站集时执行一个功能,但这也意味着您要在两个位置维护更改:在功能接收器中对现有网站进行更改,在CAML中为新网站进行更改。这是一种更清洁的方法,但也包含冗余元素,这总是为人为错误留下空间。
•另一种方法是简单地假设每次激活基本CAML功能时,您总是会执行功能接收器。这种方法说,您唯一一次更改CAML就是添加新的站点列或新的内容类型;否则,所有更改都会在Feature Receiver中发生。这种方法可以减少冗余,但也意味着随着时间的推移,您的功能接收器代码会变得非常大,并且随着时间的推移,它可能会使您的CAML成为非常“遗留”。
答案 1 :(得分:1)
更新内容类型仍然是Sharepoint的欠发达部分之一,有时会造成麻烦,尤其是在内容部署方案中。
在您的情况下,最好的办法是始终避免手动对内容类型进行任何更改(使用UI)
每当安装内容类型时,请确保删除上一个内容类型,然后安装新内容类型。 (有时由于页面已经被创建而无法实现)。
答案 2 :(得分:1)
我目前部署内容类型的方法是尽可能使用代码而不是CAML。这样就很容易完全控制更新的逻辑,包括确保手动更改不会导致冲突。我将结构定义为接口上的属性,我也用于强类型列表访问,但还有其他几种方法可以做到。
API中唯一没有的部分是设置一个特定的内容类型ID,所以你需要有一个caml文件,但它是一个小/简单的文件,不会尝试进行更新,是仅从也将运行更新代码的功能引用。