Parte 5 del kit de herramientas de integración de notificaciones, Azure y SharePoint

Esta es la quinta parte de una serie de cinco partes sobre el kit CASI (del inglés Claims, Azure, and SharePoint Integration).  En la parte 1 vimos una introducción general de todo el marco y la solución, así como una descripción de los temas que se cubrirán en la serie.  En la parte 2 se proporcionaron instrucciones para crear aplicaciones WCF, configurarlas para notificaciones y, a continuación, moverlas a Windows Azure.  En la parte 3 vimos una descripción de la clase base que usará para conectar el sitio de SharePoint con datos de Azure, agregando un nuevo control personalizado a una página en el directorio _layouts.  En la parte 4 vimos una descripción del elemento web que se incluye en el kit CASI y cómo usarlo, sus diferentes propiedades, etc.  En esta última entrada, veremos los otros dos escenarios básicos de este kit: el uso del control personalizado creado en la parte 3 para recuperar datos de Azure y almacenarlos en la memoria caché de ASP.NET para usarlos con otros controles, y cómo usarlos en una tarea de SharePoint; en este caso, un trabajo de temporizador de SharePoint personalizado.

Uso del control en otros elementos web

Uno de los escenarios básicos que había que hacer compatible era el uso del marco del kit CASI para recuperar datos que se van usar en otros elementos web de SharePoint.  También queda el otro objetivo de diseño, que consistía en NO introducir llamadas del lado servidor de rutina en extremos de WCF remotos potencialmente latentes.  Para intentar conciliar estas dos necesidades divergentes, la clase base implementa la compatibilidad para recuperar los datos y almacenarlos en la memoria caché de ASP.NET directamente.  Esto permite desarrollar otros elementos web personalizados y seguir un modelo bastante simple:

1.       Compruebe si los datos están en la memoria caché de ASP.NET.

a.       Si están, puede recuperarlos desde allí

b.      Si no están:

                                                              i.      Cree una instancia del control personalizado

                                                            ii.      Establezca OutputType en ServerCache, y ServerCacheName y ServerCacheTime en los valores adecuados

                                                          iii.      Llame al método ExecuteRequest y obtenga los datos

Para empezar, inicie un nuevo proyecto de Visual Studio: en este caso, supondré que se usa Visual Studio 2010 para que podamos crear un nuevo proyecto de SharePoint 2010.  Configure el proyecto para crear un nuevo elemento web y, a continuación, agregue dos referencias: una para la clase base del kit CASI y otra para el control personalizado que escribió en la parte 3.  Tenga en cuenta que si no agrega una referencia a la clase base del kit CASI, cuando intente establecer una de las propiedades del control, Visual Studio la subrayará con una marca ondulada de color rojo y le indicará que no puede encontrar la propiedad.  Si ve ese tipo de error, sabrá que aún no ha agregado la referencia a la clase base del kit CASI.

Una vez establecidas las referencias, puede escribir cualquier código que sea adecuado para el elemento web.  Cuando llegue al punto en el que necesite extraer datos de Azure, como contenido, información de configuración, etc., aquí hay un ejemplo de cómo se implementa el modelo descrito anteriormente:

string CACHE_NAME = "AzureConfigConsumerCacheSample";

int CACHE_TIME = 10;

 

//create a var of the type of configuration data we want to retrieve

AzureWcfPage.CustomersWCF.Customer[] Customers = null;

 

//look for our item in cache

if (HttpContext.Current.Cache[CACHE_NAME] != null)

{

//if we find, it cast it to our type and pull it out of cache

       Customers =

(AzureWcfPage.CustomersWCF.Customer[])

HttpContext.Current.Cache[CACHE_NAME];

}

else

{

//if it's not in cache, then retrieve it and put it into cache

 

       //create an instance of the control

       AzureWcfPage.WcfDataControl cfgCtrl = new AzureWcfPage.WcfDataControl();

 

       //set the properties to retrieve data

       cfgCtrl.WcfUrl = "https://azurewcf.vbtoys.com/Customers.svc";

       cfgCtrl.OutputType = AzureConnect.WcfConfig.DataOutputType.ServerCache;

       cfgCtrl.ServerCacheName = CACHE_NAME;

       cfgCtrl.ServerCacheTime = CACHE_TIME;

       cfgCtrl.MethodName = "GetAllCustomers";

 

       //execute the method

       bool success = cfgCtrl.ExecuteRequest();

 

       if (success)

       {

//get the strongly typed version of our data

//the data type needs to come from the control we are creating

Customers =

(AzureWcfPage.CustomersWCF.Customer[])cfgCtrl.QueryResultsObject;

 

              //if you wanted the Xml representation of the object you can get

              //it from QueryResultsString

              string stringCustomers = cfgCtrl.QueryResultsString;

}

       else

       {

              //there was some problem; plug in your error handling here

       }

}

 

