Keyvan Nayyeri

God breathing through me

How to Write a Custom Workflow Activity

Normally writing a custom workflow is a common task in Windows Workflow Foundation because there are many situations that we need to apply a development process to workflows.  There are several references about writing a custom workflow but I see many newbies who can't understand the process easily.  In my opinion the reason is most resources try to talk about all aspects of writing a custom activity at a glance without simple examples.  So I want to test my chance and write about this topic in this post and some future posts.  I'll begin with a simple custom activity which doesn't have any optional or advanced part of a custom activity.

There are two general types of custom activities: basic and composite.  Both basic and composite activities can work with properties, events and ... but composite activities can do something more.  Composite activities can contain basic or composite activities.  There are some examples of basic and composite activities in built-in workflow activities.  Delay or Suspend are two examples of basic activities and While or Parallel are two examples of composite activities.

It's possible to write a custom basic activity or composite activity but process to write a composite activity is a bit longer than basic activity.

Each activity is constructed of some components but for an activity it's not essential to have all these components:

  • Definition: Main definition for an activity where you define properties, events and ...
  • Executer: This component defines the execution logic for an activity.  For example you can use this component to run child activities in a special order.
  • Validator: Validator components helps you to validate workflow information before runtime so it can let you to prevent from some exceptions as a result of wrong input.
  • Toolbox Item: This component defines default values to be added to a workflow when it's being added to workflow.  For example you can use this component to set a default integer value for a property.
  • Designer: Designer component is all about visual presentation of a workflow and what you see when you're working with it.

Only first component (Definition) is required for an activity to work but usually other components are implemented for an activity.  As you can guess from above description it's not always necessary to have an execution logic, validation logic, default values or a good visual presentation so you can ignore these components based on your needs.

In this post I just want to introduce the core by giving a simple example that only needs first and second components (Definition and Executer).  I write a custom workflow activity that gets two string values: a file path a text.  On execution it creates a text file and writes text value into it.  Before doing anything I create a Class Library project and add appropriate references to it then create a new class file and name it CustomActivity

Alright, I begin with definition component.  To design a custom activity I have to derive my definition from a base class.  For basic activities I must inherit it from System.Workflow.ComponentModel.Activity and for composite activities I must inherit from System.Workflow.ComponentModel.CompositeActivity base classes.  As I want to design a base activity, derive my class from System.Workflow.ComponentModel.Activity:

using System;

using System.Collections.Generic;

using System.Text;

using System.Workflow;

using System.Workflow.Activities;

using System.Workflow.Runtime;

using System.Workflow.ComponentModel;

using System.Workflow.ComponentModel.Design;

using System.IO;

 

 

namespace CustomActivitySample

{

    public class CustomActivity : Activity

    {

Next step is to define my properties.  I'll use DependencyProperties to define my properties and show them in Properties window.  My class also has a getter and setter for these properties but calls GetValue() and SetValue() methods from base class to get or set these dependency properties.  I also put a constructor for my class and set Name property from base class to have a default Name for my activity in Properties window.

public CustomActivity()

{

    base.Name = "CustomActivity1";

}

 

public static DependencyProperty PathProperty = DependencyProperty.Register

    ("Path", typeof(string), typeof(CustomActivity));

public static DependencyProperty TextProperty = DependencyProperty.Register

    ("Text", typeof(string), typeof(CustomActivity));

 

public string Path

{

    get

    {

        return Convert.ToString(base.GetValue(PathProperty));

    }

    set

    {

        base.SetValue(PathProperty, value);

    }

}

 

public string Text

{

    get

    {

        return Convert.ToString(base.GetValue(TextProperty));

    }

    set

    {

        base.SetValue(TextProperty, value);

    }

}

Well, now I write my execution logic for the activity.  To do this I must override Execute() method from base class.  It has an ActivityExecutionContext parameter and returns an ActivityExecutionStatus enumeration.  My logic is simple and just calls File.WriteAllText() method to write text value into file.  At the end my code returns an ActivityExecutionStatus based on what has happened.

protected override ActivityExecutionStatus

    Execute(ActivityExecutionContext executionContext)

{

    try

    {

        File.WriteAllText(this.Path, this.Text);

 

        return ActivityExecutionStatus.Closed;

    }

    catch

    {

        return ActivityExecutionStatus.Faulting;

    }

}

So my final code looks like this:

using System;

using System.Collections.Generic;

using System.Text;

using System.Workflow;

using System.Workflow.Activities;

using System.Workflow.Runtime;

using System.Workflow.ComponentModel;

using System.Workflow.ComponentModel.Design;

using System.IO;

 

 

namespace CustomActivitySample

{

    public class CustomActivity : Activity

    {

        public CustomActivity()

        {

            base.Name = "CustomActivity1";

        }

 

        public static DependencyProperty PathProperty = DependencyProperty.Register

