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

Workflow Foundation 4.0 Collections

Introduction

In this post we will see an important built in activities comes with Workflow foundation 4.0., these built-in activities enable you to manipulate a collection in your workflow. this post guide you to do the most required actions for manipulating collections like add,remove and delete items from collection and sorting, searching and clearing the collection.

We will build a console application that demonstrates these activities using a Book Store application.

Building Book Store application
To build the Book Store application you should follow the below steps

1- Create new console application and add System.Activities reference to the new project

2- Open the program.cs file and add the following list of code for declaring BookStoreListItem this class contains a few public properties that store information about an item to be stored.

   1: public class BookStoreListItem
   2:     {
   3:         public string Description { get; set; }
   4:         public int Quantity { get; set; }
   5:         public decimal UnitPrice { get; set; }
   6:         public string Author { get; set; }
   7:         public string BookName { get; set; }
   8:         public BookStoreListItem(string description, int quantity, decimal unitPrice,string author, string bookName)
   9:         {
  10:             Description = description;
  11:             Quantity = quantity;
  12:             UnitPrice = unitPrice;
  13:             BookName = bookName;
  14:             Author = author;
  15:         }
  16:         public BookStoreListItem(string bookName)
  17:         {
  18:             BookName= bookName;
  19:         }
  20:     }

3- Initiate the Workflow by adding the following namespace to the top of program.cs class

using System.Activities.Expressions; now add the following list of code after the closed practices for the main method in the program.cs class

   1: private static Activity CollectionWF()
   2:         {
   3:             // myList is a collection of ListItem objects
   4:             Variable<ICollection<BookStoreListItem>> myList = new Variable<ICollection<BookStoreListItem>>()
   5:             {
   6:                 Name = "MyList",
   7:                 Default = new LambdaValue<ICollection<BookStoreListItem>>
   8:                     (env => new List<BookStoreListItem>())
   9:             };
  10:             return new Sequence
  11:             {
  12:                 Variables = { myList },
  13:                 Activities =
  14:                 {
  15:                     new WriteLine
  16:                     {
  17:                         Text = "Workflow starting..."
  18:                     },
  19:                     new AddToCollection<BookStoreListItem>
  20:                     {
  21:                         Collection = myList,
  22:                         Item = new LambdaValue<BookStoreListItem>
  23:                         (env => new BookStoreListItem("New WorkFlow 4.0 book", 5, 50,"Mohammed", "WorkFlow 4.0"))
  24:                     },
  25:                     new AddToCollection<BookStoreListItem>
  26:                     {
  27:                         Collection = myList,
  28:                         Item = new LambdaValue<BookStoreListItem>
  29:                         (env => new BookStoreListItem("New Linq 4.0 book", 3, 30,"Sherif", "LINQ 4.0"))
  30:                     },
  31:                     new AddToCollection<BookStoreListItem>
  32:                     {
  33:                         Collection = myList,
  34:                         Item = new LambdaValue<BookStoreListItem>
  35:                         (env => new BookStoreListItem("New Windows Communication Foundation 4.0 book", 8, 80,"Atef", "WCF 4.0"))
  36:                     },
  37:                     new AddToCollection<BookStoreListItem>
  38:                     {
  39:                         Collection = myList,
  40:                         Item = new LambdaValue<BookStoreListItem>
  41:                         (env => new BookStoreListItem("Visual studio 2010 book", 15, 40,"Khalid", "VS 2010"))
  42:                     },
  43:                     new WriteLine
  44:                     {
  45:                         Text = "Workflow ended"
  46:                     }
  47:                 }
  48:             };
  49:         }

This workflow defines a variable that is a collection of BookStoreListItem classes named myList. The variable can be any typeof collection that supports the ICollection interface.the LambdaValue Represents a lambda expression used as an r-value, which supports binding of In arguments so it is bind the default value of myList with the returned new instance of BookStoreListItem class .

After that we are going to build the sequence activity for our workflow and the sequence activity will have the following activities

a- writeline activity that printing “Workflow starting…”

b- four AddToCollection activity that used for adding new item of BookStoreListItem to myList

c- another writeline activity to print “Workflow ended…”

4- Now we need to invoke the workflow, so please add the following lines of code in the main method at program.cs class

   1: WorkflowInvoker.Invoke(CollectionWF());
   2: Console.WriteLine("Press ENTER to exit");
   3: Console.ReadLine();

These few line of code used to invoke the workflow by calling collectionWF into the Invoke method.

If you have run the application now you will find the following lines printed

Workflow starting…

Workflow ended…

Press ENTER to exit

5- Printing Collection , we will provide a way to display the contents of the books list, to do that right-click the project and choose Add new Item and select Class, For the class name, enter PrintBooksList.cs. The implementation of this class is shown in Listing below

   1: using System;
   2: using System.Activities;
   3: using System.Collections.Generic;
   4: namespace WFFBookStoreApp
   5: {
   6:     public sealed class PrintBooksList: CodeActivity
   7:     {
   8:         public InArgument<ICollection<BookStoreListItem>> Collection { get; set; }
   9:
  10:         protected override void Execute(CodeActivityContext context)
  11:         {
  12:             ICollection<BookStoreListItem> list =
  13:             this.Collection.Get<ICollection<BookStoreListItem>>(context);
  14:             if (list.Count == 0)
  15:             {
  16:                 Console.WriteLine("The Book list is empty");
  17:             }
  18:             else
  19:             {
  20:                 foreach (BookStoreListItem l in list)
  21:                 {
  22:                     Console.WriteLine("Book Named {0} has the following information :", l.BookName);
  23:                     Console.WriteLine("(Description:{0} ,Quantity: {1},Price: {2} ,Author {3})",
  24:                     l.Description,l.Quantity.ToString(), l.UnitPrice, l.Author);
  25:                 }
  26:                 Console.WriteLine();
  27:             }
  28:         }
  29:     }
  30: }

This custom activity receives the collection as an input argument. It expects a collection of BookStoreListItem classes. the overridden execute method first check if the list empty or not, if yes it is printing the book list is empty message, else it is loop throw the list and print each book item information, this code is very simple you can understand but if you do not know how to create custom activity please visit the following link WFF 4.0 custom activity.

6- To use this custom activity, Open the program.cs file and add the following activity definition to the collectionWF () method before the final writeline activity

   1: new PrintBooksList
   2:                     {
   3:                         Collection=myList
   4:                     },

If you run the application now you will find the following message printed

clip_image002

7- Sorting the collection, we will provide a way to sort the books list by book price, to do that right-click the project and choose Add new Item and select Class, For the class name, enter SortBooksList.cs. The implementation of this class is shown in Listing below

   1: using System;
   2: using System.Activities;
   3: using System.Collections.Generic;
   4: namespace WFFBookStoreApp
   5: {
   6:     public sealed class SortBooksList : CodeActivity
   7:     {
   8:         public InOutArgument<ICollection<BookStoreListItem>> Collection { get; set; }
   9:         protected override void Execute(CodeActivityContext context)
  10:         {
  11:             ICollection<BookStoreListItem> tempList = this.Collection.Get<ICollection<BookStoreListItem>>(context);
  12:             if (tempList.Count > 0)
  13:             {
  14:                 List<BookStoreListItem> sortedList = new List<BookStoreListItem>(tempList);
  15:                 ItemComparer c = new ItemComparer();
  16:                 sortedList.Sort(c as IComparer<BookStoreListItem>);
  17:                 Collection.Set(context, sortedList as ICollection<BookStoreListItem>);
  18:             }
  19:         }
  20:     }
  21:     public class ItemComparer : IComparer<BookStoreListItem>
  22:     {
  23:         public int Compare(BookStoreListItem x, BookStoreListItem y)
  24:         {
  25:             // Handle null arguments
  26:             if (x == null && y == null)
  27:                 return 0;
  28:             if (x == null)
  29:                 return -1;
  30:             if (y == null)
  31:                 return 1;
  32:             // Perform comparison based on the priority
  33:             if (x.UnitPrice == y.UnitPrice)
  34:                 return 0;
  35:             if (x.UnitPrice > y.UnitPrice)
  36:                 return 1;
  37:             else
  38:                 return -1;
  39:         }
  40:     }
  41: }

This custom activity receives the collection as an input argument and return the same argument after sorting it. It expects a collection of BookStoreListItem classes .the overridden Execute() method of this activity takes a collection as both an input and output argument.The Sort() method of the List class is used to perform the sort, but you must supply a class that implements the IComparer interface because the standard implementation will not know how to sort BookStoreListItem objects. The IComparer interface provides a single method called Comparer (), which receives two objects (x and y) as input parameters. It returns 0 if the two objects are equal, 1 if x is greater than y, and -1 if x is less than y.

8- To use this custom activity, Open the Program.cs file and add the following activity definition to the collectionWF () method before the final writeline activity

   1: new SortBooksList
   2: {
   3:     Collection=myList
   4: },
   5: new WriteLine
   6: {
   7:     Text = "Books List sorted by Price"
   8: },
   9: new PrintBooksList
  10: {
  11:     Collection=myList
  12: },

If you run the application now you will find the following message printed

clip_image002[7]

if you have reviewed the printed lines in console, you will find the new books listed after line “books list sorted by price are order desc by price.

9- Searching in the collection, now we are going to use built in activity in Workflow Foundation 4.0 like ExistsInCollection, so we will check if the item found in the book list or not.

As the ExistsInCollection should iterate between books list items so it is require to use Equals() methods which mean we need to implement this method to our BookStoreListItem class, For our purposes, you should consider two items equal if they have the same name,To do that add the following list of code to BookStoreListItem class in program.cs file

   1: public override bool Equals(object obj)
   2: {
   3:     BookStoreListItem i = obj as BookStoreListItem;
   4:     if (i == null)
   5:         return false;
   6:     else
   7:     {
   8:         if (i.BookName == this.BookName)
   9:             return true;
  10:         else
  11:             return false;
  12:     }
  13: }
  14: public override int GetHashCode()
  15: {
  16:     return base.GetHashCode();
  17: }

The Equals() method cast the input object to a BookStoreListItem and returns True if the BookName property matches. When overriding the Equals() method, the compiler expects you to also override the GetHashCode() method. This implementation simply calls the base method

10- Now , we can use ExistsInCollection to do that add the following lines of code before the final writeline activity

   1: public override bool Equals(object obj)
   2:        {
   3:            BookStoreListItem i = obj as BookStoreListItem;
   4:            if (i == null)
   5:                return false;
   6:            else
   7:            {
   8:                if (i.BookName == this.BookName)
   9:                    return true;
  10:                else
  11:                    return false;
  12:            }
  13:        }
  14:        public override int GetHashCode()
  15:        {
  16:            return base.GetHashCode();
  17:        }
  18:

