Reescribir URL en SharePoint

Si tenéis la necesidad de realizar un portal (sobre todo enfocado a ser un portal público) y que cumpla con ciertas reglas SEO, un aspecto importante a tener en cuenta es el tema de las URLs.

Ya sabemos que SharePoint tiene su forma de crear la jerarquía de navegación en sus elementos (páginas), y no da flexibilidad para cambiar el modo en el que se navega dentro de un portal.

Realmente no hay como tal una solución soportada por Microsoft, pero si que existe una solución que puede resultar válida para lo que se busca. Sin perder el foco, lo que perseguimos es olvidarnos de una URL que sea así: http://miportal.es/Paginas/portada.aspx y poder tener su sustituta con una forma similar a esta: http://miportal.es/portada. O incluso ciertas URL en las que en la propia dirección se está pasando una query similar a http://miportal.es/Paginas/Consultas.aspx?num_consulta=14 y queremos que sea del estilo http://miportal.es/Paginas/Consultas/14.

Para conseguir esto, existe una herramienta llamada URL Rewrite que nos va a permitir crear una serie de reglas para que logremos transformar esas URL. Lo bueno es que no tenemos que hacer nada en nuestro portal de SharePoint (o casi nada), ya que esta herramienta va a trabajar a nivel de IIS, abstrayéndose de cómo trabaja SharePoint.

Con unos ejemplos rápidos y sencillos vamos a ver su funcionamiento. Lo primero de todo es descargar la herramienta. En mi caso he usado la Web Platform Installer, que simplifica el proceso:

image

image

Una vez instalada, podemos acceder a la herramienta desde nuestro IIS.

image

Y dentro del sitio correspondiente, tendremos una nueva opción para configurar el URL Rewriter:

image

Llegados a este punto, hay que comenzar con la creación de las reglas. Se pueden crear las reglas y una vez aplicadas, la herramienta hará un reciclado del pool y ya podremos ver si se están aplicando o no, es decir, que no hace falta que se haga un iisreset ni nada por el estilo. También si sirve de ayuda se puede activar el log para la herramienta.

image

Las reglas ha crear son de tipo Inbound (reglas de entrada), y vamos a crearlas a partir de una regla en blanco:

image

Es importante crear las reglas por orden, ya que se van a aplicar en el orden que hayamos establecido (se pueden mover a posterior). La primera regla es para eliminar la entrada de /Pages/ o /Paginas/, dependiendo del idioma. Vamos a usar las expresiones regulares para crear estas reglas:

image

Y luego se aplica una condición para excluir las URL que vienen de otras direcciones de SharePoint que no deben ser aplicadas, tales como las bibliotecas de estilos o las páginas dentro de /_layouts/:

image

La segunda regla es para la página por defecto o la Home, y tiene la siguiente configuración:

image

Hasta aquí, las dos reglas son de reescritura de URLs. Las dos siguientes son para redirección. La tercera regla en concreto es para los enlaces que se encuentran en la Home, y tiene la siguiente configuración:

image

Y la cuarta y última regla es para el resto de enlaces que se encuentran en el resto de páginas, subhomes, etc. y tiene la siguiente configuración:

image

Pues con estas cuatro reglas se cubre prácticamente la totalidad de casos a aplicar en las URLs de un portal de publicación por ejemplo de SharePoint. Ahora nuestro portal tendrá una navegación similar a la siguiente:

image

image

Como veis hemos hecho que desaparezca tanto el /Pages/ como el .aspx de la extensión de la página.

Aquí tenéis un resumen de las reglas y el orden de nuevo en el que deben de aplicarse para que funcionen correctamente:

image

Espero que sea de utilidad.

Cliente de SkyDrive Pro para Windows ya está disponible

Con la versión de Office 2013 apareció la herramienta SkyDrive Pro, que permitía a través de una aplicación cliente mantener sincronizados su carpeta local de SkyDrive Pro y las librerías de documentos de SharePoint 2013 y/o Office 365 para poder trabajar sin conexión.image

Ahora Microsoft ha liberado una versión para cliente que no requiere de una versión de Office instalada en el equipo, así que se puede instalar de forma independiente siempre que no tengamos alguna versión de Office 365 Pro Plus, Small Business Premium u Office Professional Plus 2013, ya que en esos casos ya viene incluida.

