Las Apps de SharePoint 2013 (III): La primera app

October 21, 2012

Despúes de ver la introducción al modelo de las aplicaciones de SharePoint 2013 y de repasar los conceptos básicos de la infraestructura, vamos a profundizar en nuestro viaje creando una aplicación sencilla alojada en SharePoint.

La aplicación de ejemplo mostrará la ocupación en MB de un sitio de SharePoint y se actualizará mediante un botón “Refrescar”. El cálculo del espacio se hará sumando los tamaños de los ficheros alojados en las bibliotecas de ese sitio.

Crear la aplicación en Visual Studio 2012

Para empezar, abriremos Visual Studio 2012 y crearemos una nueva app de SharePoint 2013 con el nombre SpaceCounter.

New SharePoint 2013 app project

Acto seguido, completaremos los detalles del nombre (SpaceCounter) y la URL de prueba de la aplicación (http://sp2013). Es muy importante que elijamos la opción “SharePoint-hosted” en el último cuadro desplegable. Clicamos “Finish” y esperamos que Visual Studio cree la aplicación.

image

Echemos un vistazo a lo que ha generado VS2012. Veremos que hay un fichero llamado AppManifest.xml y una estructura de carpetas dentro del proyecto. El AppManifest.xml es el descriptor de la app para SharePoint: aquí está su ID (Guid), su nombre, el logo y la enumeración de recursos que necesita (permisos, tokens etc).

SharePoint app project open in VS2012

Para poder acceder al sitio host (el sitio desde el cual accedemos a la app), hay que editar el manifiesto en la parte de “Permission requests” y dar permisos de lectura al objeto Web, editando el grid que hay en ese apartado.

image

La solución está empaquetada junto con una feature (característica) de SharePoint, (auto)llamada SpaceCounter Feature1. En ella están definidas los módulos auxiliares y los ficheros que estos modulos contienen:

image

La carpeta Scripts contiene el fichero JS de la lógica de nuestra aplicación (App.js) junto con jQuery y otros ficheros JS auxiliares. Cabe recordar que no podemos usar código de servidor de SharePoint en nuestra app, aunque esté alojada en SharePoint.

La carpeta Content tiene el fichero CSS de la app y la carpeta Images las imágenes.

La carpeta Pages contienen las vistas (páginas HTML o ASPX de SharePoint, sin código de servidor). En nuestro caso tenemos la página Default.aspx que contiene un ejemplo de app que muestra el nombre del usuario.

image

Nuestro trabajo consistirá en modificar el fichero JS y el ASPX para introducir nuestra lógica y la vista HTML adecuada.

Crear la vista

Primero eliminaremos los restos de la app de ejemplo, concretamente el elemento p con el id ”message”. En su lugar pondremos el código siguiente:

<p>
Space used for this site: <span id="spaceInKB"></span>&nbsp; <button id="btnRefresh">Refresh</button>
</p>

La vista también tiene un pequeño script que invoca la función sharePointReady() al acabar de cargar. Allí cambiaremos el tag script para cargar el contexto del sitio host (en vez del contexto del sitio de la aplicación) y para volver a invocar la función mediante el botón Refresh. Aquí añadimos una función auxiliar llamada getParameterByName que nos sacará los parámetros de la URL de la aplicación. (Si a estas alturas tenemos dudas sobre que es el sitio host y que es el sitio de la aplicación, repasemos el post anterior donde explico estos conceptos).

<script type="text/javascript"> var hostweburl; var appweburl;

$(document).ready(function () { hostweburl = getParameterByName("SPHostUrl"); appweburl = getParameterByName("SPAppWebUrl"); var scriptbase = hostweburl + "/\_layouts/15/"; $.getScript(scriptbase + "SP.Runtime.js", function () { $.getScript(scriptbase + "SP.js", function () { $.getScript(scriptbase + "SP.RequestExecutor.js", sharePointReady); } ); } ); $("#btnRefresh").click(function () { sharePointReady(); }); });

function getParameterByName(name) { name = name.replace(/\[\[\]/, "\\\[").replace(/\[\]\]/, "\\\]"); var regexS = "\[\\?&\]" + name + "=(\[^&#\]\*)"; var regex = new RegExp(regexS); var results = regex.exec(window.location.search); if (results === null) return ""; else return decodeURIComponent(results\[1\].replace(/+/g, " ")); } </script>

Crear la lógica

Reemplazaremos el contenido del fichero App.js con este código en JS:

var context; var lists;

// This function is executed after the DOM is ready and SharePoint scripts are loaded // Place any code you want to run when Default.aspx is loaded in this function // The code creates a context object which is needed to use the SharePoint object model function sharePointReady() { context = new SP.ClientContext(appweburl); var factory = new SP.ProxyWebRequestExecutorFactory(appweburl); context.set\_webRequestExecutorFactory(factory); var appContextSite = new SP.AppContextSite(context, hostweburl); var web = appContextSite.get\_web(); lists = web.get\_lists(); context.load(lists); context.executeQueryAsync(onGetListsSuccess, onGetListsFail); }

function onGetListsSuccess(sender, args) { var listsEnumerator = lists.getEnumerator(); var listItemsArray = \[\]; var i = 0; var size = 0; // --- Agrupamos todas las query en un solo objeto cliente var query = SP.CamlQuery.createAllItemsQuery(); while (listsEnumerator.moveNext()) { var list = listsEnumerator.get\_current(); // --- Miramos si la lista es una biblioteca if (list.get\_baseType() === 1) { listItemsArray\[i\] = list.getItems(query); context.load(listItemsArray\[i\], 'Include(File, FileSystemObjectType, File.Length)'); i++; } } // --- Ejecutamos la query con todas las listas de golpe context.executeQueryAsync(function (sender, args) { // --- Recogemos el resultado para cada una de las listas for (j = 0; j < i; j++) { items = listItemsArray\[j\]; var itemEnumerator = items.getEnumerator(); while (itemEnumerator.moveNext()) { var item = itemEnumerator.get\_current(); // --- Solo nos interesan ficheros (fsoType = 0) if (item.get\_file() !== null) { if (item.get\_fileSystemObjectType() === 0) { size = size + item.get\_file().get\_length(); } } } } var totalSizeInKB = size / 1024; totalSizeInKB = totalSizeInKB.toFixed(2); $("#spaceInKB").text(totalSizeInKB + " KB"); }, onGetListsFail); }

function onGetListsFail(sender, args) { alert('Failed to get list data. Error:' + args.get\_message()); }

La función sharePointReady() será el punto de entrada. Aquí listaremos las todas las listas de nuestro sitio de host (pasado como parámetro appWebUrl desde Default.aspx) mediante el método get_lists(). En el callback de la ejecución de esta consulta, llamaremos a la función onGetListsSucccess().

En esta función ya tenemos las listas del sitio host y haremos una consulta recursiva por cada lista. Para no hacer N llamadas a SharePoint, agruparemos todas las consultas en un array y haremos la consulta CAML de todos los elementos a SharePoint con todas las listas a la vez. Al volver de la consulta, sumaremos los tamaños en bytes de cada elemento de tipo documento.

Para evitar los errores, sólo haremos la consulta de aquellas listas que tengan como tipo base la biblioteca de documentos (list.get_baseType() === 1).

Nota: para poder acceder a la propiedad File de un elemento, donde tenemos el tamaño en bytes, hay que cargar previamente estas propiedades mediante esta linea: context.load(listItemsArray[i], 'Include(File, FileSystemObjectType, File.Length)');

Al final, escribiremos el tamaño de la suma (redondeado a 2 decimales) en el espacio previsto en la vista.

Desplegar y probar

Para desplegar la app, haremos una ejecución apretando F5. Visual Studio empaquetará la solución y la subirá a SharePoint, quitando antes la versión anterior, si la hubiera.

image

Al proyecto le he añadido una imagen como logo de la aplicación, de tamaño 96x96 pixeles.

Una vez desplegada la app, se nos mostrará la pantalla de confirmación de permisos para la aplicación. Aquí se nos pide acceder en modo lectura a las listas y bibliotecas del sitio host. Confirmamos la elección clicando el botón “Trust”.

image

Ahora, nuestra app sale en la lista de contenidos del sitio.

image

Clicando en nuestra app, se abre una nueva ventana con la app en ejecución.

image

Nota: si os pica la curiosidad, podéis examinar la URL que se lanza al abrir la aplicación.

http://app-6855013c35bdd3.app.sharepoint.local/SpaceCounter/Pages/Default.aspx?SPHostUrl=http%3A%2F%2Fsp2013&SPLanguage=en%2DUS&SPAppWebUrl=http%3A%2F%2Fapp%2D6855013c35bdd3%2Eapp%2Esharepoint%2Elocal%2FSpaceCounter

Aquí podemos ver la URL del sitio de la app, la URL de inicio de la app y los tres parámetros que se pasan por defecto: la URL del sitio host (SPHostWebUrl), la URL del sitio web de la app (SPAppWebUrl) y el idioma (SPLanguage).

Podéis descargar el código fuente de esta aplicación en mi cuenta de SkyDrive.

En el próximo post vamos a ver como mejorar la app y como incrustarla en el sitio host.


Profile picture

Written by Edin Kapić Insatiably curious code-writing tinkerer. Geek father. Aviation enthusiast. Cuisine journeyman. Follow me on Twitter