2012年1月19日,星期四

双色球推荐一注PartAdderExtension–部署双色球推荐一注部件的更好方法

最近那个好年轻人 威克多 Wilén 发表于 双色球推荐一注PartAdderExtension 和双色球推荐一注部件库资源–这是SharePoint中鲜为人知的功能(目前尚未记录),它使您能够以不同的方式部署自定义双色球推荐一注部件,从而获得了巨大的好处。总之,SharePoint 2010为您提供了一种方法来指定要在双色球推荐一注部件中显示的双色球推荐一注部件。‘picker’,而无需在本地双色球推荐一注部件库中使用.webpart文件(这是通常的方法)。代码是必需的,但是SharePoint 2010提供了‘hook’供您以以下形式添加 双色球推荐一注PartGallerySourceBase 类。为了帮助可视化,下图中突出显示的双色球推荐一注部件使用 双色球推荐一注PartAdderExtension –它看起来就像一个使用.webpart文件的自定义双色球推荐一注部件,并且用户很高兴没有意识到任何区别:

双色球推荐一注PartAdderExtension_双色球推荐一注PartSelection

我读 威克多’的两篇优秀文章,在最近的项目中,我决定将他的样本扩展到一个模型,该模型在许多情况下都适用。现在,我不’不想太戏剧化,但我认为 双色球推荐一注PartAdderExtension 通常是 大不了的 – I just can’想象不到完全回到制作双色球推荐一注部件的旧方法。在本文中,我们’首先我要回顾一下问题所在,以及为什么这种新方法更好,而我’然后将讨论我的实现以及可以在哪里下载文件。

问题

简而言之,双色球推荐一注部件和双色球推荐一注部件‘gallery’SharePoint中的模型非常好,除非必须更改双色球推荐一注部件的定义以使’已经在那里。通常采用以下形式:

客户:“嘿,我们可以更改标题吗‘foo’网络部分?其实我们想到的那个名字不是’很棒,用户也很棒’t finding it.”
客户:“Hey can we move ‘foo’ web part into a different category? 那’快速更改吧? ”

作为开发人员,您说“Sure, I’ll get right on it!”。但是后来你意识到’部署到每个人’s我的网站。您有成千上万的人。或者也许’在团队网站中,但想起来您也有很多。这很重要,因为双色球推荐一注部件在每个网站集中’的双色球推荐一注部件库(在 .webpart 文件),然后您’必须执行一些操作来迭代每个站点并执行 一些 每一种的处理方式。根据您要处理的站点数量,这可能需要花费大量时间才能运行,并且在运行时会给基础结构带来一定的负载。在我的上一个项目中,通常需要大约7-8个小时来迭代我们拥有的25,000个“我的网站”,并且由于进行处理的服务器和数据库服务器上的负载,我们只能在较长的维护时段内运行它。当然,有25,000个网站’这么大。在大型企业中,我’我什至听说有人编写自定义多线程应用程序来处理此类问题“iterate the sites” scenarios. I’m not saying you won’不需要出于其他原因偶尔执行此迭代,但是如果我们可以从公式中排除一个常见的用例(即,对双色球推荐一注部件定义的更改),那’在我的书中一定要很好。

解决方案

考虑与 双色球推荐一注PartAdderExtension,将这种更改(例如25,000个站点)推出具有以下特征:

  • 无需迭代,因此服务器上没有负载
  • 立即在所有站点生效
  • 根据您的实现,甚至可能不需要回收应用程序池!

这个怎么运作: 双色球推荐一注PartAdderExtension是Feature元素(XML),可以在服务器场/ 双色球推荐一注应用程序/网站集范围内定义(它本身很有趣!)。这个‘points’派生于 双色球推荐一注PartGallerySourceBase 在这里你可以做你喜欢的事– all you have to do is return a collection. Each item in the collection will then appear as a web part in the web part 画廊. 当用户浏览双色球推荐一注部件(在页面编辑模式下)时,将触发您的自定义代码。 在威克多’作为示例,他从SharePoint列表中获取项目,这意味着伪双色球推荐一注部件实际上是列表项目,而不是每个都具有传统的.webpart文件。

 我的实施

威克多’的样本向我完美地传达了原理,但最终我得到了另一个模型。这里’我想出了什么来满足我们的要求:

  • 一系列XML文件,用于定义双色球推荐一注部件 通过网络应用 (例如,用于‘teams’双色球推荐一注部件,用于‘My Site’双色球推荐一注部件等)。
    • N.B.这可能是我们双色球推荐一注部件的本质,但是对于我们来说,双色球推荐一注应用程序绝对是最合适的因素。
  • 读取XML文件的代码‘current’ web application
  • 一个基于双色球推荐一注应用程序的功能,该功能使用 双色球推荐一注PartAdderExtension
    • 实际上,已创建了此功能的多个变体,每个双色球推荐一注应用程序一个。的‘teams’双色球推荐一注部件功能用途 双色球推荐一注PartAdderExtension 指向知道的课程‘teams’ web parts –这反过来从‘teams’ web parts XML file.

因此,而不是维克多’的基于列表的样本’我很高兴在文件系统上使用XML文件–当我们指定可以选择的双色球推荐一注部件时,我们必须指定程序集/类型名称等,由于这在开发人员领域,’我对需要WSP部署来更新此XML感到满意(这些文件位于‘_layouts’)。令人惊讶的是,SharePoint确实没有’t缓存这些数据,因此即使在基于文件的实现中,也不需要回收应用程序池–只需更新WSP(并确保 Reset双色球推荐一注Server = false),更改立即生效。即使DID需要回收,也请记住,这比长时间运行的网站集流程要好几百万倍。

这里’我的XML(自定义架构),用于定义‘teams’双色球推荐一注部件(在我的COB命名空间中在此处使用虚拟双色球推荐一注部件): 

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <双色球推荐一注Parts>
   3:   <双色球推荐一注Part
   4:     Title="My web part for team sites - deployed via 双色球推荐一注PartAdderExtension"
   5:     Category="COB"
   6:     Description="A dummy web part for team sites"
   7:     ID="Teams双色球推荐一注Part1"
   8:     Assembly="COB.SharePoint.双色球推荐一注PartAdderExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=23afbf06fd91fa64"
   9:     Type="COB.SharePoint.双色球推荐一注PartAdderExtension.Teams双色球推荐一注Part1.Teams双色球推荐一注Part1"
  10:     IconUrl="_layouts/images/webpart.gif"
  11:     RibbonCommand=""
  12:     OnClientAdd=""
  13:     />
  14:   <双色球推荐一注Part
  15:   Title="My second web part for team sites - deployed via 双色球推荐一注PartAdderExtension"
  16:   Category="COB"
  17:   Description="Another dummy web part for team sites"
  18:   ID="Teams双色球推荐一注Part2"
  19:   Assembly="COB.SharePoint.双色球推荐一注PartAdderExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=23afbf06fd91fa64"
  20:   Type="COB.SharePoint.双色球推荐一注PartAdderExtension.Teams双色球推荐一注Part2.Teams双色球推荐一注Part2"
  21:   IconUrl="_layouts/images/webpart.gif"
  22:   RibbonCommand=""
  23:   OnClientAdd=""
  24:     />
  25: </双色球推荐一注Parts>

然后,我们需要一些代码来使用它。如前所述,这必须是派生自 双色球推荐一注PartGallerySourceBase –因为我的实现是‘每个双色球推荐一注应用程序的XML文件’,我创建了一个基本类,可以理解我的XML模式,然后创建了每个双色球推荐一注应用程序的派生类。它’后一个类,它知道在哪里可以找到XML文件:

0: [Guid("98FF0ED8-6697-4E13-8BCC-161FEE3E4B0C")]
1: public class Global双色球推荐一注PartGallerySource_Teams : Global双色球推荐一注PartGalleryXmlSource

   2: {
   3:     public Global双色球推荐一注PartGallerySource_Teams(Page page)
   4:         : base(page)
   5:     {
   6:     }
   7:  
   8:     public override string XmlPath
   9:     {
  10:         get
  11:         {
  12:             string path = SPUtility.GetGenericSetupPath(@"template\layouts\COB.SharePoint.双色球推荐一注PartAdderExtension\Global双色球推荐一注Parts\Global双色球推荐一注Parts_Teams.xml");
  13:             return path;
  14:         }
  15:     }
  16: }

..和基类简单地从选定的XML文件中读取并返回( Global双色球推荐一注PartGalleryItem 我的情况–重要的是它源自 双色球推荐一注PartGalleryItemBase):

   1: public class Global双色球推荐一注PartGalleryXmlSource : 双色球推荐一注PartGallerySourceBase
   2: {
   3: public Global双色球推荐一注PartGalleryXmlSource(Page page)
   4:     : base(page)
   5: {
   6: }
   7:  
   8: public virtual string XmlPath
   9: {
  10:     get
  11:     {
  12:         return string.Empty;
  13:     }
  14: }
  15:  
  16: protected override 双色球推荐一注PartGalleryItemBase[] GetItemsCore()
  17: {
  18:     List<双色球推荐一注PartGalleryItemBase> items = new List<双色球推荐一注PartGalleryItemBase>();
  19:     string path = XmlPath;
  20:  
  21:     if (File.Exists(path))
  22:     {
  23:         XElement root = XElement.Load(path);
  24:         var webParts = from wpDef in root.Elements("双色球推荐一注Part")
  25:                         select wpDef;
  26:  
  27:         foreach(XElement wp in webParts)
  28:         {
  29:             string title= wp.Attribute("Title").Value;
  30:             string category = wp.Attribute("Category").Value;
  31:             string description = wp.Attribute("Description").Value;
  32:             string iconUrl = wp.Attribute("IconUrl").Value;
  33:             string id = wp.Attribute("ID").Value;
  34:             string ribbonCommand = wp.Attribute("RibbonCommand").Value;
  35:             string onClientAdd = wp.Attribute("OnClientAdd").Value;
  36:             string assembly = wp.Attribute("Assembly").Value;
  37:             string typeName = wp.Attribute("Type").Value;
  38:  
  39:             items.Add(new Global双色球推荐一注PartGalleryItem(this, base.Page, title, category, description, iconUrl, id, assembly, typeName, onClientAdd, ribbonCommand));
  40:         }
  41:     }
  42:  
  43:     return items.ToArray();
  44: }

链接我的关键 Global双色球推荐一注PartGallerySource_Teams 我上面的课‘teams’网络应用程序是网络应用程序范围内的功能,具有以下元素:

   1: <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 
   2:   <双色球推荐一注PartAdderExtension 
   3:       Assembly="$SharePoint.Project.AssemblyFullName$" 
   4:       Class="$SharePoint.Type.98ff0ed8-6697-4e13-8bcc-161fee3e4b0c.FullName$"/> 
   5: </Elements>

注意我’m使用令牌化支持通过GUID属性引用我的类’s decorated with. 注意 –使用此类令牌时,GUID *必须*为小写(我不告诉你)。这只是Feature / VS模式中的两个地方之一’我知道哪个有此要求。

还有我’ll让您陷入一个小秘密,并说我的实现中有几行反射代码 Global双色球推荐一注PartGalleryItem –这对于将标题保留给 已添加到页面的双色球推荐一注部件实例。 完全可选,但是由于这在双色球推荐一注服务器流量的宏伟方案中很少发生,因此它’恕我直言,获得一致的用户体验是完全值得的。

最后,将双色球推荐一注部件添加到页面的行为正是用户所期望的。如果您下载我的样本(本文末尾的链接),请点击此处’s如下所示:

双色球推荐一注PartAdderExtension_TeamSites双色球推荐一注Part

不需要的XML(必须从VS项目中手动删除)

It’在这里值得指出的是,您必须从项目中明确删除项目才能使用此方法。请记住,Visual Studio / CKS:Dev只知道‘regular’开发双色球推荐一注部件的方式以及您选择的方式‘Add New Item> Visual 双色球推荐一注 Part’,项目将添加到您不再需要的项目中–具体来说,这是.webpart文件和elements.xml文件,它们将其提供给双色球推荐一注部件库。一世’ve not tested, but I’d假定您收到错误消息,或者如果忘记删除这些错误消息,则假定重复出现。为了清楚起见,它’s these:

将双色球推荐一注部件添加到项目时,Elements.xml(由Visual Studio自动添加):

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <!-- DO NOT USE - THIS XML IS NO LONGER NEEDED WHEN USING WEBPARTADDEREXTENSION -->
   3: <Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
   4:   <Module Name="MySites双色球推荐一注Part1" List="113" Url="_catalogs/wp">
   5:     <File Path="MySites双色球推荐一注Part1\MySites双色球推荐一注Part1.webpart" Url="MySites双色球推荐一注Part1.webpart" Type="GhostableInLibrary" >
   6:       <Property Name="Group" Value="Custom" />
   7:     </File>
   8:   </Module>
   9: </Elements>

MySites双色球推荐一注Part1.webpart:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <!-- DO NOT USE - THIS XML IS NO LONGER NEEDED WHEN USING WEBPARTADDEREXTENSION -->
   3: <webParts>
   4:   <webPart xmlns="http://schemas.microsoft.com/双色球推荐一注Part/v3">
   5:     <metaData>
   6:       <type name="COB.SharePoint.双色球推荐一注PartAdderExtension.双色球推荐一注Parts.MySites双色球推荐一注Part1.MySites双色球推荐一注Part1, $SharePoint.Project.AssemblyFullName$" />
   7:       <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
   8:     </metaData>
   9:     <data>
  10:       <properties>
  11:         <property name="Title" type="string">My web part title</property>
  12:         <property name="Description" type="string">My web part description</property>
  13:       </properties>
  14:     </data>
  15:   </webPart>
  16: </webParts>

然后’s it.

概要

尽管使自定义双色球推荐一注部件可用的旧方法已经工作了很多年,但这并没有’t mean it’的效果很好!原来在那里’我认为具有更好特征的替代方案–如果您需要对网站集进行更改,则无需再遍历每个网站集 定义 已经存在的双色球推荐一注部件的一部分。当我向客户提到我’d将这种新方法用于我们最新的双色球推荐一注部件,响应是“哇。我认为我们应该返回并将所有自定义双色球推荐一注部件切换到该模型。”我认为Wictor引起了人们的关注,但引起了人们的赞誉。– I’我只是为蛋糕锦上添花:)

下载链接

下载 my 双色球推荐一注PartAdderExtensionsample project

4条评论:

布赖恩 said...

是的,这是他们使用Microsoft.SharePoint.Meetings.MeetingsListGallerySource(内部/密封)在会议工作区中执行的操作。

围绕为什么和如何写好!

杰森说过...

爱这个兄弟。打的好。

致命性的说过...

嘿克里斯,

这如何影响在页面中配置双色球推荐一注part?我认为AllUsers双色球推荐一注Part方法可能是不行吗?

谢谢,

贾斯汀

克里斯·奥'Brien说过...

嘿贾斯汀,

那'一个好问题:)我还没有'我尝试了AllUsers双色球推荐一注Part和双色球推荐一注PartAdderExtension的组合,但实际上我不会'不要指望任何问题。考虑到AllUsers双色球推荐一注Part在声明性XML中采用字符串ID-.webpart文件和双色球推荐一注PartAdderExtension都要求您指定此字符串。

还有 '完全有可能使用AllUsers双色球推荐一注Part将ListView双色球推荐一注Part设置到页面上,而这些出现在画廊中是由某些Microsoft代码提供的,这些代码实际上使用了相同的方法(即'的双色球推荐一注PartGallerySource)。

所以我可以't imagine there'd是任何问题,但我'd喜欢听到任何发现这是't the case.

干杯,

C。