Anidando CDATAs, o cómo no morir personalizando el CoreResultsWebPart

Cada vez que he tenido que hacer una personalización del elemento web de resultados de búsqueda de SharePoint (CoreResultsWebPart) me he encontrado con el mismo problema: el despliegue. La teoría es muy simple, sobre un sitio creado se edita el elemento web, se obtiene el valor del campo XSL, se edita con cualquier editor de XSL, se guarda el webpart con el nuevo valor de la propiedad hasta que obtenemos el resultado deseado y finalmente exportamos el elemento web para insertarlo donde nos convenga en nuestro paquete de despliegue.

¿Pero qué pasa cuando metemos variables en juego? En ocasiones tenemos que introducir valores multilenguaje o urls relativas a la colección de sitios en la que nos encontramos. Por cierto, si habéis llegado hasta aquí y no he despertado vuestro interés, o bien es por que tenéis totalmente resuelto este problema, o bien es porque no os habéis visto en la necesidad de crear algo productizable. Si, como digo, no he despertado vuestra curiosidad a estas alturas, os recomiendo no perder más tiempo en este artículo, ya escribiré cosas mejores Winking smile.

Bien, si seguís leyendo a estas alturas, imagino que estaréis esperando la fórmula mágica para hacer esta tarea un poquito más simple de lo habitual. Primero, dediquemos unas líneas al método tradicional. Una vez obtenido el valor para la propiedad XSL anteriormente mencionada, escapamos el código y lo insertamos en el XML de aprovisionamiento. Si habéis hecho esto en alguna ocasión, estaréis conmigo en que como se te escape algún pequeño error en este punto, depurarlo va a ser poco menos que imposible. Además, la próxima vez que hagas un cambio vas a tener que repetir todo el proceso. No sé a vosotros, pero a mí eso no me gusta nada de nada. Hasta hoy esto era un trance por el que tenía que pasar, pero el frotar se va a acabar…

Una solución, como habréis deducido del título del post, consiste en anidar CDATAs. Pero, ¡si no se puede! ¡si no está permitido según el estándar! Hoy he encontrado una solución muy original de un tal Nat Dunn y que podéis encontrar aquí. La solución consiste en utilizar el siguiente patrón, teniendo en cuenta que el primer CDATA contendría el elemento web y que el CDATA anidado contendría el valor de la propiedad XSL.

<![CDATA[

 

<![CDATA[<!-- Contenido del CDATA anidado -->]]]]><![CDATA[>

      

]]>

De acuerdo pero, ¿cómo queda esto al final? El siguiente listado muestra partes del fichero de aprovisionamiento con el que he hecho las pruebas. He dejado a propósito otra propiedad (SampleData) para demostrar las diferencias entre el modo habitual de tratar este tipo de propiedades y el modo que os estoy proponiendo.

<![CDATA[<webParts>

<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

  <metaData>

    <type name="..." />

  </metaData>

  <data>

    <properties>

      <property name="SampleData" type="string">&lt;All_Results&gt;

        &lt;Result&gt;

          &lt;workid&gt;1&lt;/workid&gt;

          &lt;rank&gt;222&lt;/rank&gt;

          &lt;title&gt;Title of document or web page&lt;/title&gt;

          &lt;author&gt;Author of document or web page&lt;/author&gt;

          &lt;size&gt;1025&lt;/size&gt;

          &lt;sitename&gt;http://www.sample.com&lt;/sitename&gt;

          &lt;url&gt;http://www.sample.com/folder/document.aspx&lt;/url&gt;

          &lt;imageurl&gt;/_layouts/images/aspx16.gif&lt;/imageurl&gt;

          &lt;description&gt;This is the summary of the document or web page. The summary is generated from the original document based on matches with query terms. In some cases, the summary is a description provided by the author.&lt;/description&gt;

          &lt;write&gt;December 26, 2004&lt;/write&gt;

        &lt;/Result&gt;

      &lt;/All_Results&gt;

      </property>

      <property name="Xsl" type="string">

        <![CDATA[

          <?xml version="1.0" encoding="iso-8859-1"?>

          <xsl:stylesheet version="1.0"

              xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

              xmlns:srwrt="http://schemas.microsoft.com/WebParts/v3/searchresults/runtime"

              xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime">

            <xsl:output method="xml" indent="no"/>

            <xsl:param name="Keyword" />

            <xsl:param name="ResultsBy" />

            <xsl:param name="ViewByUrl" />

            <xsl:param name="ShowDropDown" />

            

            <!-- Un montón de código aquí -->

            

                </xsl:otherwise>

              </xsl:choose>

            </xsl:template>

 

            <!-- End of Stylesheet -->

          </xsl:stylesheet>          

        ]]]]><![CDATA[>

      </property>

      

      <!-- Un montón de propiedades aquí -->

      

    </properties>

  </data>

</webPart>

webParts>]]>

