Microsoft Theme Builder beta disponible para Office y SharePoint

19.4.11 / Comments (0) / by Unknown

Microsoft ha publicado la beta de un programa más que prometedor: SharePoint Theme Builder, una aplicación de escritorio que permite crear y editar visualmente temas de Office 2007/2010 (ficheros THMX). Evidentemente podemos utilizar los temas generados por este aplicativo para subirlos a SharePoint Foundation y Server 2010 y aplicarlos a nuestros sitios.

image

Podéis descargarlo en http://connect.microsoft.com/ThemeBuilder

 

Requisitos software:

.NET Framework 3.0:

http://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en

Primary Interop Assemblies:

http://www.microsoft.com/downloads/details.aspx?familyid=59daebaa-bed4-4282-a28c-b864d8bfa513&displaylang=en

Herramientas para rastreo de logs de SharePoint (2)

14.4.11 / Comments (2) / by Unknown

Mandíbula desencajada se me ha quedado al conocer gracias a Javier Hidalgo la existencia desde 2009 de ULS Viewer, aplicación de explotación de logs ULS que, por comparación, deja a las dos anteriores herramientas comentadas en la categoría de semi-chusta.

image

ULS Viewer es también un simple ejecutable, descargable desde MSDN (pero al parecer sin soporte de la propia MS), y ofrece todo lo siguiente:

  • Leer eventos de log de ficheros especificados por usuario, de portapapeles o en tiempo real desde los ficheros de log ULS del servidor. Podemos agregar (append) eventos de distintas fuentes.

image

  • Filtrado, por supuesto, por todos los atributos del evento y por distintas operaciones de filtrado. Los criterios de filtro pueden acumularse con ANDs y ORs.

image

  • Notificaciones: es decir, la posibilidad de ser informado en el área de notificaciones de Windows de los eventos críticos o de aquellos eventos filtrados por nuestros criterios. Esta funcionalidad tiene muchas similitudes con el SPTraceView de Hristo Pavlov, herramienta que también circula por el mundillo desde hace tiempo, pero que a mi juicio queda desfasada ante la potencia de ésta.

image

image

  • Posibilidad de definir formato condicional de color para ciertos eventos que cumplan ciertos filtros. Nuestros ojos agradecerán sin duda evitar tanta monocromía.

image

  • Podemos organizar y filtrar los eventos por los Correlation ID.

image

  • Smart Highlight: ésta me encanta. Cuando se activa, al hacer hover encima de un valor determinado de una columna, resalta automáticamente el resto de valores iguales.

image 

  • Podemos añadir bookmarks en los eventos de log.
  • Podemos buscar textualmente en toda la información de log abierta en la sesión.
  • Podemos ocultar/reordenar las columnas de los eventos.
  • Podemos guardar la sesión en ficheros de log o en workspaces (conjunto de fuentes, filtros, formatos y notificaciones configuradas en una sesión).

 

Simplemente apabullante. SharePoint 2010 debería haber contado con algunas si no todas estas funcionalidades de serie. Mis servidores ya no usan otra cosa.

Windows Media Load Simulator: configuración y referencia de errores

13.4.11 / Comments (0) / by Unknown

Al testear una plataforma de Windows Media Services 2008 disponemos de la herramienta Windows Media Load Simulator (conocida también como LoadSim y que no tiene versión específica para 2008 sino que sigue utilizándose la de WMS 9 Series). A continuación lanzo algunos tips de configuración y uso sobre ella.

image

image

  • Puede instalarse sobre Windows XP, Windows 7 o un sistema operativo de servidor como Server 2008.
  • Sirve para probar conexiones unicast RTSP o HTTP (publishing points on-demand), pero no multicast (publishing points broadcast).
  • Debe ejecutarse la herramienta siempre con el usuario con el que se instaló. El motivo es que durante la instalación se realizan algunos cambios sobre ficheros de configuración de Windows Media Player que dependen de usuario.
  • Para habilitar un servidor de Windows Media Services, es necesario:
        • Crear un fichero WMLoad.asf en la carpeta c:\wmpub\wmroot del servidor.
        • Permitir conexiones entrantes sobre el publishing point unicast <Default>.
        • En algunos foros se comenta la necesidad de crear un fichero wmloadsafe.txt en la carpeta c:\, pero por lo menos en las pruebas que he efectuado hasta ahora, la existencia o no de ese fichero no parece determinante.
  • Las URL’s de streams de video deben corresponder todas al mismo servidor (que debe coincidir con el que está configurado en “Default Server”).
  • Lo ideal antes de probar la herramienta de carga es verificar que desde ese mismo equipo con Windows Media Player es posible reproducir el video a testear (si somos capaces de verlo en el reproductor, nos descartará cualquier tipo de problema de conectividad con el servidor, de misspellings con URL’s o de servicios/puntos de publicaciones no iniciados).

 