Podéis descargarla del siguiente enlace:

http://www.microsoft.com/en-US/download/details.aspx?id=39050

Usar Report Viewer WebPart II. Reports

Si en la entrada anterior vimos cómo configurar el WebPart de Report Viewer, ahora vamos a ver cómo crear un report que se alimente de una lista de SharePoint.

A partir de este punto, ahora vamos a utilizar Report Builder para crear nuestro informe.image

Podremos obtener esta herramienta al instalar SQL Server 2008 R2 (Report Builder 3.0).

La herramienta recuerda mucho a la apariencia de productos Office 2007 (creo que era Office 2007). Barra Ribbon en la parte superior, un menú lateral con los objetos, y el panel de edición de nuestro report.

Lo primero que vamos a hacer es añadir nuestro origen de datos, que en este caso será nuestra colección de sitios de SharePoint donde se encuentra la lista o listas de las que queremos leer información.

image

Seleccionaremos como tipo de conexíón “Microsoft SharePoint List”, y en la cadena de conexión indicaremos únicamente la colección de sitios donde se encuentran:

image

Podemos usar el botón de Test Connection para comprobar que la herramienta es capaz de acceder al site.

Una vez logrado lo anterior, el siguiente paso sería añadir los conjuntos de datos con los que vamos a trabajar en el informe:

image

Desde ahí seleccionaremos el origen de datos del que queremos leer (podemos tener varios orígenes de datos), y entraremos en el diseñador de consultas (Query Designer):

image

Desde esta ventana podremos seleccionar la lista, y los campos de la misma con los que vamos a querer trabajar en el informe:

image

Una vez los tengamos seleccionados, podemos ver el formato de query con la que vamos a trabajar:

image

Y podremos continuar con el modelado del informe, por ejemplo:

image

Una vez lo tengamos listo, guardamos el informe, lo subimos a una Biblioteca de Informes de SharePoint, y le decimos al WebPart de Report Viewer que queremos cargar ese informe:

image

Y ahí lo tenemos:

image

Scroll perdido en iPad?

En un proyecto estábamos trabajando maquetando un portal de publicación en SharePoint 2010 en HTML 5, con idea de hacerlo multidispositivo, y nos llevamos la sorpresa de que al visualizarlo físicamente en un iPad, habíamos perdido la posibilidad de hacer scroll sobre la página que habíamos publicado, teniendo que usar los dos dedos para desplazarnos verticalmente.

Pues si esto os ocurre, tenéis que añadir una media query a vuestro CSS, para que se vuelva a habilitar el scroll con un dedo en iPad. Este problema se debe a cómo calcula SharePoint en espacio del contenido y cómo lo interpretan algunos navegadores.

Aquí tenéis la media query que usamos nosotros para solucionar el problema:

@media (max-device-width: 768px){
body.v4master {height: auto;width: auto;overflow: auto !important;}
}

Y si aún así tenéis algunas zonas donde sigue sin funcionar correctamente, probar a usar esta otra más completa:

@media (max-device-width: 768px){
body.v4master {height: auto;width: auto;overflow: auto !important;}
body #s4-workspace {overflow: visible !important;height: auto !important;width: auto !important;}
#s4-titlerow {width: auto !important; }
}

Página de mantenimiento de WebParts

A veces pasa que estamos trabajando en una página de SharePoint y cuando estamos configurando algún WebPart, ya sea de serie o uno desarrollado a medida, de repente algo falla y nos deja la página con la típica pantalla de error, sin posibilidad de editarla para quitar ese WebPart o poder editar sus propiedades.

En SharePoint tenemos una página llamada página de mantenimiento, en donde nos lista todos los WebParts que tenemos en una página en concreto, permitiéndonos además eliminar uno o varios de ellos.

Si no recordáis la URL exacta de la página o cómo llegar a través de la navegación, hay un pequeño truco para llegar a esa página desde otra.

Podremos ver la página de mantenimiento de la página en la que estamos trabajando cuando en la URL del navegador añadamos el parámetro: “?contents=1”.

image

Usar Report Viewer WebPart I. Configuración

SharePoint ofrece múltiples métodos y herramientas para visualizar informes. Dependiendo del tipo de licencia (Standard, Enterprise) se pueden usar unos u otros, como puedan ser PerformancePoint, Excel Services, o como es este caso, los Report de SQL Server a través del Web Part Report Viewer.

