Crear acción personalizada para Flujo de Trabajo Sharepoint 2010

En esta primera entrada hablaré sobre un aspecto con el que he estado trabajando en estos últimos días y está relacionado con crear acciones personalizadas para workflows en Sharepoint Designer. La verdad es que, si bien la información que podemos encontrar es bastante, es muy difusa y a la hora de sacar algo en claro resulta complejo. Por tanto a lo largo del post intentaré explicar como desarrollar una acción personalizada que ponga de manifiesto todos los tópicos que pueden ser necesarios a la hora de abordar este tipo de desarrollos, o que al menos, lo han sido para mi.

Vamos a desarrollar una acción personalizada que va a actualizar uno de los campos del elemento actual sobre el que se está ejecutando el flujo de trabajo. De esta forma trabajaremos sobre varios tópicos en el desarrollo de acciones personalizadas:

  1. Desarrollo de acciones personalizadas para flujos de trabajo en Sharepoint Designer 2010.
  2. Acceso por medio de código del elemento actual sobre el que se está ejecutando el Workflow.
  3. Modificación de los campos del elemento actual a través de un parámetro pasado desde la acción en Sharepoint Designer.
  4. Definición del archivo Element.xml donde se va a encontrar la especificación de la acción para poder incluirla en Sharepoint Designer.

Para empezar, en primer lugar lo que hay que hacer es crear el proyecto en Visual Studio 2010 donde se va a desarrollar la acción personalizada. Para ello seguimos los siguientes pasos:

  1. Hacemos click en Archivo->Nuevo Proyecto.
  2. Seleccionamos la plantilla de Sharepoint 2010, Proyecto de SharePoint vacío. Podemos darle como nombre al proyecto EjemploCustomAction.
  3. A continuación se abre el asistente para la personalización de Sharepoint. Indicamos en primer lugar la dirección del sitio de SharePoint a donde queremos referenciar la actividad y a continuación marcamos la casilla Implementar como solución enespacio aislado. y pulsamos en Finalizar.
Tras esto se crea nuestro proyecto. El siguiente paso va a ser crear la clase que va a contener la acción personalizada propiamente dicha. Para ello haremos click en el botón derecho de nuestro ratón en el nombre del proyecto en el explorador de soluciones (situado habitualmente en la parte derecha de la interfaz de Visual Studio 2010) y pulsamos Agregar->Clase. A la clase la llamaremos ejemplo.cs.
De esta forma se crea la clase. Lo primero en lo que nos vamos a centrar es en las referencias y namespaces que tenemos que referenciar. Inicialmente tendrán que aparencer al menos las siguintes directivas using:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint.UserCode;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

using System.Collections;</pre>
Las más importantes son las que hacen referencia a la API de SharePoint. A continuación os muestro el código de la clase completa y posteriormente iré explicando los aspectos importantes de dicho código, así espero que se vea más claro el código propiamente dicho.
namespace EjemploCustomAction
{
    class ejemplo
    {
        public Hashtable manejadorDocumentacion(SPUserCodeWorkflowContext context, string ListId, int ListItem, string Tipo)
        {
            Hashtable resultado = new Hashtable();
            resultado["Except"] = String.Empty;

            try
            {
                using (SPSite site = new SPSite(context.CurrentWebUrl))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        //Se carga la lista y el item actual desde el que se esta ejecutando el flujo de trabajo
                        SPList list = web.Lists[new Guid(ListId)];
                        SPListItem listItem = list.GetItemById(ListItem);

                        //Se realiza la actualizacion de ls lista correspondiente con el valor calculado
                        site.AllowUnsafeUpdates = true;
                        web.AllowUnsafeUpdates = true;

                        listItem["columnaEjemplo"] = Tipo;

                        listItem.Update();
                        list.Update();
                    }
                }
            }
            catch (Exception ex)
            {
                 System.Console.Write(ex.ToString());
            }
            finally
            {
                 site.AllowUnsafeUpdates = false;
                 web.AllowUnsafeUpdates = false;
            }

            return resultado;
        }
    }
}

Vamos a resaltar los aspectos más importantes y que es importante destacar del código anterior:

  • Debemos crear un método (manejadorDocumentacion en nuestro caso) que devuelva un objeto del tipo HashTable y que será el método invocado cuando ejecutemos las acción desde el Workflow. Además dicho método tendrá al menos un parámetro, que será SPUserCodeWorkflowContext context y que contendrá la información del contexto en que se está ejecutando la acción dentro del Workflow.
  • En la misma declaración de la función aparecen otros parámetros importantes y que nos van a permitir obtener la información del item actual sobre el que se está ejecutando el workflow. Estos parámetros son string ListId y int ListItem, además por último tenemos un parámetro llamado Tipo que será el que vamos a utilizar para actualizar la lista correspondiente.
  • Con las líneas 12 y 14 cargamos el sitio sobre el que se está ejecutando el workflow, lo que nos dará acceso a toda la información de ese sitio de SharePoint a través de los métodos y propiedades del objeto del tipo SPWeb.
  • En las líneas 17 y 18 se ejecuta el código que nos va a permitir acceder al elemento actual. La primera va a cargar la lista correspondiente de SharePoint a la que pertenece el elemento. La siguiente carga dentro de esa lista la información del item actual sobre el que se está trabajando.
  • El resto del código que se ejecuta es el que nos permite variar el dato de una de las columnas de la lista y actualizarlo, para hacer efectiva la actualización se usa el método update() de los objetos del tipo SPList y SPListItem
Una vez tenemos el código el siguiente paso es crear el archivo .xml que utilizará posteriormente SharePoint Designer para entender la acción que hemos desarrollado. Para ello, sobre el nombre del proyecto hacemos click en el botón derecho y agregar->Nuevo Elemento y Elemento Vacío. Se crea un archivo llamado Element.xml. Este archivo contendrá los siguientes elementos que explicaremos a continuación.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <WorkflowActions>
    <Action Name="Actualizar Documentacion Lista"
            SandboxedFunction="true"
            Assembly="$SharePoint.Project.AssemblyFullName$"
            ClassName="EjemploCustomAction.ejemplo"
            FunctionName="manejadorDocumentacion"
            AppliesTo="all"
            Category="Acciones Personalizadas">
      <RuleDesigner Sentence="Actualizar lista valor %1 en el elemento %2(Exception to %3)">
        <FieldBind Field="Tipo"
           Text="Tipo del elementos actual" Id="1"
           DesignerType="StringBuilder"/>
        <FieldBind Field="ListId,ListItem" Text="Este elemento" Id="2" DesignerType="ChooseListItem" />
        <FieldBind Field="Except"
                   Text="Exception" Id="3"
                   DesignerType="ParameterNames" />
      </RuleDesigner>
      <Parameters>
        <Parameter Name="__Context"
                   Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,
                   Microsoft.SharePoint.WorkflowActions"
                         Direction="In"
                         DesignerType="Hide"/>
        <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In"/>
        <Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In"/>
        <Parameter Name="Tipo"
                   Type="System.String, mscorlib"
                         Direction="In"/>
        <Parameter Name="Except"
                   Type="System.String, mscorlib"
                   Direction="Out"
                   DesignerType="ParameterNames"
                   Description="Exception encountered"/>
      </Parameters>
    </Action>
  </WorkflowActions>
</Elements>

Vamos ahora a explicar el fichero Element.xml y los aspectos más importantes del mismo:

  • Empezaremos por la etiqueta <action>, en esta etiqueta se van a definir los aspectos de la acción en para SharePoint Designer. Los atributos más importantes de esta etiqueta van a ser ClassName y FunctionName, el primero de ellos indica el namespace y el nombre de la clase que contiene la acción. El segundo de ellos indica el método de la clase que contiene a la propia acción.
  • La etiqueta <RuleDesigner> contiene la descripción de la acción que aparecerá en SharePoint Designer. Para indicar en los puntos en los que aperecerán parámetros en la acción de SPD 2010 se usará %1, %2, %3 para cada parámetro sucesivamente.
  • Las características y tipos de esos parámetros se definirán en las siguientes etiquetas <FieldBind>. El atributo Field indica el nombre del parámetro, el atributo Text indica el texto que aparecerá en SPD 2010 y atributo ID hace referencia al atributo y por último DesignerType especifica el tipo de atributo en SPD 2010. Es importante destacar aquí el segundo tag <FieldBind> que es el que nos va a permitir capturar la información relativa al Item actual y que después usamos como se indicó en el código de la acción.
  • Las siguientes etiquetas hacen referencia a los parámetros que se ejecutan para la acción en el código. Cada etiqueta <parameter> hace referencia a cada parámetro. El primer parámetro es un tipo especial que hace referencia al contexto y siempre se utilizará de la misma forma. El resto hacen referencia a los distintos parámetro del método. Siempre hay que incluir un elemento de salida (el último parámetro que se indica) para capturar el return del método.

Por último y antes de publicar la acción que hemos desarrollado y poder trabajar con ella en SPD 2010 vamos a modificar la característica que se creó en el directorio del proyecto. Para ello desplegamos en el explorador de soluciones y abrimos la característica que se ha desplegado tal y como se ve en la imagen.

Una vez abierta la característica cambiaremos el ámbito de la misma al tipo Site.

Ahora ya podremos implementar la solución, para ello, podemos pulsar en el menú generar de la barra de herramientas superior  y una vez desplegado el menú en implementar y la solución se generará. Tras esto si accedemos a SPD 2010 podremos encontrar la acción que acabamos de crear y utilizarla como parte de cualquier flujo de trabajo que desarrollemos dentro del sitio para el cual lo hayamos creado. En la siguiente imagen se puede demostrar el resultado del trabajo que hemos realizado en la entrada actual.

Y con esto terminamos este post-tutorial en el que he intentado enseñar parte de lo que he aprendido en estos días trabajando con Sharepoint, en los próximos días publicaré nuevas entradas en las que enseñaré otros aspectos relacionados con el filtrado de listas en C# y otros aspectos como el acceso a usuarios de un sitio, etc.

Ha sido mi primer post, espero que os sirva de ayuda, y así comenzar a cumplir en parte con mi objetivo que no es otro que aportar mi granito de arena a la comunidad de desarrolladores.

INFORMACIÓN COMPLEMENTARIA (Enlaces de interés)

Un saludo. Hasta la próxima

EDITADO: He corregido el código porque había una parte que no estaba muy correcta y era la forma de volver a poner la propiedad AllowUnsafeUpdates a False. Al estar dentro de un Try{}Catch{} y hacer el cambio de la propiedad dentro del try, había la posibilidad de que si hubiese una excepción no se pudiera cambiar el valor de la propiedad y devolverlo a False. Eso se puede resolver usando un bloque finally y modificando la propiedad en ese bloque, con lo que nos aseguramos que en caso de que haya una excepción, se vuelve a colocar esa propiedad en su valor correspondiente.

Anuncios