No se vosotros, pero yo me he llevado una alegría al ver que esto funcionaba. Antes de acabar, un par de puntos:

  1. Esto está funcionando ahora, pero puede tener algún efecto secundario, como siempre. Si detecto alguno, actualizaré el artículo e indemnizaré a todos mis subscriptores con 100€ en la MartosStore
  2. He leído por ahí que nunca deberíamos anidar CDATAs jamás de los jamases. Lo único que os puedo decir es que si por cada vez que lo haces, dios mata a un gatito… lo dejaré de hacer.

¿Te funciona el intellisense pero no compila?

Hoy toca ese tipo de recordatorios que, no por ser cosas aparentemente triviales, dejan de ser importantes. En el caso que me ocupa, estuve el otro día haciendo una pequeña prueba de concepto y me pasé un buen rato con un error bastante curioso. Un código que tenía funcionando perfectamente en un proyecto no me compilaba en esta prueba de concepto. Las líneas conflictivas eran:

SPLimitedWebPartManager limitedWebPartManager;

SPUtility.GetGenericSetupPath("TEMPLATE");

Estas dos líneas, aparentemente sencillas, devolvían los siguientes dos errores:

'Microsoft.SharePoint.Utilities.SPUtility' does not contain a definition for 'GetGenericSetupPath'

The type or namespace name 'SPLimitedWebPartManager' could not be found (are you missing a using directive or an assembly reference?)

Antes de ir a la solución, es necesario entender el momento de frustración por el que se pasa. El sistema no encuentra elementos que debería encontrar y que además, son de lo más común del mundo. Eliminas y vuelves a crear la referencia a Microsoft.SharePoint.dll una y otra vez. Haces mil cambios en el código hasta dejar prácticamente aisladas estas dos llamadas. Nada, siempre el mismo error.

Como no podía ser de otra manera, el error viene causado por una tontería. Como sabréis, cuando creáis un proyecto de SharePoint se os da la opción de elegir entre Farm Solution y Sanboxed Solution. No os voy a hablar de las diferencias entre un modo y el otro, pero simplemente deciros que el modelo de objetos de SharePoint cuando estáis en modo Sanbox se reduce bastante. De esa manera, espacios de nombre, clases o miembros que funcionan perfectamente en soluciones de tipo granja, quedan deshabilitados completamente en modo Sandbox. Si váis, por ejemplo, a esta página, Veréis que la clase SPLimitedWebPartManager no está disponible para Sandbox.

La solución a este problema puede ser muy simple o muy compleja en función de la siguiente pregunta: ¿realmente necesitáis que el código funcione en modo SandBox? si la respuesta es no, os bastará con ir a las propiedades del proyecto y cambiar el valor de la propiedad Sandboxed solution. Si la  respuesta es seguramente la solución pasará por buscar una alternativa, si es que la hay, que no haga uso de los elementos que nos están dando problemas. Si tenemos la opción de desplegar un Sandbox Proxy será una buena noticia, porque siempre podremos trasladar allí el código conflictivo.

SharePoint 2010 y ALM. ¿Es posible?

Muchos de vosotros habréis notado un descenso importante en la frecuencia de artículos en este blog. Históricamente siempre me ha pasado esto, empezando con mucho ritmo pero, a medida que se acercaba el final del año y con las urgencias que esto acaba acarreando, me acababa dedicando a todo menos a actualizar el blog.

Este año, no obstante, la razón ha sido otra. Las últimas semanas las he dedicado a una parte de mi trabajo que siempre he identificado como la más importante, pero que siempre ha quedado en un segundo plano: ALM o la Gestión del Ciclo de Vida de las Aplicaciones. Ahora que ya puedo decir con orgullo que la mayor parte de la infraestructura necesaria está en su lugar, y aprovechando que tengo preparados unos cuantos eventos que giran en torno a este asunto he pensado escribir una serie de artículos, empezando por la introducción que haré a continuación.