En esta caso vamos a usar los servicios de Reporting Services para visualizar un informe creado con Report Builder 3.0, que se alimenta de una lista de SharePoint.

Para poder utilizar el WebPart de Report Viewer, es necesario activar la característica de Report Server Integration Feature, o sino no tendremos posibilidad de añadirlo.

image

Una vez activada, podremos añadirlo en una página:

image

Y en este punto es posible que encontremos un error similar al siguiente:

image

Si revisamos la traza del error, veremos que este control utiliza lo que se llama Session state, que es posible que no lo tengamos activado en nuestra granja:

Microsoft.Reporting.WebForms.SessionDisabledException: Session state has been disabled for ASP.NET. The Report Viewer control requires that session state be enabled in local mode.

at Microsoft.Reporting.WebForms.ReportViewer.EnsureSessionOrConfig()

at Microsoft.Reporting.WebForms.SessionKeepAliveOperation.CreateRequest(ReportViewer viewer)

at Microsoft.Reporting.WebForms.ReportViewerClientScript.SetViewerInfo(ReportViewer viewer, String reportAreaId, String promptAreaRowId, String docMapAreaId, String fixedTableId, String promptSplitterId, String docMapSplitterId, String docMapHeaderOverflowId, String directionCacheId, String browserModeCacheId)

at Microsoft.Reporting.WebForms.ReportViewer.OnPreRender(EventArgs e)”

Tendremos que hacer uso de PowerShell para habilitarlo, mediante el comando Enable-SPSerssionStateService:

image

Ahora podremos visualizar el WebPart en la página, en donde tendremos que indicarle qué report queremos visualizar:

image

Reglas de búsqueda comunes

En algunas ocasiones, cuando se realiza una búsqueda en un portal de SharePoint, éste nos devuelve resultados que no son útiles para el usuario o que pueden crear confusión, o permitir acceso a ciertos sitios que no queremos que estén presentes en esos resultados.

Por defecto, el buscar no realiza ningún filtro de los resultados, y si por ejemplo lanzamos una búsqueda de unas páginas, el buscador nos va a incluir en los resultados la propia librería de páginas donde se encuentran.

Para omitir esos resultados basta con crear una serie de reglas en el Servicio de Búsqueda, que van a evitar que aparezcan resultados de las listas que contienen los contenidos por ejemplo.

Si estamos buscando una serie de artículos y no tenemos las reglas creadas, es posible encontrar un resultado como el siguiente:

image

Como veis, los últimos resultados incluyen las listas donde se encuentran los artículos. Es una información que queremos omitir en los resultados.

Para ello, hay que crear unas reglas. Las más comunes son las siguientes, y por supuesto, se pueden complementar con otras adicionales si fueran necesarias:

*://*AllItems.aspx

*://*AllForms.aspx

*://*DispForm.aspx

*://*default.aspx

*://*my-sub.aspx

*://*Thumbnails.aspx

*://*mod-view.aspx

Para crearlas, desde la Administración Central hay que darlas de alta dentro de la administración del servicio de búsqueda:

image

image

Una vez creadas todas hay que lanzar una indexación completa (no basta una incremental) para que aplique las reglas que se han creado.


image

La próxima vez que se realice una búsqueda, los resultados ya aparecerán sin esa información que queríamos eliminar:

image

REST API en SharePoint 2013 II:CRUD sobre listas

Si en el anterior Post vimos como realizar consultas básicas de lectura sobre listas utilizando REST, ahora vamos a ver cómo realizar operaciones de creación, actualización, eliminación e inserción con listas de SharePoint. La construcción de la petición para métodos HTTP de tipo GET es más sencilla que para los tipos POST, ya que éstos van a requerir por un lado la obtención del “Form Digest” que nos permitirá realizar este tipo de operaciones, y además será necesario incluir información adicional en las cabeceras JSON y un bloque de datos para algunas peticiones.

Siguiendo el ejemplo del Webpart anterior, vamos a extender el código para implementar la nueva funcionalidad.

Form Digest