Errores:

  • SERVER ACCESS DENIED,, Code 0x00000000, Description: The operation completed successfully.
    • Este error puede apuntar hacia varios motivos: no hay conectividad con el host del servidor de video, el servidor está parado, la herramienta no ha podido encontrar el fichero WMLoad.asf o bien el publishing point <Default> está parado.
  • Code: 0x80070002, Description: Error Description Not Found
    • Este error aparece al intentar ejecutar WMLS desde una sesión de un usuario distinto al que instaló la herramienta.
  • Code: 0xC00D2EE6, Description: Error Description Not Found
    • Este error puede aparecer cuando el publishing point del video a testear está parado o al superar el límite de conexiones simultáneas permitidas por el servidor o el publishing point.
  • Code: 0xC00D001A, Description: Error Description Not Found
    • Este error se produce al no encontrar el fichero de video referenciado en el servidor.

 

Para profundizar más sobre el tema:

Checking Server Performance with Windows Media Load Simulator

Libro: Microsoft Windows Media Resource Kit

Entity Framework 4 + WCF + lazy loading: toma solo lo necesario

12.4.11 / Comments (0) / by Unknown

Tema ya trillado en otros idiomas pero sobre el cual me apecete disertar en la lengua de Cervantes. Premisas: trabajamos en un proyecto con Entity Framework 4, que genera nuestro modelo de entidades (con relaciones entre ellas) a partir de nuestro repositorio (típicamente un SQL Server). Exponemos parte de ese modelo a través de una capa de servicios WCF utilizando como valores de retorno de los métodos del servicios las propias clases del modelo. Ningún problema puesto que WCF se encargará de serializar adecuadamente esas clases y las ofrecerá a los clientes del servicio como clases proxy.

Un buen día descubrimos que el aplicativo empieza a ofrecer un rendimiento más que discutible y nos preguntamos por qué. Acude al rescate una herramienta de pago con trial de 30 días que bien vale, por lo menos, evaluarla. Entity Framework Profiler (EFProf), de los conocidos Hibernating Rhinos, permite hacer un profiling de las SQL lanzadas contra nuestra base de datos por el engine de Entity Framework. Simplemente hay que incluir la siguiente llamada en la inicialización de nuestra aplicación (p. ej. en Application_Start de global.asax):

HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();

La herramienta EFProf monitorizará desde ese momento cada todo Object Context de EF y nos mostrará qué comandos SQL está utilizando para cargar datos:

image

Dos cosas: primero, hay un contexto que necesita 97 SQL queries?!?!? Esto es mucho comparado con el resto de contextos. Segundo, ese mismo contexto está lanzando advertencias Using a single object context in multiple threads is likely a bug, SELECT N+1 y Too many database calls per object context.

image

image

Bueno, ahí hay un problema, claramente. Pero esas alarmas es difícil que provengan de mi código. Al fin y al cabo, mi interacción con EF se limita a utilizar queries de LINQ-To-Entity Framework del estilo:

var result = myObjectContext.Reports
.OrderBy(r => r.Title);

¿Como puede generar eso tanta query SQL? Bien, pues desvelo el misterio sin más. Hay dos claves: la primera está en WCF, que juega un papel más importante del que podríamos pensar. WCF necesita devolver los objetos del modelo y para ello serializar sus propiedades y colecciones. El proceso de serialización no sabe lo que hay por debajo, simplemente accede a esas propiedades para obtener sus valores, y punto. La segunda clave es lo que hay realmente por debajo, que es la configuración de lazy loading del Object Context de EF. Por defecto en la versión 4 los contextos son creados con la propiedad LazyLoadingEnabled a true. Esto significa que al acceder a propiedades de un objeto del modelo, si esas propiedades son a su vez otros objetos relacionados, esos accesos van a generar queries de carga adicionales. WCF pide, y EF se lo da. Todo. Propiedad por propiedad. Prácticamente nos estamos trayendo la base de datos entera query a query, sin un solo join que agrupe un poquito las peticiones. Mal.

Lo primero: desactivar el lazy loading en el contexto que utiliza WCF (LazyLoadingEnabled = false). Pero ahora tenemos un problema. Esta configuración produce que la consulta de un objeto no devuelva los objetos relacionados, a menos que se lo especifiquemos manualmente.

Por ejemplo, imaginemos que nuestra entidad Reports tiene relacionados unos Users que deben estar disponibles al realizar la consulta LINQ anterior. Entonces esos users no se cargarán a menos que hagamos algo como lo siguiente:

myObjectContext.LazyLoadingEnabled = false;

var result = myObjectContext.Reports
.Include("Users")
.OrderBy(r => r.Title);

Este eager loading que estamos haciendo utilizando el método Include generará una query SQL con un join entre la tabla de Reports y la de Users, que es lo que buscábamos desde el principio. Vuelta a los clásicos. Y el Entity Framework Profiler contento, puesto que habremos reducido drásticamente la carga de queries.

Bibliografía para insomnes:

EF – Loading related objects

Silverlight: Unable to start debugging. The Silverlight Developer Runtime is not installed

11.4.11 / Comments (0) / by Unknown

Un entorno maravillosamente configurado para desarrollar y debugar sobre Silverlight 4 en Visual Studio 2010 (con las Silverlight Tools 4) te pregunta un día si deseas actualizar Silverlight. Tú, que no tienes un “no” para nadie y menos para una splash screen de actualización, sigues adelante con ello. Después del proceso, dejas de poder ejecutar tus proyectos en Visual Studio a causa de:

Unable to start debugging. The Silverlight Developer Runtime is not installed. Please install a matching version

No panic. La solución consiste simplemente en reinstalar Windows Developer Runtime encima de nuestra instalación y podremos volver a ejecutar y depurar nuestros proyectos.

Reemplazar la página de Access Denied en SharePoint

7.4.11 / Comments (0) / by Unknown

"Have you ever...?" La página de acceso denegado en SharePoint es feucha, y puede ser blanco de las iras de aquellos que han mimado y cuidado hasta el extremo el branding de su portal. De pronto, un usuario accede al sitio, a alguien se le olvida asignar un permiso y... ugh. Qué desagradable.

 

image

image

Y lo bueno (y lo malo) es que por ahora hay dos maneras de evitar esto: controlando las excepciones de acceso denegado por código (SPSecurity.CatchAccessDeniedException) o bien implementando un HttpModule como el siguiente:

using System;
using System.Web;

namespace MyNamespace
{
public class CustomAccessDenied : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += ContextAcessDenied;
}

public void Dispose()
{

}

static void ContextAcessDenied(object sender, EventArgs e)
{
try
{
var httpApp = sender as HttpApplication;
if (httpApp != null)
{
var context = httpApp.Context;

var httpUrl = context.Request.Url.ToString();

if (httpUrl.ToLower().Contains("/_layouts/accessdenied.aspx"))
{
HttpContext.Current.Server.ClearError();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Redirect(
"/Anonymous/Pages/CustomAccessDenied.aspx", false);
}
}
}
catch (Exception ex)
{
//...
}
}

}
}

Este HttpModule redirigiría las peticiones que han devuelto con URL '_layouts/accessdenied.aspx' a una página personalizada que debería estar en un subsitio anónimo de nuestra colección de sitios. Ello implica, sí, habilitar la disponibilidad de acceso anónimo en toda la colección.

Este HttpModule sería, de las dos soluciones, la menos intrusiva en el código de nuestro portal. Y que conste que no soy para nada partidario de hinchar los web apps de handlers y módulos, pero reconozco que en esta ocasión el requerimiento lo merece...

 

Edit: cuidado con la opción "Sign as a different user" del menú Welcome. Redirige a /_layouts/accessdenied.aspx?loginasanotheruser=true&Source=... Tenemos que modificar el HttpModule para que deje pasar estas peticiones.

Localized resource for token 'groupExpColl' could not be found

1.4.11 / Comments (0) / by Unknown

Una de dejar el log de ULS como una patena. Si estamos desplegando features con definiciones de lista, podemos advertir en los ficheros de log las siguientes entradas:

Localized resource for token 'groupExpColl' could not be found 
for file with path: "C:\Program Files\Common Files\Microsoft 
Shared\Web Server Extensions\12\Template\Features\
<nuestra_feature>\<nuestra_lista>\schema.xml
Localized resource for token 'filterIframeTitle' could not be found 
for file with path: "C:\Program Files\Common Files\Microsoft 
Shared\Web Server Extensions\12\Template\Features\
<nuestra_feature>\<nuestra_lista>\schema.xml

Esto se debe a que en el schema.xml que estamos desplegando aparecen dos literales de recursos:

  • $Resources:groupExpColl;
  • $Resources:filterIFrameTitle;

que no hacen referencia explícita a ningún fichero de recursos, pero que están localizados en el “core.resx”. Tenemos dos opciones: o reemplazamos estas ocurrencias por $Resources:core,groupExpColl; y $Resources:core,filterIFrameTitle; o, mucho mejor, si especificamos en nuestro feature.xml:

DefaultResourceFile="core"

Este post es una adaptación libre de http://blogs.msdn.com/b/carloshm/archive/2008/03/13/did-you-find-groupexpcoll-error-in-your-logs.aspx