If you have run the application now you will see this line printed before workflow ended

“LINQ 4.0 Book has been added before”

11- Remove item from Collection, Workflow Foundation 4.0 has activity named RemoveFromCollection that is responsible for removing item from collection it very easy in implementation, we will use it to remove book named “LINQ 4.0“,to do that add the following line of code before the final writeline activity

   1: new WriteLine
   2: {
   3:     Text = "Removing LINQ 4.0 book from Books Store..."
   4: },
   5: new RemoveFromCollection<BookStoreListItem>()
   6: {
   7:     Collection = myList,
   8:     Item = new LambdaValue<BookStoreListItem>
   9:         (env => new BookStoreListItem("LINQ 4.0"))
  10: },
  11: new PrintBooksList()
  12: {
  13:     Collection = myList
  14: },

if you have run the application now you will see the following lines printed before workflow ended line

clip_image002[9]

12- Clearing the collection, Workflow Foundation 4.0 has built in activity to clear collection named ClearCollection to use this activity add the following lines of code before the final writeline activity

   1: new ClearCollection<BookStoreListItem>()
   2: {
   3:     Collection = myList
   4: },
   5: new PrintBooksList()
   6: {
   7:     Collection = myList
   8: },

If you have run the application now you will find line printed before workflow ended that says

“The book list is Empty”

Conclusion:

I was trying to learn you how WFF 4.0 are manipulation with collection,you can download The complete implementation of that post from here and you can return back to workflow posts list here

Back to other Workflow Foundation 4.0  posts

I Hope that helped

September 26, 2010 Posted by | .Net 2010 | , , , , , , | 1 Comment

Workflow Foundation 4.0 Custom activities

WFF 4.0 helps you to implement you own custom activity. sure creating custom activity is very important part that all Workflow developers are interested in.the new Workflow Foundation 4.0 give you two ways of generating custom activities.
As we need to prove concept only, my custom activity will be simple, just I am going to build custom activity that print the message “Hello FirstName Last Name” this custom activity taking two input parameters First Name and Last Name and return the full message,let’s see how to implement this simple example by Workflow Foundation 4.0.

Using Code Activity template

Code activity template give you advantage to inherit the codeactivity class and build your custom activity from scratch but the new Workflow Foundation helps you to do that in easy way, so to implement the new custom activity follow the following steps

1- Open Visual Studio 2010 and select file->new project->workflow->workflow consol application

2- In the name textbox write CustomactivitySample as the project name

3- After the solution has opened right click in the project name and select add new item that will open the list of items as shown in the below picture

clip_image002

select code activity and enter code activity name such as “HelloMsg
4- By default you with find the below list of code has been generated in your new file that named HelloMsg.cs

   1: public sealed class HelloMsg : CodeActivity
   2:     {
   3:         // Define an activity input argument of type string
   4:         public InArgument<string> Text { get; set; }
   5:         // If your activity returns a value, derive from CodeActivity<TResult>
   6:         // and return the value from the Execute method.
   7:         protected override void Execute(CodeActivityContext context)
   8:         {
   9:             // Obtain the runtime value of the Text input argument
  10:             string text = context.GetValue(this.Text);
  11:         }
  12:     }

5- Now we are going to add our code for printing hello message

– First we will prepare the activity parameters, so replace line no 4 in the above codes list with the following list of codes

   1: public InArgument<string> FirstName { get; set; }
   2: public InArgument<string> LastName { get; set; }
   3: public OutArgument<string> HelloMessgae { get; set; }

As shown in the above codes list we have declared two input parameters first name and last name and one output parameter for returning the complete hello message.

– The last step for implementing this custom activity is to add code for using input parameters and concatenating it to return the complete hello message, so please replace line 10 at the codes list in step 4 with the following list of codes

   1: string fname = context.GetValue(this.FirstName);
   2: string lname = context.GetValue(this.LastName);
   3: string completeMsg = " Hello " + fname +" "+ lname;
   4: context.SetValue(this.HelloMessgae, completeMsg);

6- Build the project to refresh the toolbar, and you will notice new activity hellomsg activity has been added to the toolbar.

7- Open Workflow1.xaml in designer view and drag sequence activity then drag hellomsg and writeline activity by ordered in the new added sequence activity

8- Create variable named fullname and has data type string from the variables window at bottom of the workflow1 designer

9-Open the writeline property windows and set the text property to the new created variable name in the previous step

10- Open the hellomsg property window and set it is properties as follow:

a- FirstName: “Mohammed”

b- Last Name: “Atef”

c- HelloMessage: fullname which added in step no 8

Finally run the application you will see this message in the console window

“Hello Mohammed Atef”

Using Activity

Using the activity you can create your own activity and use it in another work flow as independent activity and you can pass parameters between your activity and the main workflow designer

This kind of activities is very simple as you are using the workflow designer with all toolbar activities available to implement you custom activity.

We are going to do the same business scenario in the previous example but we will add the following message before the hello message “Custom Activity using Designer.” this only to determine the message printed for each custom activity.

Now , to implement the new custom activity follow the following steps

1- Write click into the project name and select add new item then select activity icon from the windows as shown in picture below

clip_image002[4]

name that activity hellomsgActivity.xaml

2- Drag sequence activity to the new created activity named hellomsgActivity.xaml and then drag writeline activity into the sequence activity

3- Add two arguments from arguments window below the designer of that activity named hellomsgActivity.xaml

4- Write the following line into the text property of the writeline activity

“Custom Activity using Designer: Hello Mr. ” + FName + LName

5- Build the application

6- Open the main workflow1.xaml in design mode and drag hellomsgActivity activity from the toolbar

7- Open the hellomsgActivity property window and set it is properties as follows

a- FName:”Mohammed”

b-LName:”Atef”

Now Run the application you will find the following messages are printed

Hello Mohammed Atef”

Custom Activity using Designer: Hello Mr. Mohammed Atef”

Now we have finished this example and the main workflow1.xaml should be like the following picture below

clip_image002[6]

You can also download the complete example by source code from here.
Back to other Workflow Foundation 4.0  posts

I hope that helped.

September 26, 2010 Posted by | .Net 2010 | , , , , , | 3 Comments

Workflow Foundation 4.0 Tracking

Introduction

This post will guide you to use extensions for tracking Workflow events while it is executing the defined activities.This is useful for monitoring a workflow’s execution and for triggering external processing.

Tracking
In WF 4.0, tracking is accomplished through tracking participants, which are extensions that are derived
from the TrackingParticipant abstract class.
First of all to implement tracking extensions you need to inherit TrackingParticipant class and overrides the Track() method, which is where most of the work is done. When a trackable event occurs, the workflow instance will enumerate all the extensions and will call the Track() method in any that are derived from the TrackingParticipant base class.
A TrackingRecord is passed into the Track() method. This is an abstract class; the actual instance passed
in will be one of the following classes, which are derived from the TrackingRecord class:
WorkflowInstanceRecord contains data about the workflow instance.
You can use this class to print the Workflow instance ID and Workflow instance state as shown in the below list of codes:

   1: WorkflowInstanceRecord instance = record as WorkflowInstanceRecord;
   2: if (instance != null)
   3: {
   4: Console.WriteLine(String.Format(" InstanceID: {0} State: {1}",instance.InstanceId, instance.State));
   5: }

BookmarkResumptionRecord contains data about the bookmark being resumed.

You can use this class to print the book mark name as shown in the below list of codes:

   1: BookmarkResumptionRecord bookmark = record as BookmarkResumptionRecord;
   2: if (bookmark != null)
   3: {
   4: Console.WriteLine(String.Format(" Bookmark {0} resumed",bookmark.BookmarkName));
   5: }

ActivityStateRecord contains data about a specific activity.

You can use this class to print information about activities hosted in the Workflow instance as shown in the below list of codes:

   1: ActivityStateRecord activity = record as ActivityStateRecord;
   2: if (activity != null)
   3: {
   4: IDictionary<String, object> variables = activity.Variables;
   5: StringBuilder s = new StringBuilder();
   6: if (variables.Count > 0)
   7: {
   8: s.AppendLine(" Variables:");
   9: foreach (KeyValuePair<string, object> v in variables)
  10: {
  11: s.AppendLine(String.Format(" {0} Value: [{1}]",
  12: v.Key, v.Value));
  13: }
  14: }
  15: Console.WriteLine(String.Format(" Activity: {0} State: {1} {2}",
  16: activity.Activity.Name, activity.State, s.ToString()));
  17: }

CustomTrackingRecord contains user-defined data.

You can use this class to print about user-defined data as shown in the below list of codes

   1: CustomTrackingRecord user = record as CustomTrackingRecord;
   2: if ((user != null) && (user.Data.Count > 0))
   3: {
   4: Console.WriteLine(String.Format(" User Data: {0}", user.Name));
   5: foreach (string data in user.Data.Keys)
   6: {
   7: Console.WriteLine(String.Format(" {0} : {1}", data, user.Data[data]));
   8: }
   9: }

To use the tracking extension you should add the tracking extension to the Workflow instance as shown in the below list of codes

   1: i.Extensions.Add(_tracking);
   2: //where i is an instance of WorkflowApplication  
   3: //and _tracking is an instance of class that inherits TrackingParticipant class

Then you should set up the tracking extensions participants by using TrackingProfile collections, A TrackingProfile defines a collection of queries that specify which events are to be tracked by the associated tracking participant. These queries are used to determine if an event is trackable. The queries are stored in the Queries property, which is a collection of classes derived from the abstract TrackingQuery class. There are four derived classes that correspond to the four types of tracking records:

WorkflowInstanceQuery

A WorkflowInstanceQuery is used to define the workflow instance events that should be tracked. These