Las peticiones PUT y POST van a requerir que incluyamos un valor adicional en la cabecera de la petición, del tipo X-RequestDigest: formDigest, donde éste último parámetro lo obtendremos tras realizar una petición al servicio. Esta petición hay que hacerla cada vez que queramos ejecutar una acción de tipo POST y PUT, por lo que la vamos a encapsular en una función reutilizable:

function getFormDigest() {
console.log("getFormDigest");
var digest = '';

$.ajax({
url: "/_api/contextinfo",
type: "POST",
headers: { "accept": "application/json; odata=verbose" },
dataType: "json",
success: function (data) {
if (data.d) {
digest = data.d.GetContextWebInformation.FormDigestValue;
console.log("FormDigest success");
}
},
error: function (xhr) {
console.error(xhr.status + ': ' + xhr.statusText);
},
async: false
});

return digest;
}

En este caso, la url a la que atacamos es “/api/contextinfo”, y podemos en tiempo de ejecución ver todo lo que nos devuelve, aparte del valor Form Digest. imagePor un lado tenemos el atributo FormDigestTimeoutSeconds, que es el tiempo que va a ser válido el Form Digest antes de que caduque, por lo que tendremos que realizar la operación deseada antes de que expire este tiempo (1800 segundos). Por otro lado tenemos el atributo LibraryVersion, que nos indica la versión de las librerías REST. Además nos da otros valores, como por ejemplo la url de nuestro sitio, etc.


Creación de listas


El primer cambio que vamos a añadir es la posibilidad de crear una lista genérica. Para ello, vamos a modificar el control del Webpart para añadir un botón que lance el código:


image


Y en el código javascript añadimos la función:


function createBasicList() {
console.log("createBasicList");
var listName = prompt("Enter list name");

if (listName && listName != '') {
var digest = getFormDigest();
if (digest && digest != '') {
var jsonBody = {
'__metadata': { 'type': 'SP.List' },
'BaseTemplate': 100,
'Title': listName,
'Description': ''
};
$.ajax({
url: "/_api/web/lists",
type: "POST",
headers: {
"content-type": "application/json;odata=verbose",
"accept": "application/json; odata=verbose",
"X-RequestDigest": digest, "If-Match": "*"
},
data: JSON.stringify(jsonBody),
success: function (data) {
if (data.d) {
console.log("List created");
alert("List created");
}
},
error: function (xhr) {
console.error(xhr.status + ': ' + xhr.statusText);
}
});
}
}
}

Lo primero que hemos hecho es obtener el Form Digest que vamos a usar. Posteriormente definimos el body de la petición, con sus metadatos y atributos de la lista que vamos a crear (La plantilla, el título y la descripción). Indicamos en la función Ajax que el tipo de petición es POST, y en la cabecera añadimos el tipo de contenido del resultado, y el X-RequestDigest, utilizando el valor obtenido anteriormente.


Al ejecutarlo, introducimos un nombre de una lista que no exista, y veremos el resultado (satisfactorio, o un error).


image


En caso de obtener un error, es necesario leer el log de SharePointimage, ya que no vamos a obtener el detalle del mismo en el resultado de la operación. Si la cosa se complica y no sale a la primera, paciencia y a depurar el código Javascript.


También hay que tener en cuenta que no es posible indicar algunos parámetros en la petición, como por ejemplo la fecha de última modificación. Es decir, no vamos a poder crear una lista nueva y forzar algunos valores en la creación. En el caso de no indicar el resto de valores posibles, SharePoint utilizará los de por defecto.


Para comprobar que se ha creado, podremos navegar a la lista, o utilizar el botón que habíamos desarrollado antes para ver las listas del sitio actual. En este ejemplo yo ya llevaba creadas varias listas:


image


Añadir elementos a una lista genérica


Lo siguiente que vamos a hacer, es introducir elementos en las listas que creamos. Vamos a modificar la tabla donde se mostraba el listado de listas para añadir un botón de añadir elemento. Ahora el código Javascript de ese método sería el siguiente:


image


Antes de seguir, es importante entender, que para crear un elemento dentro de una lista, vamos a necesitar por supuesto el Id de la lista, y el EntityTimageype de la lista, para asegurarnos de que el elemento creado corresponde al que acepta nuestra lista. Ese valor, se puede consultar en los detalles de la lista, y se llama ListItemEntityTypeFullName. Estos dos valores se los vamos a pasar a la función que se encargará de añadir un elemento a una lista:


