6

Ho un tipo di contenuto del sito che è stato utilizzato per una manciata di elenchi in tutta la mia raccolta siti. In quel tipo di contenuto, descrivo un ricevitore di eventi per gestire l'evento ItemAdding. Funziona bene Ora ho bisogno di aggiornare il tipo di contenuto in modo che anche ItemUpdating sia gestito. OTTOMH, ho provato semplicemente a modificare l'xml per il mio tipo di contenuto, dal momento che questo sembrava consentire un facile monitoraggio delle versioni. Ciò ha funzionato nel senso che i miei aggiornamenti venivano applicati al tipo di contenuto del sito, ma non ai miei elenchi che utilizzavano questo tipo di contenuto. Questo era previsto. Poi ho notato che la SharePoint SDK prende un grim view di che:Aggiornamento dei tipi di contenuto SharePoint già distribuiti per gestire eventi aggiuntivi degli articoli

In nessun caso si aggiornare il file di definizione del tipo di contenuto per un tipo di contenuto dopo aver installato e attivato che il contenuto tipo. Windows SharePoint Services fa sì che non tenga traccia delle modifiche apportate al file di definizione del tipo di contenuto . Pertanto, si non è disponibile alcun metodo per annullare le modifiche apportate ai tipi di contenuto del sito su i tipi di contenuto figlio.

L'SDK quindi punta a un paio di sezioni che descrivono come utilizzare l'interfaccia utente o il codice per apportare modifiche. Dal momento che l'interfaccia utente non offre hook in destinatari di eventi, suppongo che sceglierò il percorso del codice.

ho pensato che sarei in grado di fare qualcosa del genere e basta aggiungere un nuovo ricevitore evento alla copia della lista del tipo di contenuto:

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"); 

Ma il problema è che ctype.EventReceivers è nullo qui , anche se ho già aggiunto ItemAdding a questo elenco. Sembra che sia stato spostato nella lista stessa. Quindi, la lista ha una collezione EventReceivers valida.

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

Così, ho un paio di domande:

  1. è il modo corretto per fare questo solo per aggiungere eventuali nuovi ricevitori di eventi direttamente alla lista e solo dimenticare tipo completamente i miei contenuti?
  2. Per eseguire questa modifica, qual è il modo migliore per gestirlo in termini di gestione della configurazione? Devo creare una semplice app per console per trovare tutti gli elenchi appropriati e modificarli? O è in qualche modo la creazione di una caratteristica un'opzione migliore? In entrambi i casi, sembra che questo cambiamento si svolgerà da solo e difficile da scoprire da parte degli sviluppatori futuri che potrebbero dover lavorare con questo tipo di contenuto.
+0

Buona domanda: ho intenzione di chiedere qualcosa di simile. –

risposta

2

Hai chiamato ctype.Update (true) dopo aver aggiunto EventReceiver? Se non lo fai, non verrà mantenuto. E non utilizzare il tipo di contenuto Elenco, utilizzare invece SPWeb.ContentTypes.

Questo codice funziona per me:

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

Il vero parametro significa che viene spinto verso il basso per tutti ContentTypes figlio pure. (cioè a tutte le liste che usano il tipo di contenuto).

+0

Immagino di non aver nemmeno percorso quella strada dopo che l'SDK ha implicato di non toccare la definizione del tipo di contenuto. Ora vedo che questo è diverso, dal momento che puoi dire esplicitamente di spingere verso il basso le modifiche. Questo sembra il modo perfetto per farlo. Ci proverò. Grazie! Ora, come si fa in termini di gestione della configurazione? :) –

+0

È vero che non si dovrebbe toccare il CType def. ma ciò significa SOLO la CAML che è stata usata per crearla/Attraverso il modello a oggetti puoi fare ciò che ti piace. Eseguiamo il codice di cui sopra tramite un ricevitore di funzionalità che è accoppiato alla funzione che contiene i difetti cType. il while ... delete è stato aggiunto in modo che possiamo disattivare/attivare la funzione tutte le volte che vogliamo e mantenere sempre 1 eventreceiver per cType (IMHO è il modo più pulito per andare). Quindi la tua domanda ha una risposta? – Colin

0

Per quanto riguarda la seconda parte della tua domanda, volevo trasmettere quello che abbiamo fatto per situazioni simili in passato.Nella nostra situazione, avevamo bisogno di un paio di script diversi: uno che ci permettesse di propagare gli aggiornamenti del tipo di contenuto a tutti gli elenchi di tutti i Web e un altro che ripristinasse le pagine master/i layout di pagina alla definizione del sito (modulo non personalizzato).

Così, abbiamo creato alcuni comandi personalizzati di stsadm per ciascuna di queste azioni. Fare in questo modo è bello perché gli script possono essere inseriti nel controllo del codice sorgente e implementa l'interfaccia stsadm già esistente.

Custom SharePoint stsadm Commands

1

rispondere alla seconda parte della tua domanda, questa una cosa difficile a causa del fatto che cambia a ContentTypes sul sitecollection vinto't essere spinto verso il basso per le liste dove E'utilizzati. Una "copia" è costituita essenzialmente dai campi nella raccolta siti e non vi è più alcun collegamento tra di essi dopo aver aggiunto un tipo di contenuto all'elenco. Penso che ciò sia dovuto al fatto che si suppone che si apportino modifiche agli elenchi senza che ciò influenzi la sitecollection. In ogni caso il mio contributo a questo "problema", e come l'ho risolto, consiste nel rendere il xml il "master" e in un featurereceiver richiamo l'xml e trovo tutti i posti in cui viene utilizzato il contenttype e da lì aggiorniamo i contenttypes (davvero il fieldrefs) a livello di elenco per corrispondere a quello in xml. Il codice più o meno così:

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); 
    } 
} 

Il passo successivo è quello di confrontare le fieldrefs in XML xml con i campi della lista (fatto dall'attributo ID) e fare in modo che essi siano uguali. Sfortunatamente non è possibile aggiornare tutte le cose nella classe SPFieldLink (fieldref) e (sì so che non è supportato) qui ho effettivamente utilizzato la reflection per aggiornare quei valori (ad es. ShowInEditForm).

+0

Buon pezzo di codice, ma non completamente correlato all'aggiunta di itemeventreceiver, +1 anche se – Colin

+0

@Colin - Nah, ha più a che fare con l'aggiornamento delle modifiche a contenttypes. Penso che l'aggiunta di eventreceiver sia già stata risolta –