2009年2月10日,星期二

扩展Web部件框架-第2部分

在第1部分中,我展示了 我们如何实现包含在治理框架中的页面模板和功能模块的“工具箱”,以满足我们客户对灵活的WCM平台的要求,该平台可用于构建80-100个具有不同要求的互联网站点。在这篇文章中,我想详细介绍一些 问题 我们遇到了 决议案 我们发现,主要关注我们开发的“模块框架”,该框架高度围绕SharePoint Web部件。 

快速回顾

客户是一家大型跨国企业,其想法是,在80-100个国家/地区中,内容创作团队将利用我们在MOSS上提供的服务来创建其国家/地区的互联网形象,例如.com,.co.uk,.fr,.es等,以不一致的品牌/外观替换现有的混合技术站点。

就模块框架而言,我们实施的基础是 part 1 有关这些的更完整的详细信息):

  1. 模块矩阵- 规则,指出可在何处使用哪个模块,以指导作者远离那些没有构建的用户体验  'make sense'
  2. 类似于SmartPart的方法,但是具有Web部件属性- Web部件包装用户控件,但也支持在Web部件中公开的Web部件属性 定制工具零件
  3. 基本Web零件/基本工具零件类- 负责“框架”行为,例如检查是否可以添加当前Web部件(根据模块矩阵)
  4. 将发布字段控件的界面与Web部件存储相结合- 由于必须在设计时以“静态”方式添加发布字段控件(例如RichHtmlField),但是我们的作者可以在运行时动态添加控件,因此我们开发了自定义控件,该控件将发布HTML编辑器的丰富功能与Web部件结合在一起存储
  5. WebPartZone的控制适配器,以实现可访问性 -解决由SharePoint的Web部件框架生成的所有HTML表的问题,这将阻止网站验证AA
  6. 仅呈现 我们的 Web部件选择器中的Web部件 -由于在这些网站的任何地方均未使用标准SharePoint Web部件
  7. 编辑Web部件属性(工具部件)时删除不必要的选项 -避免混淆作者

问题和解决方案

我认为,我们面临的许多挑战值得分享,因为它们是通过一般Web部件开发而来的,而不是针对我们所做的任何特定工作。在详细介绍实际问题之前,请注意我们项目的一些关键开发特征:

  • 用于部署工件(例如页面布局,内容类型等)的解决方案和功能。
  • Kivati Studio用于其他一些部署方面
  • 用户控件中实现的主要功能-使用LoadControl(),Web部件实际上是.ascx文件周围的薄包装。
  • 使用“强制”将Web部件添加到页面 AllUsersWebPart 要素中的元素(尽管正如要点所说明的那样,我们研究了处理此问题的多种方式)

发现#1-无法编辑Web部件区域之外的Web部件

我们之所以希望将Web部件放置在区域之外(完全可以通过将Web部件直接拖动到SharePoint Designer中的页面布局标记中来实现)的原因是因为“固定”页面模块无法被内容作者删除。当我们将Web部件放置在Web部件区域之外时,我们发现Web部件可以在演示模式下正常运行,但是不幸的是无法进行编辑(例如,编辑Web部件属性)-该Web部件的编辑菜单根本不出现。我推测这是因为它是网络部分 区域 它们链接到Web部件存储,因此Web部件属性不能在没有区域的情况下持久保存(将始终使用标记中的值)。因此,如果需要可编辑的Web部件,则需要Web部件区域。

解析度 - 确保所有Web部件(甚至无法删除的Web部件)都位于Web部件区域中。

发现#2-将Web部件嵌入到用户控件标记中似乎是有问题的

我们测试了在Web部件区域内外使用Web部件的各种排列,还测试了直接在页面布局.aspx或子.ascx文件中使用HTML标记的情况。确定需要Web部件区域后,我们还发现标记位于.aspx或.ascx中似乎有所不同。这是出乎意料的,但是最终的效果似乎是,如果将Web部件标记插入到用户控件中而不是直接在页面布局.aspx中的Web部件区域中(即,通过重构Web部件的HTML标记)区域及其内容到用户控件中),再次不会显示编辑菜单。我不确定为什么会这样,但可能与页面执行生命周期有关。

