La pesadilla de SPWebConfigModification, o como perder el sueño debido a SharePoint

Para un proyecto en el que estoy trabajando en el momento, es necesario modificar diferentes configuraciones del archivo web.config de una manera automatizada. El problema es que un administrador de sistemas podría eventualmente hacer las modificaciones, pero no se le puede pedir a nadie que haga los mismos cambios una y otra y otra vez en toda una granja de servidores sin cometer errores involuntarios y sin que la persona se frustre tan terriblemente que comience a cometer errores voluntariamente…

El modelo de objetos de SharePoint 2007 nos ofrece una excelente posibilidad para solucionar el problema: la clase SPWebConfigModification. En principio, con un par de renglones de código es posible hacer modificaciones de cualquier sección (inclusive agregar nuevas secciones) en el archivo web.config de SharePoint, con la ventaja adicional de que cuando el código ejecuta, SharePoint propaga los cambios en todos los servidores de la granja, sin tener que hacerlo uno por uno manualmente. En el caso en el que yo lo utilizo, los cambios son realizados dinámicamente desde una aplicación, pero el sistema es ideal para realizar modificaciones en la instalación de componentes, pues el código se puede agregar al evento de una Característica, de tal forma que los nuevos componentes se encarguen de hacer las modificaciones en el web.config por sí mismos.

Pues bien, el primer “inconveniente” es que Microsoft ofrece información mínima (SDK) sobre la clase y su utilización. Pero siguiendo el sencillo ejemplo que el SDK nos da, se pueden hacer algunas cosas pequeñas, como agregar un “SafeControl” en el web.config (tomado del SDK):

 

SPWebService myService = SPWebService.ContentService;

SPWebConfigModification myModification = new SPWebConfigModification();

myModification.Path = «configuration/SharePoint/SafeControls»;

myModification.Name = «SafeControl[@Assembly=’MyCustomAssembly’][@Namespace=’MyCustomNamespace’][@TypeName=’*’][@Safe=’True’]»;

myModification.Sequence = 0;

myModification.Owner = WebConfigModificationFeatureReceiver.OwnerId;

myModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;

myModification.Value = «<SafeControl Assembly=’MyCustomAssembly’ Namespace=’MyCustomNamespace’ TypeName=’*’ Safe=’True’ />»;

myService.WebConfigModifications.Add(myModification);

myService.Update();

myService.ApplyWebConfigModifications();

 

Aquí se usan un par de propiedades, “Sequence” (probablemente para indicar la posición en la modificación) y “Type” que no están documentadas. La segunda es una enumeración (“EnsureChildNode”, “EnsureAttribute” y “EnsureSection”) que probablemente tiene que ver con el tipo de “Node” en el XML de la web.config. Pero después de experimentar un montón, se puede ver que tiene otra función: cualquiera de los tres valores se puede usar para crear entradas, pero si se crean con “EnsureSection” es imposible después eliminarlas, lo que sí se puede hacer si se usa “EnsureChildNode”.

Por otra parte, secciones se pueden crear fácilmente, pero no es posible eliminarlas (o por lo menos yo no pude encontrar como), por lo que lo único que se puede hacer es crear la sección, luego crear la entrada dentro de la sección, y esta ultima si se puede eliminar, dejando la sección vacía.

Otro problema al crear secciones es que frecuentemente son creadas dobles, inclusive si el código ejecuta una sola vez. Después de mucho pelear con el asunto parece que se debe al método “Update”: si se elimina, la sección es creada correctamente, de otra forma es creada doble. A pesar de lo que el SDK diga, parece que este método no es necesario para nada, y se puede quitar sin problemas.

Uno más: el método “ApplyWebConfigModifications” se puede llamar desde dos clases, “miAplicacionWeb.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();” (en donde “miAplicacionWeb” es un objeto creado anteriormente, del tipo “SPWebApplication”) o “SPFarm.Local.Services.GetValue< SPWebService>().ApplyWebConfigModifications();”. Por una u otra razón que solamente Microsoft conoce (o no), los dos métodos funcionan perfectamente igual en una granja de un solo servidor, pero solamente el primero en granjas con más de un servidor (es decir, las modificaciones no son propagadas utilizando el segundo método); tiene que ver con lo de “Local”? … ni idea… yo pensaba que se trataba de la “granja local”, no del “servidor local”… Increíble, pero encontrar algo así ha costado horas de sudor y lagrimas: después de crear el software en una maquina de desarrollo (un solo servidor) y probarlo y requeteprobarlo, se pasa a usarlo en una granja y no funciona… y vete tú a saber porque…

Finalmente, algo que te dan ganas de reír (aunque solo sea porque me he quedado sin lagrimas después del fin de semana): el método “se cansa” de trabajar. Por alguna razón de esas que probablemente se quedaran entre los misterios nunca descifrados, como la existencia de UFOs, o el tamaño de la nariz de Cleopatra, después de crear cientos de versiones del código y probarlas miles de veces en un computador de desarrollo, el archivo web.config simplemente se rebeló y no aceptó ningún otro tipo de modificaciones, incluso utilizando versiones del software que una hora antes habían funcionado perfectamente. Y no hay forma de que vuelva a funcionar, iisreset, reset completo del servidor, eliminar el web.config y volverlo a crear, nada, nada hace que el asunto vuelva a funciona… simplemente el programa no le da la gana de funciona más. Mi sospecha es que los cambios son guardados en alguna parte en la Base de Datos de SharePoint (en la de configuración?), y después de realizar unos cuantos cientos de cambios, el record (o buffer, o lo que sea) se llena, y no deja crear más modificaciones. Esto no es un gran problema si la modificación del web.config solamente tiene que ocurrir una vez, o un par de veces en toda la vida productiva del Portal. Pero mi programa necesita hacer modificaciones relativamente frecuentes, así que si el “buffer” es de unos cuantos cientos de modificaciones, el software dejara de funcionar en el Portal en donde se va a utilizar dentro de unos cuantos meses…

Gustavo – http://www.gavd.net/servers/
Escriba un Comentario que me haga reir…

Un comentario sobre “La pesadilla de SPWebConfigModification, o como perder el sueño debido a SharePoint”

  1. Hola, yo tambien estoy trabajando con esa clase, un poco menos elaborado pero estoy tratando de usar la propiedad path con el valor «system.web/siteMap/Providers», pero cuando hago el ApplyWebConfigModifications(); , me regresa » is an invalid expression, y eso me esta frustrando, pues ya lo probe con documentos xml y si funciona.
    Tienes idea de porque sea esto? por cierto esto lo estoy haciendo en un feature activation.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *