March 2009 - Artículos
Igual que a Jorge Serrano me gusta la fotografía:-) Las imágenes que tomamos con la cámara digital suelen ir acompañadas con una serie de información acerca de la toma(fecha, hora, modelo de cámara, exposición, longitud focal, tec.). El formato en el que se guarda esta información cumple con el estándar EXIF.
Para muchos fotógrafos profesionales o aficionados tener a la vista los datos EXIF junto a la foto puede ser muy importante y por ello si planteamos montar un archivo fotográfico con SharePoint es muy interesante poder almacenar la información EXIF de la foto de la misma forma que almacenamos otro tipo de información(metadata).
En el blog Fabita.nl encontramos una solución(con su código fuente) basada en el uso de event handler sobre una biblioteca de imágenes. Este event handler se invoca al añadir o editar un elemento de la biblioteca(ItemAdded y ItemUpdating), en ese momento extrae los datos EXIF del elemento(imagen) y rellena los campos de la biblioteca.
Es una solución útil para los aficionados a la fotografía y un buen ejemplo de uso de los event handlers(no solo de los WebPart vive el SharePoint:-)

Esta utilidad que se instala como característica(feature) añade un nuevo apartado en la página de configuración de las listas y permite visualizar una serie de información adicional sobre la lista(muy útil para el desarrollo).
Mas información en el blog del autor:
http://karinebosch.wordpress.com/2009/03/14/list-properties-feature/
Revisando los proyectos de SharePoint en Codeplex(lo hago de forma habitual)me he encontrado con el proyecto SLAM(SharePoint List Association Manager).
Se trata de una herramienta que permite configurar relaciones entre distintas listas y consolidar los datos de estas en la base de datos.
El el siguiente vídeo se puede ver claramente como funciona la herramienta. La herramienta en si parece bastante interesante, aun mas le código fuente y la idea para hacer herramienta de este tipo.
En el siguiente enlace podemos descargar gratuitamente el capítulo "Some of the New Features in Silverlight 3" del libro escrito por Laurence Moroney. En este capítulo se hace un repaso de las novedades introducidas en la versión 3 de Silverlight.
http://download.microsoft.com/download/3/0/5/3055A230-B06F-4A58-AC93-B7CFD2184A70/FirstLookSL3Moroney.pdf
Introducción
Actualmente cualquier contenido e-learning que se querrá alojar en un sistema de formación(LMS) debería de ser desarrollado en base a la norma SCORM.
La norma SCORM se compone de una serie de libros(guías) que definen:
En la actualidad existe un gran numero de herramientas que pueden ser de ayuda para la construcción de los contenidos SCORM. En este contexto es muy importante tener algún método o herramienta que permita validar la conformidad del contenido con la norma SCORM.
ADL que es el organizamos que ha definido la norma SCORM ha desarrollado una herramienta ADL TestSuite que permite realizar una prueba del contenido para validar su conformidad respecto a la norma. En este post voy a mostrar como se valida un paquete SCORM con ADL Test Suite.
Leyendo el interesante articulo: A Fusion of Proven Ideas: A Look Behind S#arp Architecture me encontré con la referencia al proyecto T4 Toolbox.
Este proyecto, alojado en Codeplex trae un conjunto de herramientas que permiten crear Generadores de Código dentro del entorno de Visual Studio.
Parece una herramienta interesante!!!! ¿alguien ha tenido alguna experiencia con este producto?
Sharepoint Tagging Solution este proyecto de CodePlex permite etiquetar la información(por medio de un Custom Field) dentro de las listas y bibliotecas.
También se incluye un WebPart de Nube de Tags que permite acceder a la información etiquetada.

Tal y como había prometido HiSoftware
la semana pasada hoy esta disponible la nueva versión(2) del Kit de
Accesibilidad para SharePoint(AKS).
Se puede descargar desde:
https://aks.hisoftware.com/default.aspx

