Flexibilidad de WSSv3: Creación de workflows!

Una de las novedades (como ya habréis leído, oído, probado,…) de WSSv3 es la posibilidad de crear workflows que nos permitan gestionar contenidos, integrarnos con otras aplicaciones, etc. Para definir estos workflows, tenemos dos herramientas tan distintas como son Sharepoint Designer 2007 (SD 2007, Technical Refresh) y Visual Studio 2005 (con las extensiones de Windows Workflow Foundation y las correspondientes plantillas de definición de workflows para WSS, disponibles con el starter kit de la beta 2). En este post  os mostraré como podemos crear el mismo workflow con ambas herramientas, y como la forma de definición, modelado y despliegue del mismo son diferentes, pero conducen al mismo resultado. El workflow que crearemos consistirá en enviar un e-mail al responsable de gestionar los eventos del calendario de nuestra organización cada vez que se cree un ítem en él. Empecemos.

Creación del workflow con SD 2007

Tras abrir nuestro sitio WSSv3 con SD 2007, vamos al menú contextual de creación de workflows con lo que se  abrirá un wizard para la definición del workflow. Le damos un nombre a la instancia de workflow, seleccionamos la lista de WSSv3 que nos interese (en este caso Calendar) y marcamos la opción de que nuestro workflow se inicie de modo automático.

Lo siguiente que haremos es configurar que tiene qué hacer nuestro workflow, en este caso enviar un e-mail cada vez que se cree una nueva entrada en el caledario. Como no vamos a definir ninguna condición para el envío del e-mail, lo único que tenemos que hacer es definir una acción (actividad en VS) de envío de e-mail.

Configuramos adecuadamente el e-mail a enviar cuando se cree el ítem en el calendario: destinatario del e-mail, subject, y el cuerpo del e-mail (en el ejemplo he añadido algunos campos del ítem utilizando la opción Añadir Campos de Búsqueda que nos ofrece SD 2007). Una vez configurado el workflow, probamos que funciona correctamente (botón Comprobar flujo de trabajo) y lo desplegamos contra nuestro sitio WSS (botón Finalizar), y ya tendemos vinculado el workflow con la lista Calendar de nuestro sitio.

Creación del workflow con VS 2005

Para crear el workflow anterior en VS 2005 dentro de la sección de C# escogemos de tipo Windows Sharepoint Services, y seleccionamos la plantilla adecuada (Sharepoint Sequential Workflow Library en este caso, puesto que estamos modelando un workflow de tipo secuencial).

Una vez creado el proyecto, abrimos el archivo workflow1.cs que nos permitirá modelar nuestro workflow de manera visual, así como acceder a la vista de código para definir su comportamiento. Al abrir este fichero, vemos que por defecto ya tenemos una actividad agregada, OnWorkflowActivated, que es la actividad de inicio del workflow. Lo siguiente que haremos será añadir la actividad de envío de e-mail sin más que seleccionarla en la toolbox y arrastrarla a la ubicación correcta en la superficie de diseño (debajo la actividad de inicio).

La actividad de envío de e-mail la tendremos que configurar para que tenga el mismo CorrelationToken que la actividad de inicio y establecer de esta manera el canal de ejecución del workflow. Además, para esta actividad también configuraremos las propiedades Header y Body (bien en modo visual o en la vista de código) para posteriormente definir el e-mail a enviar. Una vez configurado el workflow en modo diseño, tenemos que definir su comportamiento en la vista de código (a través de los Handlers de cada actividad). Este sería el código de los handlers de las actividades del workflow:

//Manejador actividad de inicio del workflow.

        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)

        {

            workflowId = workflowProperties.WorkflowId; //inicializamos el identificador del workflow

        }

      

        //Manejador que envía gestiona el envio del e-mail

        private void sendEmail1_MethodInvoking(object sender, EventArgs e)

        {

            //Variables que contendrán la información a enviar en el e-mail!

            string starttime = "";

            string endtime = "";

            string description = "";

            //Elementos de WSSv3

            SPSite site = new SPSite("http://localhost");

            SPWeb web = site.OpenWeb();

            SPList list = web.Lists["Calendar"];

            SPListItemCollection listcollection = list.Items;

            foreach (SPListItem listitem in listcollection)

            {

                if ((string)listitem["Title"] == (string)workflowProperties.Item["Title"])

                {

                    for (int i = 0; i < listitem.Fields.Count; i++)

                    {

                        SPField campo = listitem.Fields[i] ;

                        if (campo.InternalName == "EventDate"

                                || campo.InternalName == "EndDate"

                                || campo.InternalName == "Description")

                        {

                            if (listitem[campo.InternalName] != null)

                            {

                                //Fecha de inicio del evento

                                if (campo.InternalName == "EventDate")

                                {

                                    starttime = listitem[campo.InternalName].ToString();

                                }

                                //Fecha de fin del evento

                                if (campo.InternalName == "EndDate")

                                {

                                    endtime = listitem[campo.InternalName].ToString();

                                }

                                //Descripción del evento

                                if (campo.InternalName == "Description")

                                {

                                    description = listitem[campo.InternalName].ToString();

                                }

                            }

                        }

                    }

                }

            }

            //Configuramos el e-mail a enviar!

            cabecerasEmail.Add("To", "jcgonzalez@ciin.es");

            cabecerasEmail.Add("Subject", "Nuevo evento en el calendario!");

            cabecerasEmail.Add("From", workflowProperties.OriginatorEmail);

            cuerpoEmail = "Se ha programado un nuevo evento en el calendario:  " + workflowProperties.Item["Title"] +

                               ". Características del evento: <br>" + description + "<br>" +

                               "La duración del evento será de " + starttime + " a " + endtime + ".";

                               

        }

Lo siguiente que tenemos que hacer es compilar nuestro assembly, firmarlo (puesto que para poder desplegarlo en WSS es condición indispensable) y ya estamos listos para desplegarlo  (lo haremos como una feature, que es la opción que nos da por defecto VS 2005) en el sitio de WSSv3, para ello tenemos que realizar los siguientes pasos:

§  Configurar el fichero de feature adecuadamente (tiene que referenciar al fichero de manifiesto del workflow).

§  Configurar el fichero de manifiesto, siendo la sección más importante la siguiente:

<Workflow

       Name="Ejemplo de Workflow secuencial"

       Description="Ejemplo de workflow que crea una tarea de revisión."

       Id="FE543FCF-DCB3-41b5-BA88-4C783C6C0B43"

       CodeBesideClass="VS2005_WSS_Sequential_Workflow.Workflow1"

       CodeBesideAssembly="VS2005_WSS_Sequential_Workflow, Version=3.0.0.0, Culture=neutral, PublicKeyToken=67c7fb61eb566506">

    <Categories/>

§  Configurar adecuadamente el archivo de instalación de la feature para que registre el assembly en la caché del servidor de WSSv3, instale la feature y la active.

Si todo ha ido bien, tendremos disponible nuestro workflow en el sitio de WSSv3. Para comprobarlo, vamos a asociar el workflow a la lista de tipo calendario (a través de List Settings -> Workflows Settings) de WSS.

Una vez creada la instancia del workflow, veremos como en la lista Calendar tenemos dos workfows disponibles.

Probando los workflows

Para probar los workflows, basta con que creemos un nuevo elemento en el calendario y comprobemos que nos llegan dos e-mails avisándonos de que tenemos un nuevo evento en el mismo.

Finalmente, para cerrar el post os pongo una comparativa de las implicaciones de modelar workflows con SD 2007 o VS 2005.

Worflows diseñados con el Diseñador VS 2005

Workflows diseñados con SD 2007

Se pueden escribir workflows para WSS o MOSS.

Se pueden escribir workflows para WSS o MOSS.

Los archivos de código permiten escribir código customizado para modelar procesos de negocio.

El fichero de reglas de workflow encapsula los procesos de negocio.

Se pueden asociar a múltiples sitios y listas.

Sólo se pueden asociar a una única lista en tiempo de diseño.

Los distintos ficheros que componen el workflow se compilan en un assembly.

Los distintos ficheros que componen el workflow se almacenan sin compilar en una librería de documentos específica de WSS.

El workflow (template) ha de estar asociado con cada lista o elemento en que debe estar disponible.

La asociación se da en el momento en que se crea el workflow en una cierta lista.

Se puede usar cualquier tipo de formulario: ASPX o InfoPath.

Solo se pueden utilizar formularios de tipo ASPX.

Worflows diseñados con el Diseñador VS 2005

Workflows diseñados con Sharepoint Designer 2007

Se pueden incluir modificaciones en el workflow

No permite incluir modificaciones en el workflow.

Se puede crear actividades customizadas.

Sólo se pueden usar las actividades disponibles

El assembly y definición del workflow se empaquetan como una feature de WSS, y luego se despliegan en el sitio (manual).

El despliegue es realizado de forma automática.

Se puede usar un formulario de inicialización para recoger información del usuario cuando se arranca el workflow.

Se puede usar un formulario de inicialización para recoger información del usuario cuando se arranca el workflow.

Se pueden usar formularios customizados para interactuar con tareas de WSS.

Se pueden usar formularios customizados para interactuar con tareas de WSS.

Disponible debugging de VS.

No es posible el modo debugging.

Se pueden crear workflows secuenciales y de máquina de estados.

Sólo se pueden crear workflows de tipo secuencial.

Bueno, puesto esto ha sido todo. Espero que el post os resulte de utilidad.

Uso de content types y features en WSS v3

Tratando de seguir el testigo de los excelentes artículos de Carlos Segura sobre la nueva funcionalidad de content types en SharePoint Services v3, vamos a intentar explicar un ejemplo concreto de su uso, que el propio producto utiliza en las Team Discussions, y con ello ver el mecanismo de empaquetado de soluciones de las features.

La implementación de grupos de discusión en SharePoint es muy sencilla, existe una plantilla de librería que se puede instanciar en un sitio, ofreciendo la funcionalidad de crear posts y respuestas, con dos tipos de vista, plana o jerarquizada.

 

Como con cualquier lista de SharePoint, es posible activar la aprobación de nuevos posts (no se ven hasta que un administrador los aprueba) o el versionado (para hacer seguimiento de quién los ha modificado). En caso de activar estas funciones, podemos controlar quién ve los posts que están en estado ‘draft’ (si tenemos versionado y estamos trabajando en ellos) o ‘pending’ (si hemos activado la aprobación de contenidos y estamos esperando a que un administrador los apruebe).

 

Al entrar dentro de uno de los threads, se muestran los mensajes asociados en función de una vista de SharePoint.

De forma plana:

 

O jerarquizada:

 

Veamos la estructura de información que da soporte a esta lista. Los diseñadores de SharePoint han activado la capacidad de almacenar diferentes content types. De esta forma, la lista es una especie de almacén de objetos estructurados, cada uno de ellos con sus propios campos. Adicionalmente, la lista puede añadir columnas a las aportadas por los content types, de forma que lo almacenado finalmente es la unión de las columnas diferentes de todos los content types y las restantes que defina la lista.

 

El content type Discussion deriva de Folder (una carpeta para organizar elementos en una lista), que a su vez desciende de Item, el elemento básico de una lista. Discussion añade a folder un campo body (el contenido del post) y un campo de email.

 

Message hace algo parecido, desciende de Item y le añade los campos de body y email.

 

El funcionamiento es sencillo (ya veremos como no lo es tanto), en el primer nivel se crean elementos de tipo discussion, y por debajo de ellos elementos message. Hay una vista predeterminada que nos muestra los elementos de tipo discussion de primer nivel, y al entrar en uno de estos elementos, hay disponibles dos vistas adicionales, la plana (todos los elementos por debajo de esta discussion) y la threaded, que muestra las relaciones entre mensajes. Estas vistas están desarrolladas con formularios de presentación personalizados.

Evidentemente, con los campos que se muestran a través de la web, es imposible hacer todo esto. Faltan las relaciones entre posts para crear las jerarquías, los campos calculados como Replies, que cuenta los posts que hay por debajo de un folder… Toda esta lógica está implementada en una feature (el elemento para empaquetar cualquier tipo de solución en SharePoint 2007), que se encuentra activa por defecto en WSS.

Para ver cómo funciona, es necesario ir a la definición de la feature, que se puede encontrar en la carpeta Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12TEMPLATEFEATURES, en este caso en la carpeta DiscussionList.

Dentro de la feature DiscussionsList se encuentra el fichero schema.xml que contiene la definición completa de la lista, sus ContentTypes, campos, vistas, formularios personalizados, que implementan las funcionalidades de la lista.

Los dos content types tienen bastantes más campos, que al tener una propiedad hidden, no se muestran en la vista Web. La definición completa se puede encontrar en el fichero ctypectypeswss.xlm, de la carpeta FEATURES. en la imagen de abajo podemos verlos en una versión modificada de la página aspx que muestra las propiedades.

 

Cuando comparamos los campos que se ven en la vista web y los de los tipos de contenidos, vemos que no aparecen algunos campos que luego si aparecen en las diferentes vistas. Por ejemplo el campo calculado ‘Replies’, que contiene el número de ítems por debajo de una carpeta. Vamos a seguir los pasos que SharePoint da para definir un campo como este.

La etiqueta ‘Replies’ se toma del fichero general de recursos multi-idioma, en el caso de nuestra instalación ‘core.en-US.resx’ que se encuentra en el directorio Program FilesCommon FilesMicrosoft Sharedweb server extensions12Resources. A la etiqueta ‘Replies’ le corresponde un nombre de campo ‘Reply_Count’.

 

Con la identificación del campo, buscamos en el fichero schema.xml de nuestra lista dónde se referencia, y observamos que es el campo con el nombre ‘ItemChildCount’ dentro del parámetro DisplayName="$Resources:core,Reply_Count;"

Su definición completa es esta:

<Field ID="{b824e17e-a1b3-426e-aecf-f0184d900485}"
 Name="ItemChildCount"
 SourceID=http://schemas.microsoft.com/sharepoint/v3
 StaticName="ItemChildCount"
 Group="_Hidden"
 ReadOnly="TRUE"
 Filterable="FALSE"
 Hidden="FALSE"
 DisplayName="$Resources:core,Reply_Count;"
 Type="Lookup"
 List="Docs"
 FieldRef="ID"
 ShowField="ItemChildCount"
 JoinColName="DoclibRowId"
 JoinRowOrdinal="0"
 JoinType="INNER">
</Field>

El campo es de tipo Lookup (una búsqueda dinámica sobre una lista), en este caso aplicada a la propia lista Docs. Muestra como resultado el campo ItemChildCount, una propiedad de SPBuiltInFieldId. La información del SDK no recoge todavía la información detallada sobre estos campos. Los joins permiten generar lookups uniendo las listas de origen y destino (en este caso, son la misma). El resultado es que podemos contabilizar los ítems que cuelgan por debajo de un folder, que en este caso corresponde a las respuestas por debajo de un post.

Esperamos que con la publicación de la Beta2TR se complete la documentación para conocer el funcionamiento detallado de las nuevas características y se arreglen los problemillas que tiene por ahora este excelente producto.

Problemas con la optimización TCPIP en Windows Vista

Hola,

Si estáis probando las betas de Windows Vista, es posible que os encontréis con problemas con las comunicaciones, páginas que se empiezan a abrir pero no terminan de descargar. Parace que tiene que ver con la incorrecta implementación en algunos routers domésticos de optimizaciones de tamaños de ventanas y retransmisiones del protocolo TCP/IP, que Vista activa por defecto.

Para beta 2 Microsoft publicó un parche, y en la RC1 debería estar resuelto, pero al menos con nuestro router, un Linksys RV082, sigue fallando, tanto para conexiones salientes como entrantes. La inspección de paquetes SPI del firewall descarta paquetes y las comunicaciones se bloquean, salvo que se desactive el FW.

Si os pasa, se pueden deshabilitar las optimizaciones automáticas de Vista desde un cmd, con esta línea:

   netsh interface tcp set global autotuninglevel=disabled

Como netsh está controlado por UAC, no permite el cambio directamente, es preciso hacerlo como administrator, para ello, crear un acceso directo a un cmd, botón derecho, "run as administrator".

Saludos,

Saludos desde Cantabria

Hola,

Os escribimos desde el Centro de Innovación en Integración de Cantabria, un proyecto creado por el Gobierno de Cantabria y Microsoft para ayudar a las empresas TIC regionales a acceder a las últimas tecnologías y que puedan ser más competitivas.

Estamos trabajando sobre SharePoint 2007, WCF, WWF y Biztalk, y esperamos poder contar cosas en una comunidad tan interesante y experta como esta.

Gracias a los administradores de Geeks y a la gente de Plain Concepts por la oportunidad de participar.

Saludos,