SPContext, using, RunWithElevatedPrivileges y demás…

Lo que os voy a explicar hoy no es nada nuevo. Mucho se ha escrito al respecto e incluso yo, seguramente, he escrito algún artículo sobre ello, pero el que se hable mucho de una cosa no implica que no sea importante o que no se tenga que ir recordando. El caso es que ayer, a partir de una consulta en un foro, recordé el que es, bajo mi punto de vista, el error que más comunmente cometemos los que desarrollamos sobre SharePoint, y pensé que sería un buen ejercicio escribir este artículo para ver si para todos aquellos que empiezan en esta tecnología (y todos aquellos que llevamos años pero que sistemáticamente cometemos una y otra vez el mismo error…) podría resultar de utilidad.

Comenzaremos por una cosa muy simple: estoy desarrollando un elemento web que tiene que acceder a información que se encuentra alojada en el sitio web donde reside dicho webpart. Lo primero que se plantea uno, es algo como lo del siguiente listado.

SPSite site = new SPSite(url);

SPWeb web = site.OpenWeb();

La variable url la habremos inicializado previamente con alguna información del contexto y lo único que tenemos que hacer es instanciar un objeto SPSite y un objeto SPWeb. Esto no es del todo incorrecto siempre que cuando acabemos de utilizar dichos objetos los eliminemos. Al final, lo que acabaríamos haciendo para trabajar de una manera apropiada sería algo similar a lo siguiente.

using (SPSite site = new SPSite(url))

{

    using (SPWeb web = site.OpenWeb())

    {

    }

}

Si conocéis el objeto SPContext o si lo habéis visto en el código de alguien, os puede pasar por la cabeza la idea de utilizarlo para hacer el código de arriba más ‘correcto’ y cambiarlo por:

using (SPSite site = SPContext.Current.Site)

{

    using (SPWeb web = site.OpenWeb())

    {

    }

}

Y ahí es donde lo romperíamos todo. Si os fijáis, ahora no estamos creando ninguna instancia de SPSite, sino que estamos haciendo una referencia al objeto de nuestro contexto, de manera que en cuanto salgamos del using y se ejecute el dispose estaremos eliminando un objeto que no deberíamos eliminar nunca. ¿Cómo arreglamos el código de arriba?

using (SPSite site = new SPSite(SPContext.Current.Site.ID))

{

    using (SPWeb web = site.OpenWeb())

    {

    }

}

¡Atención! fijáos que uso SPContext.Current.Site.ID y no SPContext.Current.Site.Url como parámetro de la constructora. Aparentemente el resultado es el mismo, pero cuando trabajamos en sitios extendidos la cosa varía un poquito. De todas maneras, si lo que tenéis que hacer es lo de arriba, podéis simplificarlo mucho y dejarlo tal que así:

SPWeb web = SPContext.Current.Web;

Pero aquí es cuando entra en juego nuestro amigo RunWithElevatedPrivileges. ¿Qué pasa cuando desde ese código necesitamos acceder a información con permisos elevados? Nada, que rodeamos el código de esta manera:

SPSecurity.RunWithElevatedPrivileges(delegate

{

    SPWeb web = SPContext.Current.Web;

});

Aquí lo volveríamos a romper todo, ya que el objeto SPContext es, como su nombre indica, una referencia al contexto de SharePoint, que está asociado al usuario autenticado independientemente de que el código se ejecute de manera elevada. La recomendación siempre es hacer uso del RunWithElevatedPrivileges sólo cuando sea estrictamente necesario y en el mínimo ámbito posible y, por lo tanto, todo nos empujaría a hacerlo de la siguiente manera.

using (SPSite site = new SPSite(SPContext.Current.Site.ID))

{

    using (SPWeb web = site.OpenWeb())

    {

        SPSecurity.RunWithElevatedPrivileges(delegate

        {

        });

    }

}

 

Aquí estaríamos cometiendo el mismo error. En el momento en que hemos creado la instancia del objeto SPSite estábamos trabajando en un contexto no elevado y, por lo tanto, así seguiremos siempre que hagamos referencia a éste. Si queremos tratar información de ese objeto SPWeb que viene de la instancia del objeto SPSite creada al inicio del código lo tenemos que hacer de la siguiente manera:

SPSecurity.RunWithElevatedPrivileges(delegate

{

    using (SPSite site = new SPSite(SPContext.Current.Site.ID))

    {

        using (SPWeb web = site.OpenWeb())

        {

        }

    }

});

Para finalizar, deciros que esto es sólo un ejemplo para un caso concreto. En general, trabajar con SharePoint, con su contexto y con la creación de objetos es algo que se tiene que hacer siguiendo ciertas normas. Os dejo un enlace que os puede resultar de interés: http://code.msdn.microsoft.com/SPDisposeCheck

Con esta utilidad podréis comprobar si estáis siguiendo correctamente las normas o no.

CRM 2011 Online ya disponible

Me vuelvo a meter en territorio enemigo para hablaros un poquito de CRM. Y es que hoy, y antes de que la versión Server aparezca, Microsoft ha lanzado la versión para la nube de CRM 2011. Esto deja clara la apuesta de la compañía por todo lo que a Cloud computing se refiere. En cualquier caso, y para aquellos que ya hemos tenido el placer de trastear un poco con el producto, es una gran noticia el que ya podamos disfrutar de la versión final para dejar de trastear y empezar a trabajar.

Os dejo más información aquí:

http://www.microsoft.com/Presspass/Features/2011/jan11/01-17CRMOnline.mspx

Desarrollo en sharepoint para desarrolladores mortales de .NET

El próximo miércoles 2 de Febrero participaré, junto con Gustavo Vélez, Juan Carlos González y Alberto Díaz, en un evento organizado por el grupo MadNUG, y que girará en torno a desarrollo sobre SharePoint. Aquí os dejo el enlace a la página de MadNUG donde se hace referencia a dicho evento.

http://madriddotnet.wordpress.com/2011/01/17/evento-desarrollo-en-sharepoint-para-desarrolladores-mortales-de-net/

Encontraréis ahí enlaces a la página de registro y a la zona online donde podréis ver el evento por Live Meeting.

CryptographicException: The data protection operation was unsuccessful

El haber estado los últimos años dedicándome mayormente a SharePoint ha hecho que me olvidase casi por completo de mi amigo IIS. El problema cuando pasa esto es que después vuelves a trabajar en una aplicación ASP.NET y en ocasiones ves muertos.

En el caso que me ocupa, una serie de razones que ahora no tienen relevancia me llevaron a una serie de decisiones que tienen menos relevancia aún, pero que desembocaron en cambiar el servidor web incorporado en Visual Studio 2010 por mi flamante IIS nuevo de trinca. Todo parecía ir bien hasta qué:

The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread’s user context, which may be the case when the thread is impersonating.

La primera reacción fue correr por la oficina como pollos sin cabeza. De funcionar todo perfectamente excepto un temita que ocasionó la serie de decisiones anteriormente citada pasamos a no poder autenticarnos en el sitio. Afrutanadamente la solución era más simple de lo que parecía y se reducía a lo siguiente:

  1. Abrir Internet Information Services
  2. Acceder, en la lista de application pools, a los advanced settings del pool de aplicaciones asignado a mi sitio web.
  3. Establecer a True el valor de la propiedad Load User Profile en la sección Process Model, tal y como muestra la figura:

image

  1. Continuar con lo que estábamos haciendo hasta entonces 🙂

Cumulative updates de Diciembre 2010 para SharePoint disponibles

Me hago eco de la información publicada por el amigo Juan Pablo referente a la disponibilidad de las actualizaciones mencionadas en el título del post y, para no ser repetitivo, os dejo simplemente el enlace para que veáis lo que contienen dichas actualizaciones así como los enlaces de descarga.

http://surpoint.blogspot.com/2011/01/cu-diciembre-2010-listos-para-moss-2007.html