miércoles, 26 de octubre de 2011

Introducción al Modelo de Objetos de Cliente de SharePoint 2010

Introducción

Septiembre 2011[ Artículo publicado originalmente en la revista CompartiMOSS número 9: http://jpussacq.me/2011/09/25/compartimoss-nmero-9-septiembre-2011/]

Trabajar con SharePoint implica conocer un conjunto de tecnologías y enfoques de programación que necesitan ser balanceados para obtener los mejores resultados y la mejor inversión del presupuesto de nuestros clientes. Muchas veces debemos combinar alternativas como:

  • Configuración de SharePoint
  • SharePoint Designer
  • Visual Studio
  • Herramientas (Excel Services o InfoPath por ejemplo)

Desde el punto de vista de programación, en la versión 2007 ya contábamos con un robusto modelo de objetos para programar en el servidor. Sin embargo el trabajo se volvía algo más complicado cuando necesitábamos interactuar con SharePoint desde el cliente, o cuando los administradores de SharePoint no nos permitían instalar componentes en el servidor, por el riesgo de desestabilizar la granja. Así surgieron gurúes y especialistas que se caracterizaban por:

  • Aprovechar los servicios web de SharePoint, no muy amigables.
  • Hacer maravillas con JavaScript y jQuery.
  • Hacer cosas increíbles con SharePoint Designer.

Estos métodos por momentos daban muy buenos resultados, otras veces no llegaban a convencer.

Pero esos días han terminado para el programador de SharePoint. Porque en la versión 2010 tenemos muchas mejoras y una de las que me parece más interesante (no es la única, ver imagen más abajo) es el Modelo de Objetos de Cliente de SharePoint 2010.

Sobre él, haremos hoy una breve introducción, simplemente para que el lector comience a imaginar todo lo que puede hacer…

Qué lo disfruten!

Platform stack for SharePoint 2010

Fuente de esta imagen: http://msdn.microsoft.com/en-us/library/gg552610.aspx

 

El modelo de objetos de cliente de SharePoint 2010

Lo primero que debemos saber es que el modelo de objetos de cliente de SharePoint 2010 es algo nuevo e introduce tres variantes:

  • Administrado
  • Silverlight
  • JavaScript

Cada una de estas variantes está contenida en una librería particular:

  • Administrado: Microsoft.SharePoint.Client.dll y Microsoft.SharePoint.ClientRuntime.dll (carpeta ISAPI)
  • Silverlight: Microsoft.SharePoint.Client.Silverlight.dll y Microsoft.SharePoint.Client.Silverlight.Runtime.dll (carpeta LAYOUTS\ClientBin)
  • JavaScript: SP.js (carpeta LAYOUTS)

Los tres modelos interactúan con SharePoint a través del servicio Client.svc. Los desarrolladores programamos entonces contra el modelo de objetos de cliente, pero las operaciones son enviadas en forma de lote como XML al servicio Client.svc. El servicio Client.svc ejecuta las operaciones contra el modelo de objetos del servidor y los resultados son enviados nuevamente al cliente en la forma de JavaScript Object Notation (JSON).

La siguiente imagen explica cómo se implementa (en SharePoint Online por ejemplo):

SharePoint client object models architecture

Fuente de esta imagen: http://msdn.microsoft.com/en-us/library/gg317460.aspx

Hay mucho, mucho más. Pero prefiero detenerme acá con la teoría y pasar a un ejemplo terrenal. Ya habrá otros artículos para profundizar o ustedes tendrán tiempo de consultar MSDN o algún libro.

¿MSDN? Aquí el enlace: http://msdn.microsoft.com/en-us/library/ee537247.aspx.

 

Un caso sencillo

Hasta antes de SP 2010, acceder al modelo de objetos de SharePoint desde JavaScript no era una opción. Imaginen sólo unos minutos todo lo que podemos hacer ahora a nivel de interfaces de usuario. Adicionen a eso que en principio no necesitamos ningún permiso especial del administrador de la granja de SharePoint, lo cual también significa que el modelo de objetos de cliente es más limitado que el del servidor.

Voy a darles un ejemplo muy sencillo para que vean el potencial de este modelo. Espero en próximos artículos mostrar ejemplos más complejos, pero siempre es conveniente arrancar por algo parecido al “hola mundo”.

En este caso vamos a:

  1. Insertar un elemento web de edición de contenido (CEWP).
  2. Leer los ítems de una lista del sitio raíz utilizando el modelo de objetos de cliente para JavaScript.
  3. Aplicar algo de estilo a través de CSS.

Sí, leyeron bien, vamos a leer datos de SharePoint a través de su modelo de objetos desde dentro de la simple y querida CEWP.

 

Paso 1: insertando la CEWP

Vamos a repasar rápidamente como insertar una CEWP, ya que hay algunos cambios (mejoras) en SharePoint 2010. Lo más interesante es que el contenido de la CEWP lo podemos tener almacenado en un archivo de texto, lo cual facilita el mantenimiento del código. En nuestro caso vamos a agregar un archivo llamado “CEWP.txt” dentro de una librería de documentos llamada “Scripts” tal como muestra la siguiente imagen:

image

 

Luego vamos a la página principal de nuestro sitio, hacemos clic en “Page” en la cinta y luego “Edit” para editar la página. Dentro de “Editing Tools”, hacemos clic en “Insert” y luego en “Web Part”:

image

 

Luego elegimos “Media and Content" / Content Editor” e insertamos el elemento web:

image

 

Finalmente editamos las propiedades del elemento web, en donde completaremos la ruta y el nombre del archivo que contiene el código de nuestra CEWP.

image

 

Paso 2: codificando

Abrimos nuestro archivo “CEWP.txt” desde algún editor, como puede ser el humilde Bloc de Notas, directamente desde la librería de SharePoint, insertamos el código que muestro a continuación y luego grabamos.

Nota: más adelante explicaré el código.

<div id="div1"></div>

<script type="text/javascript">

ExecuteOrDelayUntilScriptLoaded(cargar_productos, "sp.js");

function cargar_productos() {
    contexto = new SP.ClientContext.get_current();
    var lista = contexto.get_site().get_rootWeb().get_lists().getByTitle('Productos');
    var query = new SP.CamlQuery();
    query.set_viewXml('<View><ViewFields><FieldRef Name="Title"/></ViewFields></View>');
    this.items = lista.getItems(query);
    contexto.load(items);
    contexto.executeQueryAsync(Function.createDelegate(this, this.cargaok), Function.createDelegate(this, this.cargamal));
    }

function cargaok(sender, args) {
    var itemslista = this.items.getEnumerator();
    var strHtml ="<table id='box-table-a'><thead><tr><th scope='col' id='box-table-a'>Productos</th></tr></thead><tbody>";   

    while (itemslista.moveNext()) {
        var elitem = itemslista.get_current();
        strHtml += "<tr><td>";
        strHtml += elitem.get_item('Title');
        strHtml += "</td></tr>";
        }

    strHtml +="</tbody></table>";   
    document.getElementById("div1").innerHTML = strHtml;
    }
 
function cargamal(sender, args) {
    alert('ERROR: ' + args.get_message() + '\n' + args.get_stackTrace());
}

</script>

<style>

Aquí agregamos los estilos que más nos gusten. En el ejemplo, yo he tomado los estilos propuestos en este enlace:

http://coding.smashingmagazine.com/2008/08/13/top-10-css-table-designs/

Estos estilos mapean con los identificadores creados en el código JavaScript anterior:  id='box-table-a' para los <table> y <th>

Nota: no es este el lugar ideal para agregar estilos, pero prefiero no agregar complejidad en este ejemplo y que además el lector vea el potencial de la CEWP.

</style>

 

Paso 3: el resultado

Una vez que hayamos pegado nuestro código en la página principal de nuestro sitio, hacemos clic en “Home” y luego vemos los resultados, tal como grafica la siguiente imagen. Observen como sin ningún código de servidor hemos hecho una consulta a datos residentes en una lista de SharePoint:

image

 

Paso 4: entendiendo el código

Bien, vamos ahora a analizar un poco el código. Recuerden que estamos viendo un caso particular de modelo de objetos de cliente para javascript, el código puede variar si el JavaScript está por ejemplo en un página de aplicación, o si usamos Silverlight o una aplicación con código .net administrado.

Empecemos por analizar la primera línea importante de código:

ExecuteOrDelayUntilScriptLoaded(cargar_productos, "sp.js");

Esta es la instrucción que utilizamos para garantizar que SP.js esté cargada antes de que nuestra función comience a acceder a los datos de SharePoint a través del modelo de objetos de cliente.

Más información en http://msdn.microsoft.com/en-us/library/ff411788.aspx.

 

Lo segundo es obtener el contexto. A diferencia de Silverlight y el código administrado, no necesitamos especificar la URL:

contexto = new SP.ClientContext.get_current();

 

En la siguiente porción de código vamos a acceder a una lista. Si bien no podemos acceder a una lista de otra colección de sitios, si podemos acceder a una lista del sitio raíz :-), que es lo que estamos haciendo en este caso:

