7.06.2010

Exponiendo un Workflow como un Servicio – WF + WCF

En aspectos relacionados con SOA – Arquitectura orientada a servicios – hay dos componentes en lo que concierne al desarrollo en .NET que están muy relacionados: WCF – Windows Comunication Foundation – y WF – Workflow Foundation. La razón es que normalmente los servicios en SOA son utilizados para exponer lógica de negocios; es decir, yo expongo funcionalidad de mi negocio a través de servicios en WCF, y en algunos casos – o muchos – expongo procesos de negocios a travpes de estos servicios. Estos servicios están desarrollados en WCF y los procesos de negocios implementados utilizando WF. Esto alineado con el hecho que normalmente en los ESB se exponen orquestaciones a través de servicios, hace que las únicas dos actividades nuevas en el Framework 3.5 tengan mucho sentido – SendActivity y ReceiveActivity. En este post vamos a explicar como exponer un workflow hecho en WF, a través de un servicio en WCF.

El primer paso es definir que vamos a modelar en el workflow. En este caso y por brevedad vamos a hacer un workflow muy simple que recibe el id de un usuario y me devuelve todas las aprobaciones que tiene pendientes por hacer.

El primer paso es crear un proyecto del tipo Sequential Workflow Service Library tal y como se ve en la siguiente figura.

image

Esta plantilla de proyecto, genera un contrato para el servicio y además genera un workflow que implementa el contrato, acompañando estos dos elementos, se agrega el app.config para exponer el servicio y sus endpoints.

image

image

Como mencionamos antes, el proyecto genera un contrato de forma automática, el cual es implementado por el workflow del proyecto.  Como se puede ver en la figura anterior, el contrato simplemente tiene un método llamado GetData, el cual vamos a renombrar a ObtenerAprobacionesPendientes, el cual recibe de parámetro un entero que va a representar el id del usuario, y devuelve una lista de strings – podría ser de objetos – en los cuales se indica que falta de aprobar. Al mismo tiempo, el proyecto genera un archivo workflow1.cs, el cual contiene la implementación del contrato, este workflow tiene una actividad de recibo con el método de la interface Workflow1 implementada

image

Para hacer el cambio del nombre de la operación del contrato, voy a utilizar refactoring, y en mi caso voy a utilizar R# – www.jetbrains.com – la cual es una herramienta que tiene muchas posibilidades extra de refactoring respecto a las utilidades estándar de VS – además de un gran número de funcionalidad que aumenta la productividad del desarrollador de gran forma [100% recomendada]. Al seleccionar el metodo y con botón derecho darle “refactor” aparece la siguiente pantalla:

image

Esta pantalla me solicita el nuevo nombre que le voy a poner al método. Seguidamente me indica los cambios contextuales – además de tipificados – en donde se va a realizar el cambio.

image

Como podemos ver en la figura anterior, el nombre del método debe de cambiarse en la asignación en la propiedad tpedooperationinfo1.name. Como podemos ver en la siguiente figura del designer.cs del workflow, la propiedad ServiceOperationInfo del receiveActivity1 es la que configura como se ejecuta el servicio. En esta propiedad se establece el contrato a utilizarse y el método que se va a implementar en esta actividad.

image

Una vez hecho el refactor de método, el workflow lucirá de esta forma en modo gráfico:

image

Seguidamente cambiamos el tipo de retorno del contrato de la siguiente forma:

image

Igualmente tenemos que actualizar la propiedad ServiceOperationInfo para refrescar el tipo de retorno. Para hacer esto, vamos a la propiedad en el receiveActivity y le damos click en la elipsis para llevar a cabo esta configuración.

image

La pantalla para refrescar los parámetros es la siguiente

image

Una vez cargada esta pantalla, podemos ver los tipos de retorno e ingreso refrescados correctamente y de manera automática.  Seguidamente vamos a declarar la variable que va a retornar todas las aprobaciones pendientes ( esta vez en una lista de strings ) y vamos a crear una propiedad para exponerla. Esta declaración se ve en la siguiente figura

image

Luego agregamos un codeActivity y lo configuramos de la siguiente manera.

image

El siguiente paso es en el método retornarAprobaciones del codeActivity AprobacionesRestantes ingresamos el código para obtener las aprobaciones faltantes – en este caso vamos a llenar la lista de manera manual con el fin de no alargar innecesariamente el post, pero la situación normal es ir a traer estos datos ya sea a través de conexiones a una base de datos o vía servicios. El código de este método sería el siguiente:

private void retornarAprobaciones(object sender, EventArgs e)
{
AprobacionesPendientes.Add("Vacaciones Luis");
AprobacionesPendientes.Add("Adelantos de Salario Julio");
AprobacionesPendientes.Add("Compras Suministros");
AprobacionesPendientes.Add("Pagos varios");
}


Seguidamente configuramos el receiveActivity para que retorne la lista ya creada. Para esto, seleccionamos la propiedad return value del receiveActivity y seleccionamos la propiedad AprobacionesPendientes como binding para el retorno.



image



Para probar el servicio, le damos F5 al visual studio para que el servicio WCF se hostee en el WCF Service Host para pruebas que trae Visual Studio. En este paso veremos dos pantallas, la primera es la del host del servicio, y la segunda la que nos permite probar el servicio. Ambas pantallas las podemos ver a continuación.



image



Como podemos ver en la prueba anterior, ya expusimos un workflow como un servicio. El siguiente paso es consumir el servicio desde un cliente.



Creando un Cliente Windows para Consumir el Servicio


El siguiente paso es crear un cliente para poder consumir este servicio, y en este caso vamos a utilizar Visual C# Express 2010. Primero creamos una aplicación del tipo WPF : File –> New Project –> WPF Application. En este caso le vamos a poner ClienteWFAsAService. Seguidamente procedemos a agregar una referencia al servicio para poder consumirlo. La dirección del servicio es la estipulada en el app.config del servicio creado, sin embargo, si le damos botón derecho sobre el servicio en el WCF Service Host nos sale la opción de “copy address metadata”, con la cual podemos copiar la dirección para agregar dicha referencia.







image





Seguidamente le damos botón derecho al proyecto WPF y seleccionamos add service reference, luego copiamos la dirección ( ctrl  V) del servicio obtenida a traves del WCF Service Host. El siguiente paso es seleccionar el botón de Go para obtener la especificación del servicio, y renombrar la referencia como SRAprobaciones para accederla desde el código. La pantalla en este paso debe lucir de la siguiente manera:



image



Ahora vamos a agregar un ListBoxpara exponer el resultado de la invocación al servicio.



image





Por último, en el evento load de la pantalla principal, vamos a agregar la invocación al servicio, y el resultado de la misma se la vamos a ligar al LsitBox tal y como se muestra el siguiente código:



private void Window_Loaded(object sender, RoutedEventArgs e)
{
SRAprobaciones.Workflow1Client cliente = new SRAprobaciones.Workflow1Client();
List<string> lstResultado = cliente.ObtenerAprobacionesPendientes(1).ToList<string>();
listBox1.ItemsSource = lstResultado;
}


El resultado de la ejecución de el código anterior es:



image 





Technorati Tags: ,,,

2 comentarios:

RauMarz dijo...

Mil Gracias Diego, este post me ayudo demasiado a entender tanto Web Services como WorkFlows y la integracion de estos 2 conceptos, muy bien explicado !!
Keep on that way :)

Luis D. Rojas dijo...

Gracias RauMarz por tus comentarios y por tomarte el tiempo para leer el blog.