代码之家  ›  专栏  ›  技术社区  ›  Chris Farmer Marcelo Cantos

正在更新已部署的SharePoint内容类型以处理其他项目事件

  •  6
  • Chris Farmer Marcelo Cantos  · 技术社区  · 15 年前

    我有一个网站内容类型,在我的网站集中用于少数列表。在该内容类型中,我描述了一个事件接收器来处理itemadding事件。这个很好用。现在我需要更新内容类型,以便同时处理项更新。Ottomh,我尝试简单地修改我的内容类型的XML,因为这似乎允许轻松的版本跟踪。这在我的更新被应用到网站内容类型的意义上起作用,但不适用于使用此内容类型的列表。这是意料之中的。然后我注意到SharePoint SDK grim view 其中:

    在任何情况下你都不应该 更新内容类型定义 内容类型的文件 已安装并激活该内容 类型。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");
    

    但这里的catch是ctype.eventReceivers为空,即使我已经将itemAdding连接到这个列表。它似乎已移动到列表本身。因此,该列表具有有效的EventReceivers集合。

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

    所以,我有几个问题:

    1. 这样做的正确方法是将任何新的事件接收器直接添加到列表中,然后完全忘记我的内容类型吗?
    2. 为了完成这个更改,在配置管理方面,最好的方法是什么?我应该创建一个简单的控制台应用程序来查找所有合适的列表并修改它们吗?或者创造一个特性是一个更好的选择?不管是哪种方式,这一变化似乎将自行关闭,未来的开发人员很难发现谁可能需要与这种内容类型的工作。
    3 回复  |  直到 15 年前
        1
  •  2
  •   Colin    15 年前

    添加eventReceiver后是否调用了ctype.update(true)?如果你不这样做,就不会坚持下去。 不要使用列表内容类型,而是使用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);
    

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

        2
  •  1
  •   Alex Angas Colin    15 年前

    要回答问题的第二部分,这是一个棘手的问题,因为SiteCollection上的ContentType更改不会被下推到使用它的列表中。“副本”本质上是由SiteCollection中的字段构成的,并且在向列表中添加ContentType之后,它们之间不再有链接。我认为这是因为您应该在不影响网站集的情况下更改列表。无论如何,我对这个“问题”的贡献,以及我如何解决它涉及到使XML成为“主文件”,在一个FeatureReceiver中,我提取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)上的所有内容,并且(是的,我知道它不受支持),这里我实际使用反射来更新这些值(例如ShowInEditForm)。

        3
  •  0
  •   UnhipGlint    15 年前

    至于你问题的第二部分,我想把我们过去在类似情况下所做的事情传下去。在我们的情况下,我们需要两个不同的脚本:一个允许我们将内容类型更新传播到所有网站中的所有列表,另一个允许我们将主页面/页面布局重置为网站定义(非自定义表单)。

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

    Custom SharePoint stsadm Commands