Veamos parte del código en más detalle.  En primer lugar, es importante comprender que en el nuevo elemento web NO es necesario agregar una referencia de servicio al extremo de WCF.  Ya está encapsulada en el control personalizado, por lo que se pueden usar los tipos de valor devueltos de la aplicación de WCF que se exponen a través del control personalizado.  Esta línea de código demuestra lo siguiente:

//create a var of the type of configuration data we want to retrieve

AzureWcfPage.CustomersWCF.Customer[] Customers = null;

En este ejemplo, AzureWcfPage era mi ensamblado de control personalizado.  CustomersWCF era el nombre que asigné a la referencia de servicio WCF.  Y Customer es el tipo de clase que devolvió mi método WCF.  Todo esto se transmitió al nuevo elemento web cuando agregué la referencia al ensamblado de control personalizado.

La primera comprobación que hago es ver si los datos están en la memoria caché; si están, simplemente los vuelco a la matriz de instancias de Customer que había almacenado anteriormente.  Si no están en la memoria caché, simplemente escribo las siete líneas de código necesarias para crear una instancia de mi control personalizado y recuperar los datos.  Es necesario:

a.       Crear una nueva instancia del control

b.      Establecer las propiedades WcfUrl, MethodName, OutputType, ServerCacheName y ServerCacheTime

c.       Llamar al método ExecuteRequest

¡Listo!  Si el método se completa correctamente, el valor devuelto por la aplicación de WCF se almacena en la memoria caché de ASP.NET y la próxima vez que se ejecute este código, encontrará el elemento allí.  Mientras tanto, puedo convertir la variable local Customers a la propiedad QueryResultsObject del control personalizado y, a continuación, puedo hacer todo lo que necesite mi elemento web con los datos.  En general, esto debería resultar relativamente sencillo y fácil de implementar para la mayoría de los desarrolladores de elementos web.

Uso del control en una tarea

Ahora voy a describir cómo usar el control personalizado que desarrolló en la parte 3 para recuperar datos de contenido o de configuración de Azure para usar en una tarea.  En este ejemplo, escribí un trabajo del temporizador de SharePoint personalizado, y en él voy a recuperar algunos datos de Azure.  El modelo es bastante similar al componente web descrito anteriormente, pero en este caso, al igual que con muchas tareas, no hay un HttpContext, por lo que no se puede usar la memoria caché de ASP.NET.  En ese caso OutputType va a ser None, ya que no es necesario representarlo en una página ni almacenarlo en la memoria caché; en su lugar simplemente extraeremos el directorio de valor de QueryResultsObject y QueryResultsString.  Aquí hay un un código de ejemplo: es código de la invalidación del método Execute de mi clase de trabajo del temporizador personalizado:

SPWebApplication wa = (SPWebApplication)this.Parent;

 

//create an instance of the control

AzureWcfPage.WcfDataControl cfgCtrl = new AzureWcfPage.WcfDataControl();

 

//set the properties to retrieve data

cfgCtrl.WcfUrl = "https://azurewcf.vbtoys.com/Customers.svc";

cfgCtrl.OutputType = AzureConnect.WcfConfig.DataOutputType.None;

cfgCtrl.MethodName = "GetAllCustomers";

 

//since there's no Http context in a task like a timer job, you also need to

//provide the Url to a claims-enabled SharePoint site.  That address will be used

//to connect to the STS endpoint for the SharePoint farm

cfgCtrl.SharePointClaimsSiteUrl = wa.Sites[0].RootWeb.Url;

 

//execute the method

bool success = cfgCtrl.ExecuteRequest();

 

//check for success

if (success)

{

//now retrieve the data and do whatever with it

       AzureWcfPage.CustomersWCF.Customer[] Customers =

(AzureWcfPage.CustomersWCF.Customer[])cfgCtrl.QueryResultsObject;

 

       string AzureResults = cfgCtrl.QueryResultsString;

 

//this is where you would then do your tasks based on the data you got from Azure

foreach(AzureWcfPage.CustomersWCF.Customer c in Customers)

       {

Debug.WriteLine(c.Email);

       }

 

       Debug.WriteLine(AzureResults);

}