Antes de comenzar, una puntualización: ahí fuera hay verdaderos expertos en ALM y no querría yo meterme en su terreno. Aunque en ocasiones hablaré de forma genérica, quiero dejar claro que yo voy a hablar de ALM en el mundo SharePoint, una combinación sobre la que no hay tanto material, almenos en este país. No obstante, si digo alguna barbaridad y algún experto en ALM quiere corregirme, será más que bienvenido J

ALM es un asunto que genera cierta controversia. Pese a que la mayoría de profesionales del sector opinamos que poner atención a este asunto es primordial y aumenta espectacularmente la calidad de nuestro software, es rara la ocasión en que realmente se ponen todos los medios necesarios. Normalmente el argumento que se utiliza para no destinar presupuesto a esta partida es que es difícil de justificar de cara al cliente y, efectivamente, es un argumento totalmente válido. Cuando te compras un coche tú eliges las llantas, el número de marchas, los caballos, etc., pero el vendedor nunca pone en el presupuesto una línea donde se te cobren los procesos de calidad que han seguido y el I+D que han necesitado para construir el coche que tú estás comprando. ¿Cuál es la solución entonces? Mi opinión es que SIEMPRE hay que poner especial atención a este tema y después, a la hora de justificarlo de cara al cliente, plantear que el coste de hacer las cosas bien es un factor multiplicador en el precio por funcionalidad que se le va a cobrar.

Muchos diréis que es imposible, al menos en países como España, hacer esto que digo. Que en general aquí se mira el precio por hora final o el precio total del proyecto para decidirse entre un proveedor u otro. Pues mi objetivo con esta serie de artículos es convenceros de que ahí estáis equivocados. Yo no creo que hacer las cosas bien sea necesariamente más caro que hacerlas rápido. En los próximos artículos os explicaré cómo un buen trabajo en este apartado hace que la calidad de los desarrollos aumente, y un aumento de la calidad del software implica una disminución del número de errores y una mayor mantenibilidad del código, con lo que hacemos que el tiempo total del desarrollo y los costes recurrentes de nuestros clientes disminuyan. ¿Acaso no pasa esto en otros sectores? ¿Acaso no prefieres pagar más dinero por un elemento de más calidad que nos asegure más durabilidad o menos problemas a futuro? Evidentemente siempre nos encontraremos con quien prefiere pagar menos (o dispone de menos dinero para gastar) y se decantará siempre por la solución más barata pero, desengáñate, siempre habrá alguien más barato que tú. Si quieres luchar por conseguir esos clientes entrarás en un sistema perverso en el que facturas por debajo de coste (si no lo haces tú lo harán otros) esperando a que una vez conseguido el cliente sea más fácil subir la tarifa. ¿Cuántas veces habéis visto que, cuando quieres subir la tarifa para cubrir tus costes, el cliente se decanta por un proveedor más barato? Mi idea es que si un proveedor cobra X por un trabajo de 1 mes y tú cobras 2X por ese mismo trabajo, a priori estás cobrando más dinero. Si el primer proveedor se retrasa un mes y sigue cobrando lo mismo, evidentemente el cliente estará pagando menos dinero pero tendrá que asumir un retraso. Si resulta que ese proveedor te cobra por horas al final estarás pagando lo mismo. Además, si después estás un año resolviendo incidencias o si después el código fuente acaba siento tan poco mantenible que necesitas perfiles extremadamente altos para resolver sus incidencias, te aseguro que los costes se multiplicarán exponencialmente.

En mi opinión todos deberíamos luchar en este sector para que todo el software que se desarrollase tuviese la máxima calidad. En ese momento podríamos usar términos como Ingeniero/a o Arquitecto/a con todas las de la ley. Seguramente al inicio podría resultar un poco caos porque, no nos engañemos, la inversión inicial necesaria para poner todo esto en marcha no es pequeña, y no todas las empresas están dispuestas a hacerla. Es nuestro trabajo educar primero a nuestras empresas, haciendo ver a las personas que toman decisiones lo importante de esta inversión y las ventajas que aportan a medio y a largo plazo, y de la misma manera hacer ver esto a nuestros clientes. Yo creo que con un poco de paciencia podremos conseguir grandes cosas en este aspecto.