are the process states that occur at the instance level such as Started, Completed, Unloaded, and so on, To do that you can write the below list of codes:

   1: TrackingProfile = new TrackingProfile()
   2: {
   3:     Name = "TrackingProfileName",
   4:     Queries =
   5:     {
   6:         // For instance data, only track the started and completed events
   7:         new WorkflowInstanceQuery()
   8:         {
   9:             States = { WorkflowInstanceStates.Started,WorkflowInstanceStates.Completed },
  10:         }
  11: }

BookmarkResumptionQuery

In a BookmarkResumptionQuery, you specify the name of the bookmark that you want to track whenever it is resumed. You can specify only a single bookmark in a query. If you want to track multiple bookmarks,

you should create multiple queries—one for each bookmark, To do that you can write the below list of codes:

   1: TrackingProfile = new TrackingProfile()
   2: {
   3:     Name = "TrackingProfileName",
   4:     Queries =
   5:     {
   6:         new BookmarkResumptionQuery()
   7:                       {
   8:                           Name = "GetAssignment"
   9:                       }
  10: }

ActivityStateQuery

An ActivityStateQuery class specifies both the Name of the activity and the State collection (events) that

should be tracked. You can specify an asterisk (*) for either, which indicates that all activities and/or

states should be tracked, To do that you can write the below list of codes:

   1: TrackingProfile = new TrackingProfile()
   2:                 {
   3:                     Name = "ListBoxTrackingProfile",
   4:                     Queries =
   5:                     {
   6:                         // For activity data, track all states of the InvokeMethod
   7:                        new ActivityStateQuery()
   8:                        {
   9:                            ActivityName = "InvokeMethod",
  10:                            States = { "*" },
  11:                        }
  12:                     }
  13: }

CustomTrackingQuery

The CustomTrackingQuery specifies the ActivityName, which indicates the activity that generated the

CustomTrackingRecord and the Name property, which indicates the name given to the CustomTrackingRecord,You can specify an asterisk for either (or both) as the example, above does. When

both are set to *, it indicates that all user events should be tracked, you can do that by typing the below of codes:

   1: TrackingProfile = new TrackingProfile()
   2:                 {
   3:                     Name = "ListBoxTrackingProfile",
   4:                     Queries =
   5:                     {
   6:                         new CustomTrackingQuery()
   7:                         {
   8:                             Name = "*",
   9:                             ActivityName = "*"
  10:                         }
  11:                     }
  12: }

In this post we have understood the Tracking extension and we have learned how to use it also.now you can visit the orher posts about Workflow Foundation for here

I hope that helped.

September 26, 2010 Posted by | .Net 2010 | , , , , , , | 2 Comments

Workflow Foundation 4.0

The new Workflow foundation comes with .Net Framework 4.0 that supports building and running the next generation of applications and services. The key components of the .NET Framework are the common language runtime (CLR) and the .NET Framework class library, which includes ADO.NET, ASP.NET, Windows Forms, and Windows Presentation Foundation (WPF), by the way all Visual Studio 2010 IDE are build in XAML language that provides a managed execution environment, simplified development and deployment, and integration with a wide variety of programming languages.

In version 4 of the Microsoft® .NET Framework, Windows Workflow Foundation introduces a significant amount of change from the previous versions of the technology that shipped as part of .NET 3.0 and 3.5.

The significant changes made were necessary to provide the best experience for developers adopting WF and to enable WF to continue to be a strong foundational component that you can build on in your applications.

I have wrote this article to give you a start point to understand and study Workflow Foundation 4.0, so I am going to write series of posts about WFF 4.0 as found in the below below List

I hope that helped

September 20, 2010 Posted by | .Net 2010 | , , , , , | 6 Comments

What’s new in Workflow Foundation 4.0

The New Workflow Foundation 4.0 introduces a significant amount of change from the previous versions of the technology that shipped as part of .NET 3.0 and 3.5. so let’s go quickly to see these new features

  • Designers are built in XAML The designer is based on Windows Presentation Foundation (WPF),so it is taking full advantage of the rich user experience one can build with the declarative UI framework.  Activity developers will use XAML to define the way their activities look and interact with users in a visual design environment.  In addition, it enables non-developers to view and interact with your workflows is now much easier as XAML language is written in XML language that give any non-developers ability to read and understand it.

    For example if you have created new project of Console Workflow and dragged a WriteLine activity in the designer and select the code view you will find the following list of XAML codes

       1: <Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication1.Workflow1" sap:VirtualizedContainerService.HintSize="251,240" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
       2: <WriteLine
       3: sad:XamlDebuggerXmlReader.FileName="C:\Temp\DotNet4\WorkflowConsoleApplication1\Workflow1.xaml"
       4: sap:VirtualizedContainerService.HintSize="211,200" />
       5: </Activity>

    I think any non-developer can understand the above list of XAML code

  • Different project templates The new Workflow Foundation 4.0 comes with new project templates as shown in below pictureclip_image002

    The above picture shows only four project templates of Workflow Foundation 4.0 that leads you to simplify project templates for developer. The first project template Activity Designer Library let you create you custom Workflow Foundation Activity with designer, while the second project template leads you to create your custom activity by inheriting the CodeActivity class and the third project template leads you to build new WCF Workflow Service and we are going to explain this project template deeply in another post later finally the last project type help you for creating Console application that contain Workflow Activities.

    If you reviews the below pictures that has list of project template found for Workflow Foundation 3.5 you will understand that new Workflow Foundation 4.0 has summarized and compressed the project templates in better way.

    clip_image002[7]

  • Variable and parameters new windows in the WFF IDE Workflow Foundation 4.0 introduces a helpful window for creating variables and parameters to your Workflow in easy way, the below two pictures show you the new windows generated for defining variables and parameters

    clip_image002[9]

    clip_image002[11]

    First Picture show you how to declare variable to you workflow, as shown there you can define the DataType of you variable, default value and the scope of a variable either the entire workflow or just a specific activity or its children.

    Second picture show you how to define arguments by specifying its name, direction(In,Out,In/Out), argument type and default value.

    If you have used Workflow Foundation 3.5 before you should understand what Workflow Foundation 4.0 has introduced to you for declaring variables and arguments as in WFF 3.5 you should write the following list of codes to define variable

   1: public static DependencyProperty MessageProperty =
   2:     DependencyProperty.Register("Message", typeof(string), typeof(CustomActivity));
   3:
   4:         [DescriptionAttribute("Message")]
   5:         [BrowsableAttribute(true)]
   6:         [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
   7:         public string Message
   8:         {
   9:             get
  10:             {
  11:                 return ((string)(base.GetValue(MessageProperty)));
  12:             }
  13:             set
  14:             {
  15:                 base.SetValue(MessageProperty, value);
  16:             }
  17:         }
  18:

The above bulk of code writes only for defining variable Named message of type string

  • Windows Communication Foundation (WCF) Integration

    Workflow Foundation 4.0 introduce creating services and consuming or coordinating service interactions.  A great deal of effort went into enhancing the integration between WCF and WF.  New messaging activities, message correlation, and improved hosting support, along with fully declarative service definition are the major areas of improvement, We will go deeply throw WCF integration with the new WF in another post later.

  • New built in Activity The new Workflow Foundation 4.0 has a lot of built in activities as follows- New activities for manipulating data such as Assign and collection activities such as AddToCollection.

    – New flow control activities, such as DoWhile, TryCatch, ForEach, Switch, and ParallelForEach.

    – Activities for controlling transactions, such as TransactionScope and Compensate.

    – New messaging activities such as SendContent and ReceiveReply.

    Most of these Activities will be explained in the next post for WFF 4.0 toolbar.

    Back to other Workflow Foundation 4.0  posts

I Hope that Helped

September 20, 2010 Posted by | .Net 2010 | , , , , , | 1 Comment

Using NinTex Workflow with Microsoft SharePoint Server 2007

Introduction
All developer spent more times for developing Workflow with SharePoint and end users can’t update or build them business. Now using NinTex Workflow 2007 you can build advanced Workflow in few minutes.
In this post I would like to introduce NinTex for you and how to install, configure, build new one, manage and use Tools for NinTex.
Benefits
Using NinTex you have the following benefits

1- Easy way to use NinTex Workflow and build complete workflow in few minute

2- Huge integration features like Query SQL, XML, Excel services and SharePoint Lists and calling web services.

3- Extend MOSS with advanced workflow capabilities all within a web-based GUI embedded within SharePoint

Installing

For installing NinTex Workflow 2007 just follow this Installation Guide
If you are lazy and don’t like to read it just do this steps Run the Installer, Deploy NinTex Workflow solution for all web application, Import license, configure database and Email and Activate NinTex Workflow in Office Administration site , you web application, site collection and you Site.

Configure or update NinTex Configuration
To configure you NinTex Workflow go to Site Action->site settings then you will see NinTex Workflow section as shown
clip_image002
you can click the option you would like to configure it.

Creating Workflow
there are two ways to create a workflow. First, navigate to a library or list then click the “Settings” button. Then do one of the following steps

1- Select the “Create Workflow” option. The Workflow Designer page will load with the Workflow Template picker at the front.
clip_image002[4]

2- Select the “Manage Workflows” option. The Workflow Gallery page will load. You can then select “Create” from near the top of the page.
clip_image004
clip_image006

Creating Variables
Using NinTex Workflow 2007 you can define new variable and use it into your Workflow. To define variables you need to open work flow variable screen as shown
clip_image008
from this screen just click Create new button to define new variable.

Workflow Actions Groups
NinTex Workflow 2007 has a lot of tools and actions shapes I will give you screen shot for each one and simple description for each one let’s start.
clip_image002[6]

These Actions group contains all common actions that most users need and usually using it.
Set a Condition: used to set conditions in work flow
Request approval: used for asking some user to approve some actions
Send a notification: used for sending notification after approving or denying any request approval action.

image

These Action group contain all actions shapes for integrate NinTex Workflow with other tools like SQL, Excel, Web Services, XML, MOSS Search Query, BizTalk.
So it gives you full functionality to integrate your workflow with a lot of tools.
image

These Actions group used for using SharePoint lists and library and allow you to control some process in your NinTex Work Flow.

image

Logic and flow Actions Group used for doing logical operation like for each, loop, run if statement, run parallel actions, set some conditions, do state machine and change state machine state using action set shape.
image

Operation Actions group used for doing Workflow operation like build sting, calculate date, set or get collection operation, set variable, delay workflow for specific period of time, end workflow, doing math operation, run custom regular expression.

image

The publishing actions group contains only one action shape as shown which responsible for copying or publishing your NinTex Workflow into you share point.

The SharePoint Profile Actions doing some operation into you SharePoint server.

clip_image002[18]
Sites and workspaces actions used for create or delete specific site into SharePoint.

image

User Interaction actions related to use operations like complete task, delegate task, requesting data, sends notifications and task reminders.

All NinTex Workflow actions are simple to configure just I was trying to give you quick and easy introduction if you need any help for any action shape don’t hesitate to send me mail or write comment here.

Hope this helped.

July 16, 2009 Posted by | Developement | , , | 4 Comments

CRM Dynamics 4.0 Work Flow

One important consideration is that Workflows in Microsoft Dynamics CRM are executed asynchronously, and use a Windows service to act as a Host application for the Workflow engine to work. This Windows service is called the Microsoft CRM Asynchronous Processing Service and must be running on the server or else the Workflows won’t execute. Notice that if this service is not running, you won’t see any of the Workflows you created. However, they will run as soon as you start this service because they are queued.

By default, any valid CRM user can create Workflows; however, the permissions to create Workflows can be configured by roles, to prevent users from creating new Workflows that might corrupt the system data.

Workflow Events

Workflow Manager include additional triggering events and run settings.
The events that trigger a Workflow are:
* Record is created  * Record status changes
* Record is assigned * Record attributes change * Record is deleted

Workflow Scope

Workflows created through this interface can be applied to the following areas:
* Users * Business units * Parent: Child business units * Organization

Exporting and Importing Workflows

You can transfer Workflows from one organization to another by exporting them as compressed zip files and then importing them into the new system.

Export

To export a Workflow, navigate to Settings, Customization, Export Customizations. Select Workflows from the View drop-down menu
You can export all Workflows by clicking on More Actions and selecting Export All Customizations or export only the selected Workflows.
The Workflow is downloaded as a compressed zip file. Inside the compressed zip file resides an XML file named customizations.xml.

Import

To import a Workflow, follow these steps:
1- Go to Settings, Customization, Import Customizations
2- Enter the local path of the customization file or click the Browse button to locate the customized Workflow file on your hard disk. Click Upload to continue.

Creating Workflows in Windows Workflow Foundation (WWF) with Visual Studio

we can use work flow with Microsoft CRM Dynamics without writing any number of line code

No-Code Workflow

The CRM 4.0 SDK comes with a new Visual Studio project template to build No-Code Workflows. These No-Code Workflows are Extensible Object Markup Language (XOML) files—they contain Workflow markup in XML format.
The advantages of No-Code Workflows include the following:
* Can be deployed without compiling * Easier to develop
* Can be deployed on live CRM servers or on-premise servers
* Can share WWF activities by adding parallel tasks or loop/while conditions
Before being able to create a No-Code Workflow, you need to install the CRM Workflow project templates. To install these templates, follow these steps:
1- Locate the solution file with the name WorkflowConfigurationTool.sln in the SDK folder\Tools and open the solution file with Visual Studio 2005.
2- Add the missing references Microsoft.Crm.Sdk.dll and Microsoft.Crm.SdkTypeProxy.dll to the CrmWorkflowConfigurationAndDeployment project.
3- Update the web references for the two Web Services and change the compilation mode to release then build the entire solution.
4- Close Visual Studio, go to the SDK\Tools\DeployWorkflowTool\Release folder and execute the setup.exe, click next to confirm installation, click next to continue.
Now you can start Visual Studio 2005 and start creating CRM Workflow assemblies. From Visual Studio, go to File, New, and Project. Expand Visual C# node, click CRM node, and select CRM 4.0 Workflow.
When you create a new project using this template, you will see a new group of activities specially designed to be used with CRM
Note, If you don’t see these activities in the toolbox, right-click the General Tab and click the Choose Items menu option. Then browse and add the Microsoft.Crm.Sdk.dll, which is located in the SDK\bin folder.
To configure and deploy these Workflows, you must install a Visual Studio add-in that comes with the CRM SDK. The add-in installer filename is DeployAddin.msi. Install it by double-clicking the file and following the installation procedure.
The following example shows how to build a Workflow that will create a Phone Call activity for every new Contact added to CRM.
To create the sample, you first must perform the following configuration tasks.

Configuration

Go to the Tools menu in Visual Studio and select the Microsoft Dynamics CRM menu option, Configure Workflow
1- The first screen asks you to choose whether you want to configure the deployment for CRM live or an on-premise CRM server
2- Select the On-Premise option and enter the CRM server address, username, password, and Windows domain name
3- Select the organization where you want to deploy the Workflow then enter a name for the Workflow
4- In the General section, locate the XOML Workflow filename on your hard disk by clicking Browse
5- Move to the Primary Entity selection in the list box and click Update List because all the entity types might not show by default.
6- Select the entity you want to associate the Workflow with. For this example, we use the Contact entity ,In SDK Events, check the Create option
7- Move to local parameters and enter NewContactWelcomePhoneCall as the Parameter name and select the Microsoft.Crm.Sdk.DynamicEntity in the Type Name drop-down box. Then click Add You can create any properties you need here.
8- Click Save and Close.

Development

To develop the Workflow, follow these steps
1- Select the Policy activity, which is under the Windows Workflow section in the toolbox, and drag it into the CrmWorkflow1.xoml file or double-click the item and it will be automatically added.
2- Go to the Properties window and select the RuleSetReference property; then click the … button,Click the New button ,Click the Add Rule button and In the Condition section, enter true
3- In the Then section, enter the following code:

   1: this._NewContactWelcomePhoneCall =Microsoft.Crm.Workflow.CrmWorkflow.CreateEntity("phonecall")
   2: this._NewContactWelcomePhoneCall["subject"] = "Call this new contact"
   3: 

4- Click OK to close the Rule Set Editor. And Click OK to close the RuleSetReference dialog box.

5- Select the CreateActivity item that is in the toolbox under the General group, drag this activity to the Workflow under the PolicyActivity you added in step 1, and go to the properties window.

If you don’t see these activities in the toolbox, right-click the General Tab and click the Choose Items menu option. Then browse and add the Microsoft.Crm.Sdk.dll which is located in the SDK\bin folder

6- Select the Entity property and click on the … button.

7- Select the NewContactWelcomePhoneCall property and Click OK to continue and Save WorkFlow at the end The resulting Workflow should look similar to this figure

image

Deployment

1- Go to the Tools menu in Visual Studio and select the Microsoft Dynamics CRM menu option, followed by Configure Workflow.

2- Click the Deploy button and click Yes to continue and To publish the Workflow click Yes

3- Click OK to continue and Click Save and Close

To see the Workflow that was just deployed, open Internet Explorer and go to the CRM web interface. Go to Settings and then to Workflows.

You can also see the deployed Workflows and publish or unpublish them from Visual Studio. Go to the Tools menu, select the Microsoft Dynamics CRM menu option, and then select Manage Workflows.

Custom Workflow Activities

Custom workflow activities are used to build workflow with code behind using WWF. The difference between them and No-Code workflows that we reviewed previously is that custom workflow activities are compiled in dynamic link libraries (DLL) and can be used from the Workflow interface found in either the Web or Outlook client applications as new steps. To create a custom workflow activity, open Visual Studio 2005 and create a new project using the Workflow Activity Library template that is inside the Visual C#, Workflow project.

After creating the project, you will have to add the references for microsoft.crm.sdk.dll and microsoft.crm.sdktypeproxy.dll.

With this project, you can add any workflow activity from the toolbox as well as add code in C# in the code behind if desired. For our example, we use the same sample we used for the No-Code workflow but this time with a custom activity. Go to see the code behind and replace any existing code with the following:

   1: using System;
   2: using System.ComponentModel;
   3: using System.ComponentModel.Design;
   4: using System.Collections;
   5: using System.Drawing;
   6: using System.Workflow.ComponentModel.Compiler;
   7: using System.Workflow.ComponentModel.Serialization;
   8: using System.Workflow.ComponentModel;
   9: using System.Workflow.ComponentModel.Design;
  10: using System.Workflow.Runtime;
  11: using System.Workflow.Activities;
  12: using System.Workflow.Activities.Rules;
  13: using Microsoft.Crm.Workflow;
  14: using Microsoft.Crm.Sdk;
  15: 
  16: namespace CustomActivityLibrary
  17: {
  18:     [CrmWorkflowActivity("Custom Activity", "Custom Activities Library")]
  19:     public partial class CustomActivity : SequenceActivity
  20:     {
  21:         public CustomActivity()
  22:         {
  23:             InitializeComponent();
  24:         }
  25:         public static DependencyProperty myContactProperty =
  26: DependencyProperty.Register("myContact", typeof(Lookup), typeof(CustomActivity));
  27: 
  28:         [CrmInput("My contact")]
  29:         [CrmReferenceTarget("contact")]
  30:         public Lookup myContact
  31:         {
  32:             get
  33:             {
  34:                 return (Lookup)base.GetValue(myContactProperty);
  35:             }
  36:             set
  37:             {
  38:                 base.SetValue(myContactProperty, value);
  39:             }
  40:         }
  41:         protected override ActivityExecutionStatus Execute(
  42:                                        ActivityExecutionContext executionContext)
  43:         {
  44:             // Get the context service.
  45:             IContextService contextService =
  46:                 (IContextService)executionContext.GetService(typeof(IContextService));
  47: 
  48:             IWorkflowContext context = contextService.Context;
  49: 
  50:             // Use the context service to create an instance of CrmService.
  51:             ICrmService crmService = context.CreateCrmService();
  52: 
  53:             // Creates the Phone Call activity for this conatct
  54:             Microsoft.Crm.SdkTypeProxy.phonecall nyPhoneCall =
  55:                                new Microsoft.Crm.SdkTypeProxy.phonecall();
  56:             nyPhoneCall.subject = "Call this new contact";
  57:             nyPhoneCall.regardingobjectid = myContact;
  58:             crmService.Create(nyPhoneCall);
  59:             return ActivityExecutionStatus.Closed;
  60:         }
  61:     }
  62: }

Build the solution in debug mode to create the assembly.

To deploy the custom workflow activities, register the compiled assembly as a Plug-In using the same plugindeveloper tool we used in, with minor changes to the register.xml file. Here is an example of how the register.xml file should look for our sample:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <Register
   3:     LogFile = "Plug-in Registration Log.txt"
   4:     Server  = "http://crm4"
   5:     Org     = "Webfortis"
   6:     Domain  = "Webfortis"
   7:     UserName= "administrator" >
   8: 
   9:         <Solution SourceType="0" Assembly="C:\CRM4 book\Chapter 20\CustomActivityLibrary\CustomActivityLibrary\bin\Debug\CustomActivityLibrary.dll">
  10:                 <WorkflowTypes>
  11:                         <WorkflowType TypeName="CustomActivityLibrary.CustomActivity" FriendlyName="Custom Activity"/>
  12:                 </WorkflowTypes>
  13:         </Solution>
  14: </Register>

After deploying the custom workflow activity, you can use it on any Workflow. To do this, go to Settings, Workflow, and click New. Enter a name for the workflow and select Contact in the Entity. Click OK to move to the next step. Then click Add Step and you will see the new group called Custom Activities Library with our Custom Activity inside .

Add a step with the Custom Activity and click the Set Properties button.You can set any custom property you added on the code. Our example sets the My Contact property we used to send the current contact where the workflow will be running Click Save, Close to close the Set Custom Step Input Properties and then click Save to save the workflow. Click Publish to test this solution.

important note,You can install custom workflow activities on On-Premise servers only, because they are not supported by CRM Live servers.

February 5, 2009 Posted by | CRM Dynamics 4.0, MS Dynamics | , , | 6 Comments