Mohammed Atef’s Technical blog

Workflow Foundation 4.0 Web Service

Introduction

The new Workflow has introduced new project type called WCF Workflow Service Application that can be hosted in a web service, which provides an ideal way to expose workflow solutions to non-workflow clients such as web applications. A web service receives a request, performs some appropriate processing, and returns a response.

Sample senario

The new project we will create is a BookInventory module used for looks up the specified book and returns the status of each copy that the library owns.

Implementation

To start using the new WCF Workflow service open Visual Studio 2010 and select files ->New project and select WCF Workflow service Application from list of project templates available for Workflow as shown in the below picture

clip_image002

You could name enter project name “WCFSampleWF”, once we have created the new project you will find new file added to your project called BookInventory.xamlx this file will contains the following (Sequence, Receive and Send) activities as shown in the below picture

clip_image002[16]

Now we are going to build the service contract Interface and it’s implementation class also we are going to build class that will hold the Book Info, to do that we are going to add new *.cs file named “BookInfo” that will contain the following implementation list of codes.

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Runtime.Serialization;
 4: using System.ServiceModel;
 5:
 6: namespace BookInventory
 7: {
 8:     /*****************************************************/
 9:     // Define the service contract, IBookInventory
 10:     // which consists of a single method, LookupBook() 
 11:     /*****************************************************/
 12:     [ServiceContract]
 13:     public interface IBookInventory
 14:     {
 15:         [OperationContract]
 16:         BookInfoList LookupBook(BookSearch request);
 17:     }
 18:     /*****************************************************/
 19:     // Define the request message, BookSearch
 20:     /*****************************************************/
 21:     [MessageContract(IsWrapped = false)]
 22:     public class BookSearch
 23:     {
 24:         private String _ISBN;
 25:         private String _Title;
 26:         private String _Author;
 27:
 28:         public BookSearch()
 29:         {
 30:         }
 31:         public BookSearch(String title, String author, String isbn)
 32:         {
 33:             _Title = title;
 34:             _Author = author;
 35:             _ISBN = isbn;
 36:         }
 37:         #region Public Properties
 38:         [MessageBodyMember]
 39:         public String Title
 40:         {
 41:             get { return _Title; }
 42:             set { _Title = value; }
 43:         }
 44:         [MessageBodyMember]
 45:         public String Author
 46:         {
 47:             get { return _Author; }
 48:             set { _Author = value; }
 49:         }
 50:         [MessageBodyMember]
 51:         public String ISBN
 52:         {
 53:             get { return _ISBN; }
 54:             set { _ISBN = value; }
 55:         }
 56:         #endregion Public Properties
 57:     }
 58:     /*****************************************************/
 59:     // Define the BookInfo class
 60:     /*****************************************************/
 61:     [MessageContract(IsWrapped = false)]
 62:     public class BookInfo
 63:     {
 64:         private Guid _InventoryID;
 65:         private String _ISBN;
 66:         private String _Title;
 67:         private String _Author;
 68:         private String _Status;
 69:
 70:         public BookInfo()
 71:         {
 72:         }
 73:
 74:         public BookInfo(String title, String author, String isbn,
 75:             String status)
 76:         {
 77:             _Title = title;
 78:             _Author = author;
 79:             _ISBN = isbn;
 80:             _Status = status;
 81:             _InventoryID = Guid.NewGuid();
 82:         }
 83:         #region Public Properties
 84:         [MessageBodyMember]
 85:         public Guid InventoryID
 86:         {
 87:             get { return _InventoryID; }
 88:             set { _InventoryID = value; }
 89:         }
 90:
 91:         [MessageBodyMember]
 92:         public String Title
 93:         {
 94:             get { return _Title; }
 95:             set { _Title = value; }
 96:         }
 97:         [MessageBodyMember]
 98:         public String Author
 99:         {
 100:             get { return _Author; }
 101:             set { _Author = value; }
 102:         }
 103:         [MessageBodyMember]
 104:         public String ISBN
 105:         {
 106:             get { return _ISBN; }
 107:             set { _ISBN = value; }
 108:         }
 109:         [MessageBodyMember]
 110:         public String status
 111:         {
 112:             get { return _Status; }
 113:             set { _Status = value; }
 114:         }
 115:         #endregion Public Properties
 116:     }
 117:     /*****************************************************/
 118:     // Define the response message, BookInfoList, which
 119:     // is a list of BookInfo classes
 120:     /*****************************************************/
 121:     [MessageContract(IsWrapped = false)]
 122:     public class BookInfoList
 123:     {
 124:         private List<BookInfo> _BookList;
 125:
 126:         public BookInfoList()
 127:         {
 128:             _BookList = new List<BookInfo>();
 129:         }
 130:         [MessageBodyMember]
 131:         public List<BookInfo> BookList
 132:         {
 133:             get { return _BookList; }
 134:         }
 135:     }
 136: }

The above code has the following classes and interface

1- IBookInventory is The service contract Interface that contains a single method called LookupBook(). It is has one paramter BookSearch class that has various properties that can be used to find the desired book, such as Author and Title. It returns a BookInfoList class, which contains a collection of BookInfo classes.

2- BookSearch is a class used for building the request that hold the Book Search criteria If you do not have experince about WCF service you should know that The MessageContract attribute is used on a class that defines the data types or contracts that will be added to a message header or body of your WCF service, and the class contains this attribute should have another attribute called MessageBodyMember for properties that will be used in the WCF request or response.

3- BookInfo is a class that hold book info and you can notice that it has MessageContract and MessageBodyMember attributes which means it will be used be service request or response

4- BookInfoList is a class Define the response message, BookInfoList, which is a list of BookInfo classes.

Now we are going to Configure the Send and receive activities, so please follow these steps

a- select the “ReceiveRequest” activity. In the Properties window, Enter the OperationName as LookupBook

b- From the workflow designer, click the Variables control at the bottom left. You’ll notice that the template created a couple of variables for you. The handle variable is used to correlate the response with the same instance that sent the request. The data variable was set up as the data being passed in.

Select the data variable and press the Delete key to remove it, Create two new variables.

For the first one, enter the Name as search; for the Variable type, select Browse for Types, In the dialog that appears, expand the WFFAndWCF->BookInventory assembly and choose the BookSearch class.

For the second variable, enter the Name as result. For the Variable type property, choose Browse for Types and then select the BookInfoList class

c- On the workflow designer, the “ReceiveRequest” activity has a View message link for the Content property. Click it to display the dialog that is used to define the incoming message. The input can be defined in two ways: a message or a collection of parameters. For now, make sure that the Message radio button is selected.For the Message data property, enter search. It specifies that the incoming message should be stored in the search variable. For the Message type, select BookInventory.BookSearch.

d- Select the “SendResponse” activity and click its View message link. Again, make sure that the Message radio button is selected. For the Message data property, enter result; for the Message type property, select the BookInfoList class.

For the Message data property, enter search.

Creating Custom activity for Looks up Book Status

We will create a custom activity to perform the “lookup.” Actually, it will simply return

some hard-coded data and to do that please follow these few steps

a- From the Solution Explorer, right-click the WCFSampleWF project and choose Add -> New Item. In the Add New Item dialog, select the Code Activity template from the Workflow category. Enter the Name as “PerformLookup.cs”

b- Enter the implementation of the PerformLookup activity, as shown in Listing below

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.Activities;
 6: namespace BookInventory
 7: {
 8:
 9:     public sealed class PerformLookup : CodeActivity
 10:     {
 11:         public InArgument<BookSearch> Search { get; set; }
 12:         public OutArgument<BookInfoList> BookList { get; set; }
 13:         protected override void Execute(CodeActivityContext context)
 14:         {
 15:             string author = Search.Get(context).Author;
 16:             string title = Search.Get(context).Title;
 17:             string isbn = Search.Get(context).ISBN;
 18:             BookInfoList l = new BookInfoList();
 19:             l.BookList.Add(new BookInfo(title, author, isbn, "Available"));
 20:             l.BookList.Add(new BookInfo(title, author, isbn, "CheckedOut"));
 21:             l.BookList.Add(new BookInfo(title, author, isbn, "Missing"));
 22:             l.BookList.Add(new BookInfo(title, author, isbn, "Available"));
 23:             BookList.Set(context, l);
 24:         }
 25:     }
 26: }

The above list is very clear it is creating two input/ouput arguments called search and booklist for using in send request and receive response from in the Workflow activities, then in the execute it is retrieving search criteria from the search argument and build collection of bookinfo and set booklist argument with the generated list of bookinfo if you did not understand how two build Custom Code activity please visit the following link WFF custom code activity.