En los siguientes artículos de esta serie os hablaré de dos cosas que necesitáis para convencer a la gente de la importancia del ALM: herramientas y métricas. Las herramientas nos van a ayudar a llevar todos los procesos necesarios a cabo, y las métricas nos van a servir para mostrar el valor del tiempo invertido de manera que sea entendible por personal no técnico. Imaginad, por ejemplo, que sois capaces de decir que el número de errores decrece en un 80% o que el porcentaje de código fuente cubierto por una prueba unitaria es del 95%. Con este tipo de datos no resulta demasiado complejo poner un número al lado indicando la cantidad de horas no malgastadas en mantener un código y que pueden ser facturadas en otro proyecto. En el momento en que ese número de horas se equipare con el número de horas utilizadas para montar las herramientas de las que os hablaré ya habremos hecho buena la inversión y, a partir de ese momento, el beneficio será evidente.

En fin, acabo aquí la introducción a este asunto que seguro que genera muchas discusiones. Seguro que al leer esto algunos pensáis que en vuestra empresa esto no es viable o que lo habéis probado pero no os han dejado. Después habrá gente que no estará de acuerdo con las herramientas que os iré exponiendo a medida que escriba los siguientes artículos y también habrá alguno que saque a relucir el eterno dilema de lo que es un arquitecto y lo que no lo es. Ya sabréis lo que diré: cualquier opinión tiene que ser respetada 😉

Segundo evento presencial del SUG.CAT

Desde SUG.CAT y con el apoyo de Microsoft Ibérica queremos continuar con las sesiones presenciales del Grupo de Usuarios de SharePoint de Catalunya con dos presentaciones de algunas de las características de SharePoint 2010 que más interés han despertado en la comunidad. En una de estas presentaciones os enseñaremos como podéis gestionar el ciclo de vida de las aplicaciones (ALM) en proyectos que involucren SharePoint 2010 y en la otra veremos los factores de éxito clave para que una solución de SharePoint sea adoptada por los usuarios finales, evitando los problemas asociados a la gestión del cambio y de adopción entre los usuarios.

Agenda:

  • "ALM en SharePoint 2010. Aumenta la calidad de tus proyectos."
  • "Cómo vender tu solución de SharePoint al usuario final"

Datos de interés:

  • Audiencia: Profesionales de IT.
  • Requisitos previos: Conocimientos de la plataforma SharePoint 2010.
  • Fecha: Jueves 3 de Noviembre de 2011.
  • Hora: 18:00 a 20:00.
  • Formato: Presencial y online, gratuito.

Ponentes:

Edin Kapic, Key Consultant de SharePoint en Pasiona Consulting. Miembro fundador deSUG.CAT y moderador oficial del foro de desarrollo SharePoint de MSDN http://social.msdn.microsoft.com/Forums/es-ES/mossdeves

David Martos González, MVP de SharePoint Server y Arquitecto de software en Spenta Consulting. Miembro fundador deSUG.CAT, escribe habitualmente en su blog http://david-martos.blogspot.com

Podéis inscribiros en esta dirección:

https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032496468&Culture=es-ES

Esta vez prometo, si queréis

Si no podéis venir y queréis asistir de manera virtual, podéis utilizar la siguiente dirección:

https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032496476&Culture=es-ES

¡Os esperamos a todos!

Actualizado el 27/10/2011

Gracias a mi querido lector B, me he dado cuenta que voy prometiendo cosas a la ligera (leer 5 líneas más arriba). Lo que se quedó en el tintero fue que esta vez, si alguien gusta, se harán unas pertinentes birras al finalizar el evento Smile

¡¡He sido reno-MVP-tizado!!

No hay mejor manera de iniciar la semana (bueno, sí la hay pero en este blog no procede hablar de ellas…) que recibiendo la notificación de que te han renovado como MVP por un año más. Si hace un año informaba con orgullo que había entrado en tan selecto grupo, aún con más orgullo, si cabe, os informo de que me han brindado la posibilidad de seguir estando dentro hasta octubre del año 2012.

A decir verdad no contaba con conseguirlo este año porque los compromisos profesionales me han impedido participar en la comunidad tanto como me hubiera gustado, y la competencia es realmente dura. Espero poder mantener el nivel durante este año aunque ya adelanto que va a ser realmente complicado teniendo en cuenta lo que me trae este año Papa Noel (SPOILER!!!!")

En fin, gracias a todos los que hacen posible que pueda disfrutar de este privilegio, comenzando por mi empresa (Spenta Consulting) que permite que dedique un considerable número de horas a I+D y a organizar eventos y sin olvidarme de mi mujer y de mi gato, que permiten que dedique tantas horas de mi tiempo libre a friquear. Un saludo a todos, y seguimos para bingo…