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)。

相關問題