6

Tengo un tipo de contenido de sitio que se utilizó para un puñado de listas en toda mi colección de sitios. En ese tipo de contenido, describo un receptor de eventos para manejar el evento ItemAdding. Esto funciona bien Ahora necesito actualizar el tipo de contenido para que también se maneje ItemUpdating. OTTOMH, intenté simplemente modificar el xml para mi tipo de contenido, ya que esto parecía permitir el seguimiento de la versión fácil. Esto funcionó en el sentido de que mis actualizaciones se aplicaron al tipo de contenido del sitio, pero no a mis listas que habían estado usando este tipo de contenido. Esto era esperado. Entonces me di cuenta de que el SDK de SharePoint tiene un grim view de que:Actualización de tipos de contenido de SharePoint ya implementados para manejar eventos de elementos adicionales

Bajo ninguna circunstancia debería actualizar el archivo de definición de tipo de contenido para un tipo de contenido después de que haya instalado y activado que el contenido tipo. Windows SharePoint Services does no realiza un seguimiento de los cambios realizados en el contenido tipo de archivo de definición. Por lo tanto, usted no tiene ningún método para empujar hacia abajo cambios hechos a tipos de contenido de sitio a los tipos de contenido secundarios.

El SDK luego apunta a un par de secciones que describen cómo usar la interfaz de usuario o el código para impulsar los cambios. Como la IU no ofrece ningún enlace a los receptores de eventos, creo que elegiré la ruta del código.

pensé que sería capaz de hacer algo como esto y simplemente añadir un nuevo receptor de eventos de la copia de la lista del tipo de contenido:

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

Pero el problema es que ctype.EventReceivers es nulo aquí , aunque tengo ItemAdding ya conectado a esta lista. Parece que se movió a la lista en sí. Entonces, la lista tiene una colección válida de EventReceivers.

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

lo tanto, tengo un par de preguntas:

  1. es la forma correcta de hacer esto sólo para añadir nuevos receptores de eventos directamente a la lista y olvidarse de mi tipo de contenido por completo?
  2. Para lograr este cambio, ¿cuál es la mejor manera de manejar esto en términos de administración de configuración? ¿Debo crear una aplicación de consola simple para encontrar todas las listas apropiadas y modificar cada una de ellas? ¿O de alguna manera está creando una característica una mejor opción? De cualquier manera, parece que este cambio va a ser por sí solo y difícil de descubrir por futuros desarrolladores que podrían necesitar trabajar con este tipo de contenido.
+0

Buena pregunta: he querido preguntar algo similar. –

Respuesta

2

¿Ha llamado a ctype.Update (true) después de agregar el EventReceiver? Si no lo haces, no se mantendrá. Y no use el tipo de contenido de lista, use SPWeb.ContentTypes en su lugar.

Este código funciona para mí:

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

El verdadero parámetro significa que es empujado hacia abajo a todos los TiposContenido niño también. (es decir, a todas las listas que usan el tipo de contenido).

+0

Supongo que ni siquiera fui por ese camino después de que el SDK implicó no tocar la definición del tipo de contenido. Ahora veo que esto es diferente, ya que puedes decirle explícitamente que presione los cambios. Esta parece ser la forma perfecta de hacerlo. Voy a tratar de salir. ¡Gracias! Ahora, ¿cómo se hace esto en términos de gestión de configuración? :) –

+0

Es cierto que no debe tocar la definición de CType. pero eso significa SÓLO el CAML que se usó para crearlo/A través del modelo de objetos puede hacer lo que quiera. Ejecutamos el código anterior a través de un receptor de función que está acoplado a la función que contiene los tipos de definición cType. el tiempo ... se agregó eliminar para que podamos desactivar/activar la función tantas veces como queramos y siempre mantener 1 receptor de eventos por tipo c (en mi humilde opinión la forma más limpia de ir). ¿Su pregunta es respondida? – Colin

0

En cuanto a la segunda parte de su pregunta, quería transmitir lo que hemos hecho para situaciones similares en el pasado.En nuestra situación, necesitábamos un par de scripts diferentes: uno que nos permitiera propagar las actualizaciones de tipo de contenido a todas las listas en todas las webs y otra que restablecería las Páginas maestras/Diseños de página a la definición del sitio (formulario no personalizado))

Así que creamos algunos comandos de stsadm personalizados para cada una de estas acciones. Hacerlo de esta manera es bueno porque las secuencias de comandos se pueden colocar en el control de fuente e implementa la interfaz de stsadm ya existente.

Custom SharePoint stsadm Commands

1

Para responder a la segunda parte de su pregunta, esto algo complicado, debido al hecho de que los cambios en ContentTypes en el sitecollection no seré empujado hacia abajo a las listas en las que se inunda utilizados. Una "copia" se compone esencialmente de los campos de la colección de sitios y no hay más vínculos entre ellos después de agregar un tipo de contenido a la lista. Creo que esto se debe al hecho de que se supone que debes hacer cambios en las listas sin que afecte a la colección del sitio. De todos modos, mi contribución a este "problema", y cómo lo he solucionado, implica hacer que el xml sea el "maestro" y en un receptor de características extraigo el xml y encuentro todos los lugares donde se usa el tipo de contenido y de allí actualizo los tipos de contenido (realmente los campos de referencia) en el nivel de lista para que coincida con el del xml. El código es algo como:

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

El siguiente paso es comparar los fieldrefs en XML XML con los campos de la lista (realizado por el atributo ID) y asegurarse de que son iguales. Lamentablemente no podemos actualizar todas las cosas en la clase SPFieldLink (el campo de referencia) y (sí, sé que no es compatible) aquí, he utilizado la reflexión para actualizar esos valores (por ejemplo, ShowInEditForm).

+0

Buena pieza de código, pero no completamente relacionada con la adición de itemeventreceiver, +1 a – Colin

+0

@Colin - Nah, tiene más que ver con la actualización de los cambios a los tipos de contenido. La adición de eventos receptores ya ha sido respondida, creo –

Cuestiones relacionadas