解析度 - 接受如果在设计时通过标记将Web部件区域添加到Web部件区域,则Web部件区域声明不能在用户控件中。

发现之三-使用AllUsersWebPart元素时,如果重新激活包含页面布局的功能,则会显示重复的Web部件

确定我们的“固定” Web部件将使用 AllUsersWebPart 功能元素(使用这种方法的NB,“默认” Web部件与部署它们的功能中的页面布局相关联。Web部件区域在页面布局上保留为空,SharePoint在创建时将Web部件置入该区域中版面中的一页)。我们遇到的问题是,现有页面中所有区域中的所有Web部件都将是 重复的 如果页面布局功能被重新激活-这是因为该XML在激活该功能时(以与激活时发生的内容类型置备相同的方式)以及从页面布局创建新页面时都使用。

解析度 - 编写脚本(本例中为Kivati任务)以删除所有站点中重复的Web部件

[更新-Waldek在 “防止在功能重新激活时置备重复的Web部件实例”,以及与我们为脚本编写的代码类似的示例代码。 DOH!]

发现#4-自定义页面布局(重影)时,也会出现重复的Web部件

对于自定义文件为何会导致出现重复的Web部件的原因,我尚不清楚,但这显然是我们似乎能找到的。发生的事情是,我们将使用功能将我们的母版页/页面布局部署到我们的质量检查环境中,但是这些文件将立即在该站点中作为 定制的 (即内容数据库中的内容),而不是在文件系统上未自定义和引用。经过进一步调查,我们将这种意外行为的原因归结为SPD添加到页面布局中的这些属性的使用:

meta:progid=”SharePoint.WebPartPage.Document” meta:webpartpageexpansion=”full”

解析度 - 确保文件版本不包含这些属性。实际上,即使在我们的开发服务器场中,我们也切换到运行未定制的母版页/页面布局。这意味着我们使用功能部署了文件,此后再也没有在SPD中打开它们(仅编辑源代码控制的功能文件)。

发现#5-避免在Web部件定义文件(.webpart)中设置默认属性

我们学到的最后一课是,使用Web部件时,通常最好 避免 广泛使用.webpart定义文件来设置默认属性值。该机制没有错-有效地在页面上配置Web部件时读取这些值,并且您的实例会将其属性设置为这些值。当然,问题在于当您意识到由于某些更改而需要更新在.webpart文件中定义的属性值时。网站周围页面上的所有现有实例将如何处理?您可能会猜到答案是没有的-除非您也采取措施更新它们,这通常意味着编写某种脚本来使用SPLimitedWebPartManager。当您要做的只是快速更改默认值时,这可能会非常不便。

解析度 - 考虑确保将.webpart文件剥离到最低限度(程序集名称等),并且配置来自其他位置。我们通常将这些配置项滚动到我们对 配置存储.


概要

在Web部件框架上构建时,我们遇到了一些意想不到的陷阱,但是可以采取措施将其影响最小化。希望如果进行Web部件开发,这些对您有用。特别感谢Karoly Szalkary帮助我刷新了其中的一些记忆!


附言经过两年的撰写,我决定不再需要在“功能”中使用大写的“ f”-我想我们现在都在同一页面上;-)

2条评论:

杰里米·塔克(Jeremy Thake)说过...

很好的反馈克里斯,我在Web部件方面遇到了类似的痛苦。我倾向于在功能接收器中使用对象模型代码添加我的功能,如果功能被禁用,我也会自己整理一下。可以在 www.sharepointdevwikiwiki.com.

吉姆·谢泼德(Jim Shepherd),幼兽大师说过...

很棒的帖子,我们've还发现,自定义在区域标记内包含Web部件的页面布局还具有将这些Web部件永久嵌入AllWebparts表中的效果。即使您从页面布局中删除Web部件并将页面布局重置为站点定义,也将使用页面布局将它们注入任何页面。那时,从数据库中删除Web部件的唯一受支持方法是在自定义页面布局之前从备份中还原数据库。