else

{

//do something to log the fact that data wasn't retrieved

}

 

A continuación explicaré este código con más detalle.  El trabajo del temporizador es un trabajo con ámbito de aplicaciones web, por lo que comenzaremos por obtener una referencia a SPWebApplication para la que se está ejecutando este trabajo haciendo referencia a la propiedad Parent.  A continuación, creamos el control personalizado que hicimos en la parte 3 y establecemos las propiedades mínimas que se necesitan para recuperar los datos de Azure.  En la siguiente línea de código debemos establecer la propiedad SharePointClaimsSiteUrl.  Tal como expliqué en la parte 3, cuando se ejecuta la clase base del kit CASI a través del método ExecuteRequest, ésta comprueba si tiene un HttpContext disponible.  Si lo tiene, usará dicho contexto para averiguar la dirección URL actual del sitio de SharePoint y establecer la conexión con el STS de SharePoint a través de dicho sitio.  Pero como ya he señalado anteriormente, cuando el código se está ejecutando en una tarea, normalmente no hay un HttpContext.  En ese caso, la clase base no puede determinar qué dirección URL debe usar para conectarse al STS de SharePoint. Entonces, es necesario darle la dirección URL a un sitio en una aplicación web habilitada para notificaciones.  El código de trabajo del temporizador en esta implementación supone que SOLO se va a ejecutar en aplicaciones web habilitadas para notificaciones. Por esa razón, obtenemos la referencia a la actual aplicación web y, a continuación, simplemente le pasamos la dirección URL a la primera colección de sitios.  No importa qué colección de sitios se usa, siempre y cuando esté en una aplicación web habilitada para notificaciones.

Una vez que hayamos establecido la propiedad SharePointClaimsSiteUrl, podemos llamar al método ExecuteRequest, tal como se demostró anteriormente.  Si se ejecuta correctamente, podemos extraer los datos del control directamente a través de las propiedades QueryResultsObject y QueryResultsString.

Tanto el elemento web como el trabajo del temporizador se incluyen en el archivo ZIP adjunto a esta entrada.

¡Esto es todo!

Ésta es la entrada de blog final de la serie. Espero que ahora entiendan mejor el kit CASI y cómo se puede usar para conectarse fácilmente a los datos hospedados en una aplicación de WCF en el sitio o en la nube y, al mismo tiempo, usar el token de identidad del usuario en diferentes aplicaciones e incluso más allá de los límites del centro de datos.  En resumen, el modelo es relativamente fácil de implementar:

1.       Cree un front-end de WCF al contenido o a los datos de configuración.  Habilítelo para notificaciones y, si lo desea, súbalo a la nube.  Como opción, también puede implementar decisiones de permisos más específicas en función de las notificaciones y la identidad del usuario que llama.

2.       Escriba un control personalizado que herede de la clase base del kit CASI.  Invalide un método y escriba cinco líneas de código.  Agregue el control a la página de diseños simples e impleméntelo.

3.       Agregue el elemento web a una página, establezca una o varias propiedades y empiece a representar los datos de WCF.  Si lo desea, puede usar el control para recuperar el contenido o los datos de configuración en un elemento web personalizado o una tarea, como un trabajo del temporizador personalizado.

Eso es todo, básicamente.  Espero que el kit CASI le facilite la conexión de la granja de servidores de SharePoint a los datos almacenados en cualquier lugar del mundo.  También le facilitará la recuperación de datos de configuración o personalización, así como el contenido, para su presentación en sitios de SharePoint.  Además, ahora tiene la flexibilidad necesaria para usar la seguridad que implemente en su organización en diferentes aplicaciones y más allá de los límites del centro de datos.  Fue un placer concebir, diseñar y desarrollar esta serie de artículos y espero que le resulte útil.  Como siempre, ésta es la primera versión y estoy seguro de que hay muchas cosas que se pueden mejorar. Por lo tanto, no dude en agregar sus comentarios a estas entradas de blog. Las revisaré periódicamente para tenerlas en cuenta para la próxima gran versión.

Esta entrada de blog es una traducción. Puede consultar el artículo original en The Claims, Azure and SharePoint Integration Toolkit Part 5