Mientras esperamos con impaciencia la aparición de la próxima versión de SharePoint tenemos que ir adaptándonos a algunos inconvenientes de la actual:-), InfoQ publico la semana pasada un interesante articulo: SharePoint Object Model Performance Considerations, que revisa algunas operaciones "pesadas"(en cuanto al rendimiento) del modelo de objetos de SharePoint.
Recientemente Juan Carlos González Martín contaba en un post las distintas opciones que ofrecía la tecnología SharePoint en cuanto al Multi-Idioma. El post me pareció muy interesante, y le comente a Juan Carlos que una de las opciones para añadir soporte de multi-idioma al interface de usuario es el empleo de HTTP Module. En este post quiero comentar brevemente esta solución.
Un modulo HTTP es un componente de la arquitectura ASP.NET que puede ser conectado(plug-in) en una aplicación WEB y modificar el contenido de la solicitud / respuesta de esta aplicación(algo similar a los filtros ISAPI).
Muchas de las funcionalidades importantes de ASP.NET están basadas en el uso módulos: por ejemplo el soporte de estado de sesión, autenticación basada en formularios y otros).
En Internet podemos encontrar bastante información relativa al tema(se puede empezar por este articulo de MSDN:http://msdn.microsoft.com/es-es/library/bb398986.aspx).
El tema que quería comentar es como un Modulo HTTP nos puede ayudar en ‘traducir’ ciertos literales de las páginas SharePoint para adaptarlos al idioma seleccionado por el usuario.
La idea es la siguiente: en nuestro sitio tendremos que tener algún control de usuario que permita seleccionar el idioma. El idioma seleccionado por el usuario deberá guardase en algún sitio(una variable de sesión, una cookie, el perfil, etc.). Los contenidos, o elementos del interface de usuario contendrán literales traducibles(estos literales deben de estar marcados de alguna forma para que no el modulo no los traduzca). El modulo HTTP que desarrollaremos para este propósito, en cada respuesta reemplazara los literales marcados con el literal que corresponda al idioma seleccionado. Los literales traducidos estarán almacenados en un assembly de recursos, en un XML o incluso en una base de datos. Es importante tener en cuenta que esta solución puede penalizar el rendimiento y la escalabilidad de la aplicación.
A continuación expongo un pequeño ejemplo.
- Primero crearemos el Modulo HTTP, para ello en VisualStudio creamos un nuevo proyecto de tipo ClassLibrary
- El código del Modulo es el siguiente:
using System.Linq;
using System.Text;
using System.Web;
using System.IO;
namespace com.jdiguez.sharepoint
{
public class JdcHttpModule : IHttpModule
{
public JdcHttpModule()
{
}
public String ModuleName
{
get { return "JdcHttpModule"; }
}
void IHttpModule.Dispose()
{
}
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
}
// En el evento de inicio de respuesta HTTP filtramos la salida
// de todos las solcitudes a recursos .aspx
private void Application_BeginRequest(Object source,
EventArgs e)
{
HttpApplication app = source as HttpApplication;
//Test if request is aspx page
if (app.Request.RawUrl.Contains(".aspx") &&
app.Request.RawUrl.Contains("AssetUploader.aspx") == false)
{
app.Response.Filter = new JdcHTTPFilter(app.Response.Filter);
}
}
private class JdcHTTPFilter : Stream
{
private Stream _sink;
public JdcHTTPFilter(Stream sink)
{
_sink = sink;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
_sink.Flush();
}
public override long Length
{
get { return 0; }
}
private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}
public override void SetLength(long value)
{
_sink.SetLength(value);
}
public override void Close()
{
_sink.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer); // HTML de respuesta
if (HttpContext.Current.Response.ContentType == "text/html")
{
// traducimos palabras del dicionario marcadas de forma espacial
// por los literales corespondientes en funcion del idioma actual
html = html.Replace("@DIC_SITE", "sitio");
html = html.Replace("@DIC_OPEN", "abrir");
}
byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}
}
} //class JdcHttpModule
}
Para no complicar el ejemplo no se esta mirando el idioma seleccionado, además se hace un Replace , esto en la vida real debería ser un poco mas complejo(si tenemos 800 palabras para traducir no lo vamos a reemplazar por “si acaso” en todas las páginas).
Ahora compilamos el código y copiamos(o registramos en el GAC, para ello debemos firmar el assembly) la .dll en la carpeta bin de la aplicación WEB que vamos ha intervenir.
Ahora editamos el fichero Web.config de la aplicación, para registrar nuestro modulo y así todas las solicitudes/respuestas de nuestro aplicación SharePoint sean interceptadas y tratadas.
Se tiene que localizar el apartado <httpModules> y introducir el siguiente fragmento(el type debe corresponder con el nombre completo que coresponda a cada caso) :
<add name="JdcHttpModule" type="com.jdiguez.sharepoint.JdcHttpModule, JdcHttpModule, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=00ea9cb4d8e53b60" />
Hacemos un IIRESET de costumbre.
.. y vemos como funciona nuestro modulo, por ejemplo introducimos el literal @DIC_SITE(este es el KEY para nuestro diccionario que corresponde a la palabra sitio) en el titulo del Sitio.
Y vemos el resultado
Como comente antes, esto es un ejemplo muy simple para mostrar la idea de empleo de Módulos HTTP para “traducir” páginas SharePoint, un modulo real para este propósito plantea alguna que otra dificultad, sobre todo para no perjudicar el rendimiento de nuestros sitios SharePoint.
Los sitios basados en SharePoint pueden contener diferentes tipos de páginas:
Diferentes tipos de páginas de SharePoint.
Uno de los tipos de paginas, son las de aplicación(las que se encuentran en la carpeta _layouts/) estas páginas son las que emplea SharePoint para configurar y administrar SharePoint(por ejemplo todas las paginas de la Configuración de Sitio).
Una de las particularidades molestas de estas páginas es que todas las páginas de aplicación utilizan la misma página maestra(independientemente de la colección de sitio o sitio), esto es molesto por que no permite ajustar las paginas de aplicación a los cambios visuales que hagamos en las páginas maestras de las paginas de los distintos sitios.
Hay una forma bastante fácil y efectiva de solucionar este inconveniente. Se trata de desarrollar un HTTP Module que en el evento page_PreInit obtenga la referencia al objeto Page, compruebe si su MasterPageFile es ("application.master")) y le asigne la master page que corresponda
void page_PreInit(object sender, EventArgs e)
{
Page page = sender as Page;
if (page != null)
{
// Is there a master page defined?
if (page.MasterPageFile != null)
{
if (page.MasterPageFile.Contains("application.master"))
{
page.MasterPageFile = "/_catalogs/masterpage/MyCustom.master";
}
}
}
}
Es un truco que encontré en este sitio:
http://markdorison.com/blog/one-master-rule-them-all-using-master-pages-system-pages
El otro día comente sobre el proyecto ce CodePlex SharePoint QuickLaunchExtender que hace uso de jquery para mejorar la experiencia de usuario con el menú QuickLaunch.
SharePoint InstantListFilter es un componente que añade la posibilidad de filtrar las listas de forma "instantánea" escribiendo los valores directamente en un textbox que se encuentra en el header de cada columna de la lista(mejor ver la imagen para entenderlo:-)). Este componente también hace uso de tecnología jquery.

Los Wikis son una impresionante herramienta para crear "Islas de Conocimiento", son fáciles de construir y de consultar.
Una de las razones por la que las Wikis pueden funcionar bien es que son alimentadas por cientos de personas, de esta forma en poco tiempo podemos construir un diccionario, una enciclopedia sobre una temática determinada.
Hace un tiempo comente con los amigos de SUGES(SharePoint Users Group España) la posibilidad de crear un Wiki dedicado a la temática de SharePoint, creo que es un proyecto interesante y podría ser de utilidad para todos los profesionales que nos dedicamos a SharePoint. Espero que esta iniciativa se materialice algún día, mientras tanto podemos encontrar un Wiki bastante interesante(pero en Ingles:-() dedicado al desarrollo con SharePoint: SharePointDevWiki. El contenido es bastante bueno y vale la pena bucear un rato en el.