c- build the project and opened BookInventory.xamlx file you will notice that the custom PerformLookup activity is added in your Toolbox

d- Drag a PerformLookup activity between the “Receive Request” and “Send Response” activities.

e- Select the PerformLookup activity. In the Properties window, for the BookList property enter result;for the Search property, enter search.

Testing the Service the new Visual Studio automatically starts the WCF Test Client. This is a very handy utility. It loads the web service and discovers the methods that are provided.all you need to press f5 and you find the below figure that shown the test client utility:

clip_image002[18]

As shown in the above figure the left pane contains the methods that are provided by the WCF service once you Double-click the LookupBook() method, the upper portion of the right pane will provide a place for you to enter the contents of the incoming message. Enter an author, ISBN number, and title; then click the Invoke button. You should see results similar to the ones shown bottom grid found in the same figure.

Creating a Client Workflow

Now we are going to build and client Workflow application that will use the created WCF application we have finished before, simply we can do that in few steps as shown below

a- Right click into WCFSampleWF solution name and choose Add -> New Project. Select the Workflow Console Application template from installed templates related to workflow in the left pane of create new project window and for the project name, enter BookLookup

b-From the Solution Explorer, right-click the BookLookup project and choose Add Service Reference and add the following url into address attribute http://localhost:49570/BookInventory.xamlx

, press GO button and finally enter the name of namespace property as “BookEnventoryWCF”.

c- Once you have built the solution you will find new activity added to your toolbar called LookupBook as shown in the below figure

clip_image002[20]

d- Drag that LookupBook activity to you Workflow

e- create arguments that used by the LookupBook activities as show in the below figure

clip_image002[22]

Note that the BookList argument should be of type “BookLookupClientWF.BookEnventoryWCF.BookInfo[]”

f- Set the LookupBook properties to the with the matches argument names

g- Open the Program.cs file in the BookLookupClientWF project. add The implementation for this file as shown in Listing below

 1: using System;
 2: using System.Linq;
 3: using System.Activities;
 4: using System.Activities.Statements;
 5: using System.Collections.Generic;
 6: using BookLookupClientWF.BookEnventoryWCF;
 7:
 8: namespace BookLookupClientWF
 9: {
 10:
 11:     class Program
 12:     {
 13:         static void Main(string[] args)
 14:         {
 15:             // create dictionary with input arguments for the workflow
 16:             IDictionary<string, object> input = new Dictionary<string, object>
 17:             {
 18:             { "Author" , "Margaret Mitchell" },
 19:             { "Title" , "Gone with the Wind" },
 20:             { "ISBN" , "1234567890123" }
 21:             };
 22:             // execute the workflow
 23:             IDictionary<string, object> output =
 24:             WorkflowInvoker.Invoke(new Workflow1(), input);
 25:             BookInfo[] l = output["BookList"] as BookInfo[];
 26:             if (l != null)
 27:             {
 28:                 foreach (BookInfo i in l)
 29:                 {
 30:                     Console.WriteLine("{0}: {1}, {2}",
 31:                     i.Title, i.status, i.InventoryID);
 32:                 }
 33:             }
 34:             else
 35:                 Console.WriteLine("No items were found");
 36:             Console.WriteLine("Press ENTER to exit");
 37:             Console.ReadLine();
 38:         }
 39:     }
 40: }

i-  run the application you will find the following message printed in the console screen

Gone with the Wind: Available, 58ab51cd-2796-4b32-a7be-21170f1e922b

Gone with the Wind: CheckedOut, 64406a94-a6ef-45a7-8373-066f5f991134

Gone with the Wind: Missing, a37186ec-faa7-4e6b-8226-484f17075998

Gone with the Wind: Available, e34d39e5-aafa-4fd3-8000-664809b7e98d

Press ENTER to exit

You can download the complete source code from here

Back to other Workflow Foundation 4.0  posts

I hope that helped

Advertisements

May 10, 2011 - Posted by | .Net 2010 | , , ,

2 Comments »

  1. […] Workflow Foundation 4.0 Web Service […]

    Pingback by Workflow Foundation 4.0 « Mohammed Atef’s Technical blog | May 10, 2011 | Reply

    • Actually, i do not have that enough experience to answer this question, but i will search for solution to it, and i have approved you comment so anyone else can answer

      Comment by mohammedatef83 | May 18, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: