Introducción
Como continuación a los anteriores artículos de Introducción a los Workflows Secuenciales con Tareas y Formularios en Visual Studio 2010 para SharePoint 2010 y Cómo crear un Workflow con Tareas en Visual Studio 2010, en esta ocasión vamos a realizar un ejercicio práctico de programación de un Workflow Secuencial con formularios, en particular utilizando formularios html de Asociación (Association Form) e Iniciación (Initiation Form) utilizando Visual Studio 2010. Recordemos brevemente para qué sirven estos dos tipos de formularios.
- Formularios de asociación (Workflow Association Form). Se muestran en el momento en que se asocia el Workflow al Site o Lista correspondiente. Permiten, por ejemplo, que un adminitrador pueda parametrizar el Workflow (ej: establecer un límite para la Aprobación automática, en un Workflow de Aprobación de gastos) en el momento de su asociación.
- Formularios de iniciación (Workflow Initiation Form). Se muestran al iniciar la ejecución de un Workflow, lo cual resulta útil en Workflows de Sitio y en Workflows de Lista que no se inician automáticamente, permitiendo que un usuario pueda configurar parámetros del Workflow incluso para sobrescribir los parámetros especificados por el administrador.
La creación de un Workflow con formularios html de Asociación y/o Iniciación es francamente sencilla. Los principales detalles que deberemos tener en cuenta para tal menester son:
- Se pueden agregar directamente desde Visual Studio 2010 y están totalmente integrados en Visual Studio. No es necesario modificar manualmente el fichero Elements.xml del Workflow para indicar la URL de los formularios (atributos AssociationURL e InstantiationURL), ya que Visual Studio lo realizará de manera automática por nosotros.
- Los formularios html incluidos por Visual Studio 2010 incluyen algo de código fuente, como los botones de Associate Workflow y Cancel en el caso de formularios de Asociación, y los botones Start Workflow y Cancel en el caso de los formularios de Iniciación. Del mismo modo incluye el código fuente mínimo necesario en el Code Behind.
- Los formularios html de Asociación incluyen un método GetAssociationData que devuelve un valor String, y que se utiliza para devolver la información deseada desde el formulario al Workflow. Del mismo modo, si durante la iniciación del formulario se desea inicializar sus campos con algún valor en particular, es posible utilizar el método PopulateFormFields.
- Los formularios html de Iniciación incluyen un método GetInitiationData que devuelve un valor String, y que se utiliza para devolver la información deseada desde el formulario al Workflow. Del mismo modo, si durante la iniciación del formulario se desea inicializar sus campos con algún valor en particular, es posible utilizar el evento Page_Load.
- Desde el evento Page_Load de un formulario html de Inicialización podemos acceder a la información introducida en el formulario html de Asociación, tal y como veremos más adelante en este mismo artículo.
- Dentro del Workflow podemos acceder en cualquier momento al información devuelta por los formularios html de Asociación e Iniciación utilizando las propiedades AssociationData e InitiationData del objeto workflowProperties (es decir, workflowProperties.AssociationData y workflowProperties.InitiationData) ambas de tipo String.
Además, los formularios html funcionan en cualquier versión de SharePoint 2010, no sólo en SharePoint Server 2010, sino también en SharePoint Foundation 2010 (la edición gratuita, continuación de WSS3), una ventaja muy interesante en comparación con los formularios desarrollados con InfoPath. Por desgracia, no está disponible la vista Diseño de los formularios html, por lo que deberemos desarrollar escribiendo directamente código HTML y el Code Behind.
Dicho todo esto, vamos a empezar con nuestro ejercicio práctico.
Crear un Workflow con formularios html de Asociación e Iniciación
Abriremos Visual Studio 2010 y crearemos un proyecto de tipo Sequential Workflow para SharePoint 2010.
En el Wizard para la creación del Proyecto en Visual Studio 2010, seleccionaremos la opción Deploy as a farm solution, asignaremos el nombre que deseemos para el Workflow, seleccionaremos el tipo List Workflow, y NO asociaremos el Workflow con ninguna lista.
Una vez creado nuestro Proyecto de Visual Studio 2010 (que contendrá un Workflow vacío) vamos a crear un formulario html de Asociación, para lo cual deberemos hacer click con el botón derecho sobre el nodo Workflow1 en el Solution Explorer, para seguidamente, seleccionar la opción New Item del menú Add.
En la ventana Add New Item, seleccionaremos la opción Workflow Association Form, y especificaremos el nombre deseado para dicho formulario html. Click Add para continuar.
Si nos fijamos en el fichero Elements.xml del Workflow, podremos observar que se ha añadido el atributo AssociationUrl al tag Workflow, conforme al formulario html que acabamos de añadir.
A continuación deberemos editar la Página html que acabamos de crear, para escribir el código HTML deseado dentro del contenedor PlaceHolderMain, tal y como se muestra en la siguiente pantalla capturada.
Ahora mostraremos el código fuente de la Página html que acabamos de crear, es decir, el código Behind. En nuestro caso, nos limitaremos a codificar el método GetAssociationData, para que devuelva la información que deseamos desde el formulario html al Workflow (ojo, que sólo es un String).
Ahora vamos a crear nuestro formulario html de Iniciación, para lo cual, igual que hicimos antes, deberemos hacer click con el botón derecho sobre el nodo Workflow1 en el Solution Explorer, para seguidamente, seleccionar la opción New Item del menú Add.
En la ventana Add New Item, seleccionaremos la opción Workflow Initiation Form, y especificaremos el nombre deseado para dicho formulario html. Click Add para continuar.
Si nos fijamos de nuevo en el fichero Elements.xml del Workflow, podremos observar que se ha añadido el atributo InstantiationUrl al tag Workflow, conforme al formulario html que acabamos de añadir.
A continuación deberemos editar la Página html que acabamos de crear, para escribir el código HTML deseado dentro del contenedor PlaceHolderMain, tal y como se muestra en la siguiente pantalla capturada.
Ahora mostraremos el código fuente de la Página html que acabamos de crear, es decir, el código Behind. En nuestro caso, nos limitaremos a codificar el método GetInitiationData y el evento PageLoad, para que se devuelva la información que deseamos del formulario html al Workflow (ojo, que sólo es un String) y para inicializar los Controles de nuestro formulario html. Téngase en cuenta, que en nuestro ejemplo vamos inicializar un campo del formulario de Inicialización en función de los datos introducidos en el formulario de Asociación.
Realizado esto, deberemos editar el Workflow en modo diseño para agregar las siguientes actividades: Una actividad IfElse, con una actividad CreateTask en una rama y una actividad LogToHistoryLog en la otra rama. Suficiente, para el objetivo didáctico del presente artículo. Con esto, el Workflow tendrá un aspecto similar al siguiente.
En las Propiedades de la actividad createTask1, especificaremos el valor de la propiedad CorrelationToken como taskToken, y seguidamente especificaremos el valor de la propiedad OwnerActivityName como Workflow1. Seguidamente, para la propiedad TaskId crearemos una nueva variable (Create Field) que llamaremos taskId, y para la propiedad TaskProperties crearemos una nueva variable (Create Field) que llamaremos taskProperties. En la siguiente pantalla capturada se muestra como quedan configuradas las Propiedades de la actividad createTask1. Para más información, es conveniente consultar el artículo Cómo crear un Workflow con Tareas en Visual Studio 2010.

