6

我有一个网站内容类型,用于整个网站集中的少数列表。在那种内容类型中,我描述了一个事件接收器来处理ItemAdding事件。这工作正常。现在我需要更新内容类型,以便处理ItemUpdating。 OTTOMH,我试着简单地修改我的内容类型的xml,因为这似乎允许简单的版本跟踪。这在我的更新适用于网站内容类型的意义上,但不适用于使用此内容类型的我的列表。这是预料之中的。然后,我注意到,在SharePoint SDK采取的一个grim view更新已部署的SharePoint内容类型以处理其他项目事件

在任何情况下,你应该安装 和激活的内容 类型后,您 更新内容类型定义 文件的内容类型。 Windows SharePoint Services确实 不跟踪对内容 类型定义文件所做的更改。因此,您 没有办法将 对站点内容类型的更改推送到 子内容类型。

SDK然后指向几个部分,描述如何使用UI或代码推送更改。由于UI不提供事件接收器的钩子,我想我会选择代码路径。

我想我能够做这样的事情,只是添加一个新的事件接收器的内容类型列表中的副本:

SPList list = web.Lists["My list"]; 
SPContentType ctype = list.ContentTypes["My content type"]; 
// Doesn't work -- EventReceivers is null below. 
ctype.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
         "My assembly name", "My class name"); 

但美中不足的是,ctype.EventReceivers为null这里,即使我已经将ItemAdding连接到此列表。看起来它已经移到了列表本身。所以,这个列表有一个有效的EventReceivers集合。

SPList list = web.Lists["My list"]; 
list.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
         "My assembly name", "My class name"); 

所以,我有几个问题:

  1. 是这样做只是为了直接增加任何新的事件接收器的列表,只是忘了我的内容类型完全正确的方法是什么?
  2. 要完成这个改变,在配置管理方面处理这个问题的最好方法是什么?我应该创建一个简单的控制台应用程序来查找所有适当的列表并修改它们中的每一个?或者以某种方式创建一个功能更好的选择?无论哪种方式,似乎这种变化将自行消失,很难被未来的开发者发现,他们可能需要使用这种内容类型。
+0

好问题:我一直想问一些类似的东西。 – 2009-07-02 21:07:47

回答

2

添加EventReceiver后是否调用了ctype.Update(true)?如果你不这样做,它不会被持续。 并且不要使用List内容类型,而是使用SPWeb.ContentTypes。

此代码的工作对我来说:

var docCt = web.ContentTypes[new SPContentTypeId("0x0101003A3AF5E5C6B4479191B58E78A333B28D")]; 
//while(docCt.EventReceivers.Count > 0) 
// docCt.EventReceivers[docCt.EventReceivers.Count - 1].Delete(); 
docCt.EventReceivers.Add(SPEventReceiverType.ItemUpdated, "ASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c5b857a999fb347e", "CLASSNAME"); 

docCt.Update(true); 

真实参数意味着它被下推到所有子CONTENTTYPES为好。 (即,使用内容类型的所有列表)。

+0

我想在SDK暗示不要触及内容类型定义之后,我甚至没有走上这条路。我现在看到,这是不同的,因为你可以明确地告诉它推动变化。这似乎是完成它的最佳方式。我会尝试一下。谢谢!现在,你如何在配置管理方面做到这一点? :) – 2009-07-02 21:37:09

+0

确实,你不应该触摸CType def。但这意味着仅用于创建它的CAML /通过对象模型,您可以按照自己的喜好进行操作。我们通过一个功能接收器执行上面的代码,该接收器与保存cType defs的功能耦合。 while ... delete被添加,所以我们可以根据需要多次停用/激活该功能,并且每个cType始终保留1个事件接收器(恕我直言,最干净的方式)。 所以你的问题得到了解答? – Colin 2009-07-02 22:03:06

0

就你问题的第二部分而言,我想传递我们过去为类似情况所做的一切。在我们的情况下,我们需要几个不同的脚本:一个允许我们将内容类型更新传播到所有站点中的所有列表,另一个将主站页面布局重置为站点定义(未定制表单)。

因此,我们为这些操作中的每一个创建了一些自定义stsadm命令。这样做很好,因为脚本可以放在源代码控制中,并且它实现了已经存在的stsadm接口。

Custom SharePoint stsadm Commands

1

为了回答你问题的第二部分,正因为如此变成CONTENTTYPES的事实这是一个棘手的事情的sitecollection不需额外下推到it's用在了名单。 “复制”实质上是由sitecollection中的字段组成的,并且在将contenttype添加到列表后,它们之间没有更多的链接。我认为这是由于您应该对列表进行更改而不影响网站集。无论如何,我对这个“问题”的贡献,以及我如何解决它,涉及到使xml成为“主”,并在一个功能接收器中,我拉起xml并找到所有使用contenttype的地方,并从那里更新contenttypes(真的fieldrefs)在列表级别与xml中的匹配。该代码都类似:

var elementdefinitions = properties.Feature.Definition.GetElementDefinitions(); 

foreach (SPElementDefinition elementDefinition in elementdefinitions) 
{ 
    if (elementDefinition.ElementType == "ContentType") 
    { 
    XmlNode ElementXML = elementDefinition.XmlDefinition; 

    // get all fieldrefs nodes in xml 
    XmlNodeList FieldRefs = ElementXML.ChildNodes[0].ChildNodes; 

    // get reference to contenttype 
    string ContentTypeID = ElementXML.Attributes["ID"].Value.ToString(); 
    SPContentType ContentType = 
     site.ContentTypes[new SPContentTypeId(ContentTypeID)]; 

    // Get all all places where the content type beeing used 
    IList<SPContentTypeUsage> ContentTypeUsages = 
     SPContentTypeUsage.GetUsages(ContentType); 
    } 
} 

接下来的事情就是在XML XML的fieldrefs与列表(由ID属性来完成),并确保他们是平等的字段进行比较。不幸的是,我们不能更新SPFieldLink类(fieldref)和(我知道它不被支持)的所有内容,实际上我使用了反射来更新这些值(f.e. ShowInEditForm)。

相关问题