Windows Workflow Foundation (Basics): How to handle external events and to trigger state transitions using a HandleExternalEvent activity


MSDN's description for a HandleExternalEvent reads as "Defines a workflow communication activity that is used to handle an event that is raised by a local service". In this blog I will try to expand on that definition.

Imagine a simple state machine representing a moving (state = Moving) or non-moving (state = Stopped) vehicle. For simplicity, let's assume that the vehicle can only start moving if the driver accelerates and it stops when the brakes are applied:

WF's state machine runtime allows services to raise events which can be handled by the state machine. In other words, a local service could perhaps communicate with a state machine via this route.

Let’s create a simple service project which will allow us to raise both the accelerate and brake events:

- Create an empty class library called VehicleService
- Inherit from ExternalDataEventArgs and mark the inherited class as serializable (it must be marked as serializable in order to be sent to the state machine):

public class MovementChangeEventArgs : ExternalDataEventArgs
   private MovementChangeType _movementChangeType;
   public MovementChangeType MovementChangeType
      get { return _movementChangeType; }
      set { _movementChangeType = value; }


   public MovementChangeEventArgs(Guid instanceId, MovementChangeType
movementChangeType) : base(instanceId)
      _movementChangeType = movementChangeType;
      this.WaitForIdle = true;

public enum MovementChangeType

- Create an interface which can be shared by both the local service (the service which has the responsibility for raising the event) and the state machine.
- Add only a single event to that interface

public interface IVehicleService
   event EventHandler<MovementChangeEventArgs> MovementChanged;

- As you can see above, the interface is marked with the ExternalDataExchangeAttribute attribute which flags the interface as a local service used for data exchange purposes.
- The next step is to implement the IVehicleService interface:

public class VehicleService : IVehicleService
   public void RaiseEvent(MovementChangeEventArgs args)
      EventHandler<MovementChangeEventArgs> movementChanged = MovementChanged;
      if (movementChanged != null)
         movementChanged(null, args);
   public event EventHandler<MovementChangeEventArgs>MovementChanged;

This interface now can be registered with the state machine. For this, you will need a HandleExternalEvent activity as the first event driven activity within the workflow of both the stopped and moving states:

- VehicleService class library must be referenced by the workflow project
- Go to the stopped state and drop a HandleExternalEvent activity as the first item within the event driven workflow. You will also need to set the following properties on this activity:
   o InterfaceType: IVehicleService
   o EventName: MovementChanged
- Now attach an event handler to the Invoked event of this activity which is called when the MovementChanged event is invoked. At this stage, you have a number of options open to you. One option is to keep the result of the event using a local property. You could perhaps add an IfThenElse activity followed by a SetState to your workflow which could trigger a state transition based on that local property.

The very last step is to make the workflow runtime aware of the service:

WorkflowRuntime workflowRuntime = new WorkflowRuntime();
ExternalDataExchangeService dataExchange = new ExternalDataExchangeService();
VehicleService vehicleService = new VehicleService();

You can now simply raise events by calling the RaiseEvent method of the vehicleService instance:

new MovementChangeEventArgs(instance.InstanceId,

Please let me know what you think about this blog entry.