            ("Path", typeof(string), typeof(CustomActivity));

        public static DependencyProperty TextProperty = DependencyProperty.Register

            ("Text", typeof(string), typeof(CustomActivity));

 

        public string Path

        {

            get

            {

                return Convert.ToString(base.GetValue(PathProperty));

            }

            set

            {

                base.SetValue(PathProperty, value);

            }

        }

 

        public string Text

        {

            get

            {

                return Convert.ToString(base.GetValue(TextProperty));

            }

            set

            {

                base.SetValue(TextProperty, value);

            }

        }

 

        protected override ActivityExecutionStatus

            Execute(ActivityExecutionContext executionContext)

        {

            try

            {

                File.WriteAllText(this.Path, this.Text);

 

                return ActivityExecutionStatus.Closed;

            }

            catch

            {

                return ActivityExecutionStatus.Faulting;

            }

        }

    }

}

After writing my code it's time to compile my project and get an assembly.  I create a Sequential Workflow Console Application to test this custom activity and create a new tab and add this activity to my Toolbox.

I drag and drop it to my Sequential Workflow and set my properties in Properties windows.

I run this workflow and check the path specified!  So far so good!!

As you see neither I didn't define any validation component, didn't put any logic for Toolbox Item component and didn't declare a custom presentation for my workflow and Visual Studio draws a default shape for my workflow.  Hopefully in future posts I'll extend this example to add these capabilities to it.

21 Comments

DotNetKicks.com
Jan 25, 2007 12:15 PM
#
You've been kicked (a good thing) - Trackback from DotNetKicks.com

Keyvan Nayyeri
Jan 30, 2007 9:42 AM
#
In previous post about Writing a Custom Workflow Activity I talked about writing a basic custom workflow

Keyvan Nayyeri
Feb 04, 2007 9:19 AM
#
In previous posts I discussed about Writing a Custom Workflow Activity and Writing a Validator for a

Tim Laughlin
Feb 06, 2007 10:10 AM
#
Thanks for the great resource. Being WF newbie this series is a of great help.

Keyvan Nayyeri
Feb 06, 2007 10:26 AM
#
I'm glad to hear that. Thanks Tim :-)

Chris Dunaway
Feb 12, 2007 11:59 AM
#
How would you write a DependencyProperty that was an instance of a class rather that a simple type like string or int? I have tried and the property grid does not expand the class so I can set the individual properties.

Keyvan Nayyeri
Feb 12, 2007 10:53 PM
#
So far I've discussed about these topics about writing a custom workflow activity: How to Write a Custom

dotgrid
May 20, 2007 1:05 AM
#
Code [Here] I happen to participate in an agile workshop where some automated build tools were discussed

PK
Dec 28, 2007 11:23 PM
#

can i design a property of an activity that is fix with some sort of enum values. i mean can we define group of values to set it into a property of an activity


keet
Jan 03, 2008 3:48 AM
#

good one..thanks a lot


keet
Jan 04, 2008 4:59 AM
#

Im writing a custom activity that takes a parameter , proccesses it and should return a value. The value should be exposed as Read Only from the other workflows .can u pls explain how to proceed


gopalakrishnan
Apr 10, 2008 12:29 AM
#

I wondering to work in custom workflow. But now i have the idea. Thanks for your good work.Keep it up.


Mukesh Vashisth
May 28, 2008 11:45 PM
#

excelent.

please display the link of new posts

Pingback from Exploring Workflow Foundation Part 1: Custom Activities « Hungry for Knowledge


Shane
Jul 31, 2008 7:57 AM
#

Nice tutorial - I'm currently in the experimentation/learning phase with workflow and it was of much use!

Thanks.

La conception et le développement de workflow sous SharePoint peut des fois donner le sentiment d'un


Akhilesh Nair
Nov 10, 2008 2:17 AM
#

I have a question. I have created customized workflow using visual studio and have attached it to the SharePoint list. The problem I am getting is when I modify my workflow code and reinstall/reattach it to the list; the workflow items which were already in progress stops progressing further i.e. becomes dead, so each time when I modify workflow I remove the old workflow attach the new one and had to delete the entire old workflow items.

So, is there a way to retain the workflow item in progress to use the new version of workflow when we reinstall the workflow in between. Please advice


Azadeh
Feb 13, 2009 12:31 PM
#

Interesting article Keyvan.

Merci.


Deepshikha
Nov 10, 2009 6:41 AM
#
Very nice article. It gave me understanding of topic very precisely.
:)

Lucio
Mar 03, 2010 11:09 PM
#
Simple,concise and to the point. Thanks.

Osmar
Mar 09, 2010 2:39 PM
#

Excelente articulo (excellent) en especial para los que andamos bajo el WF Thanks again

Leave a Comment





Ads Powered by Lake Quincy Media Network