Para continuar, seleccionaremos la opción Generate Handlers del menú contextual de la actividad createTask1. Escribiremos el código fuente del evento MethodInvoking y también escribiremos el método checkApprovalNeeded. Fíjese que el método checkApprovalNeeded accede a los valores introducidos en ambos formularios (Iniciación y Asociación) a través del objeto workflowProperties.
En las Propiedades de la actividad IfElseBranchActivity, deberemos configurar la propiedad Condition con el valor Code Condition y especificar como condición el método checkApprovalNeeded, tal y como se muestra en la siguiente pantalla capturada.
Ahora seleccionaremos la opción Generate Handlers del menú contextual de la actividad LogToHistoryListActivity1 y escribiremos el código fuente del evento MethodInvoking.
Realizado esto, ya habremos finalizado el desarrollo de nuestro Workflow Secuencial con formularios html de Asociación e Iniciación. Tan sólo queda probarlo.
Probando los formularios html de nuestro Workflow
No nos complicaremos mucho, pero al menos que podamos ver cómo quedan los formularios que acabamos de desarrollar. Pulsaremos F5 en Visual Studio para compilar, desplegar y ejecutar nuestro pequeño desarrollo. Una vez arrancado Internet Explorer, navegaremos hasta la librería Shared Documents y la asociaremos el Workflow que acabamos de crear, lo cual, nos mostrará nuestro formulario de asociación.
Realizado esto, seleccionaremos un documento de la Librería (Item), y click en el botón Workflows de la botonera (Ribbon).
Click sobre el Workflow que queremos asociar con el documento seleccionado, es decir, el Workflow Secuencial que acabamos de desarrollar.
Con esto, se mostrará el formulario html de Iniciación, tal y como se muestra en la siguiente pantalla capturada.
Conclusiones y Despedida
Como se ha podido ver a lo largo del presente artículo, el desarrollo de formularios html de Asociación y de Iniciación en Workflows, es una tarea bastante sencilla, que en función de nuestras habilidades de programación en ASP.NET, nos puede permitir desarrollar formularios muy potentes capaces de ejecutarse tanto en SharePoint Server con en SharePoint Foundation, siendo esta quizás la principal ventaja frente al desarrollo de formularios con InfoPath.
Antes de acabar, aprovecho para incluir un par de enlaces de interés, que han sido la principal fuente de este artículo:
Y por supuesto, como era de esperar, también quería incluir el código fuente de ejemplo.
Poco más por hoy. Como siempre, confío que la lectura resulte de interés.