var lista = contexto.get_site().get_rootWeb().get_lists().getByTitle('Productos');

 

Luego entramos en un terreno un poco más conocido, preparamos una consulta CAML, en este caso para extraer el campo título de todos los ítems de esta lista:

var query = new SP.CamlQuery();
query.set_viewXml('<View><ViewFields><FieldRef Name="Title"/></ViewFields></View>');
this.items = lista.getItems(query);
contexto.load(items);

 

Por último, vamos a pedir al servidor que ejecute nuestra petición. En JavaScript sólo podemos hacerlo en forma asincrónica, motivo por el cual debemos indicarle el nombre de las funciones que llamaremos si nuestra ejecución es exitosa o no:

contexto.executeQueryAsync(Function.createDelegate(this, this.cargaok), Function.createDelegate(this, this.cargamal));

Más información en: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.clientruntimecontext.executequeryasync.aspx

 

En caso que nuestro código se ejecute en forma correcta, lo que haremos es recorrer la lista y mostrar los resultados en una tabla HTML:

function cargaok(sender, args) {
var itemslista = this.items.getEnumerator();
var strHtml ="<table id='box-table-a'><thead><tr><th scope='col' id='box-table-a'>Productos</th></tr></thead><tbody>";

while (itemslista.moveNext()) {
var elitem = itemslista.get_current();
strHtml += "<tr><td>";
strHtml += elitem.get_item('Title');
strHtml += "</td></tr>";
}

strHtml +="</tbody></table>";
document.getElementById("div1").innerHTML = strHtml;
}