function addItemToList(listId, listItemEntityType) {
console.log("createBasicList");

var itemTitle = prompt("Enter item title");

if (itemTitle && itemTitle != '') {
var digest = getFormDigest();
if (digest && digest != '') {
var jsonBody = {
'__metadata': { 'type': listItemEntityType },
'Title': itemTitle
};
$.ajax({
url: "/_api/web/lists/getbyid('" + listId + "')/items",
type: "POST",
headers: {
"content-type": "application/json;odata=verbose",
"accept": "application/json; odata=verbose",
"X-RequestDigest": digest, "If-Match": "*"
},
data: JSON.stringify(jsonBody),
success: function (data) {
if (data.d) {
console.log("Item added");
alert("Item added");
}
},
error: function (xhr) {
console.error(xhr.status + ': ' + xhr.statusText);
}
});
}
}
}

Ahora en el body de la petición vamos a indicar este entity type, y el título del elemento a añadir. En la url vamos a indicar el id de la lista, e indicamos que vamos a atacar a los elementos de la lista. Para probar el código vamos a introducir un título para el elemento que añadamos, y veremos si el resultado a sido el deseado.


image


Podremos comprobar que el elemento se ha creado navegando a la lista y viendo los elementos que contiene.image


image


Actualización de una lista


Otra operación típica es la actualización de listas o elementos. En este caso vamos a introducir una descripción a la lista que seleccionemos del listado. Para ello vamos a modificar el método que lista las listas para añadir el botón que lance la operación:


image


Y el código para la actualización:


function setDescription(listId) {
console.log("setDescription");

var desc = prompt("Enter list description");
var digest = getFormDigest();

if (digest && digest != '') {
var jsonBody = {
'__metadata': { 'type': 'SP.List' },
'Description': desc
};
$.ajax({
url: "/_api/web/lists/getbyid('" + listId + "')",
type: "POST",
headers: {
"content-type": "application/json;odata=verbose",
"accept": "application/json; odata=verbose",
"X-Http-Method": "MERGE",
"X-RequestDigest": digest, "If-Match": "*"
},
data: JSON.stringify(jsonBody),
success: function () {
console.log("Description updated");
alert("Description updated");
},
error: function (xhr) {
console.error(xhr.status + ': ' + xhr.statusText);
}
});
}
}

En el body de la petición vamos a indicar la descripción, y en las cabeceras vamos a añadir el parámetro X-Http-Method: MERGE, para indicar que se trata de una actualización.


Podemos lanzar la prueba y ver el resultado:


image


Para comprobar que ha funcionado, podremos ver el detalle de la lista y comprobar que la descripción ha sido actualizada.


image


Eliminación de listas


En este caso vamos a añadir un botón al listado de listas para eliminar la lista seleccionada (cuidado de no eliminar ninguna lista que nos deje roto el sitio de SharePoint). El código para generar el listado quedaría así:


image


Y el código del método de borrado sería el siguiente:


function deleteList(listId) {
console.log("deleteList");

var c = confirm("Delete list?");
if (c == true) {
var digest = getFormDigest();

if (digest && digest != '') {
$.ajax({
url: "/_api/web/lists/getbyid('" + listId + "')",
type: "POST",
headers: {
"content-type": "application/json;odata=verbose",
"accept": "application/json; odata=verbose",
"X-Http-Method": "DELETE",
"X-RequestDigest": digest, "If-Match": "*"
},
success: function () {
console.log("List deleted");
alert("List deleted");
},
error: function (xhr) {
console.error(xhr.status + ': ' + xhr.statusText);
}
});
}
}
}

Aquí no tendremos que indicar ningún body en la petición, ya que se trata de un borrado. Lo que si debemos indicar es una cabecera de tipo X-Http-Method: DELETE. Probamos el código y vemos el resultado:


image


imageCon estos ejemplos básicos hemos podido comprobar cómo funcionan el conjunto de operaciones CRUD utilizando REST. Si queréis ampliar información os recomiendo echar un vistazo a la documentación del MSDN.


Espero que os haya sido de utilidad.

SharePoint Between Racks © 2012
. Con la tecnología de Blogger.

¡Compártelo!


Estoy en LinkedIn!


Ve mi perfil en LinkedIn!