En caso de error, mostramos el mensaje por pantalla:


function cargamal(sender, args) {
alert('ERROR: ' + args.get_message() + '\n' + args.get_stackTrace());
}


Ahí termina nuestro código. Es un código simple en el que me tomé algunas licencias principalmente para que puedan ver el potencial del modelo de objetos de cliente, y como dije anteriormente, imaginar todo lo que podrían hacer…

 

Conclusiones

Creo que el modelo de objetos de cliente es uno de los cambios más importantes que la versión 2010 de SharePoint implementa frente a su antecesor en cuanto a sus capacidades de desarrollo. No es el único, también están las nuevas capacidades de flujos de trabajo en SharePoint Designer, Power Shell (cool), la integración con Visual Studio y las Sandboxed solutions (más cool), por nombrar sólo algunas.

Como siempre digo, SharePoint es una excelente plataforma para construir aplicaciones, y cada vez lo es más, afortunadamente para los que nos dedicamos a esto

:-)

Hasta la próxima!

 

Juan Pablo Pussacq Laborde

Sitio  personal: http://jpussacq.me/

Twitter: http://twitter.com/jpussacq

Blog: http://surpoint.blogspot.com/

7 comentarios:

Buenas tardes!

He seguido los pasos y me sale tanto el txt cuando lo abro en blanco y también cuando lo cargo en la página a que es debido?

Gracias

No entiendo muy bien lo que dices. ¿Podrías enviarme más información o el código que has utilizado? Saludos!

Hola!

He seguido los pasos. He creado un archivo txt en una librería, en este he copiado el código que tienes en la página. Ya cuando le das al documento a abrir ya no se ve nada. Luego he hecho un content editor webpart en una pagina que yo ya tenía, lincándolo al txt pero obviamente me sale la página en blanco. Como digo copie y pegué tu mismo código.

¿Has creado las lista Productos?

Hola!

No, es eso entonces. Lo seguí como decía y pensaba que sacaba la información de algún sitio web. Entonecs como creo la lista una lista normal ,Custom list no?

Hola!! Es posible extraer los nombres de las librerias en el sitio y ordenarlas de acuerdo a la cantidad de docs que hay en cada una? poniendo un máx de librerias a mostrar

Publicar un comentario