Home » Articles | WWF

Easy embed workflow in your application

18. February 2009 by Juliën Hanssens 7 Comments

Windows Workflow Foundation (WF) has a bit of a steep learning curve. It’s a different way of thinking, but it is a great addition for providing insight in complex processes.

Whilst enterprise architectures mostly focus on BizTalk as a standalone server, WF is meant to be a more core-based addition for embedding within application. Embedding is not always as intuitive as it should be, though.

The reason: initializing – and thus running - a Workflow, like you do any common object, is a bit of a pain. Especially when you do not want to use the built-in Run-As-Service option.

Besides running the damn thing, it can also be quite non-intuïtive to pass along objects (or parameters) to your flow. And than I’m not even mentioning handling exceptions, or rethrowing them. This also could be a bit frustrating if you initially start with Workflow Foundation.

Helper class WorkflowExecutive

To this end, I’ve created the following self-titled "WorkflowExecutive" helper class. It allows you to easily start any referenced Workflow and pass along parameters to it.

Here is the base code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
 
namespace Securancy.Extensions.Workflow
{
    public static class WorkflowExecutive
    {
        /// <summary>
        /// Dynamically executes a workflow during runtime.
        /// </summary>
        /// <param name="workflowType">typeof<T> where T is the Workflow Type.</param>
        /// <param name="namedArgumentValues">Dictionary list (string, object) with the optional parameters.</param>
        /// <remarks>
        /// The static InvokeWorkflow method allows you to easily execute an existing workflow or activity. 
        /// It will also rethrow any unhandled errors thrown by a workflow. 
        /// </remarks>
        /// <example>
        ///     Dictionary<string, object> args = new Dictionary<string, object>();
        ///     Person customerParam = new Person();
        ///     customerParam.BirthDate = DateTime.Now.AddYears(-21);
        ///     args.Add("CustomerInstance", customerParam);
        ///     
        ///     InvokeWorkflow(typeof(ZeelandNet.Services.BusinessProcesses.ValidateCustomer), args);
        /// </example>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Justification = "Exception ex = a valid Exception Type.")]
        public static void InvokeWorkflow(Type workflowType, Dictionary<string, object> namedArgumentValues)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
 
                Exception eResult = null;
 
                #region -- Workflow Events --
 
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
                {
                    // All is well:
                    waitHandle.Set();
                };
 
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
                {
                    // An exception has occured:
                    if (e.Exception != null) { eResult = new Exception(e.Exception.Message, e.Exception); }
                    waitHandle.Set();
                };
 
                #endregion
 
                // Initialize and start the workflow:
                WorkflowInstance workflowInstance = workflowRuntime.CreateWorkflow(workflowType, namedArgumentValues);
                workflowInstance.Start();
 
                waitHandle.WaitOne();
 
                #region -- Finalize and cleanup --
 
                // If the WorkflowRuntime threw an error, spit it out:
                if (eResult != null) { throw eResult; }
 
                #endregion
 
            }
        }
    }
}

This sample allows you to do the following:

  • Start Workflow by type
  • Pass along parameters to your flow (Dictionary<string, object>)
  • Handle exceptions, if any…

How to use it

Once you have added the above class to your project, you can easily run a Workflow, or Activity, using something like the following example:

// Create container for parameters ('Properties' in your Workflow):
Dictionary<string, object> args = new Dictionary<string, object>();
 
// Provide the property 'Name' - and the instance (note: replace MyCustomerObject with any Type):
MyCustomObject parameter = new MyCustomObject();
args.Add("NameOfYourProperty", parameter);
 
// Start your Worfklow:
WorkflowExecutive.InvokeWorkflow(typeof(MyWorkflowName), args);

There you go!

Just in case: using parameters in Workflows is a bit different than with regular objects. A workflow requires a Dictionary<string, object> to be passed not through the constructor – but as a public property! So, if you keep this in mind and define the “NameOfYourProperty” as a public property in your Workflows’ codebehind, you’ll do just fine.

Comments

trackback
DotNetKicks.com said:

Trackback from DotNetKicks.com

Easy embed workflow in your application

Maarten Balliauw
Belgium Maarten Balliauw said:

Even cooler syntax to run the workflow would be this:

// Start your Worfklow:
WorkflowExecutive.InvokeWorkflow(typeof(MyWorkflowName), new {
  MyParam1 = "Test",
  SomeIdToQuery = 1234,
  OtherProperty = "No"
});

It will require some reflection over the properties of the anonymous class, but it is really a nice way of working with key/value pairs (idea from ASP.NET MVC).

Hanssens
Hanssens said:

@Maarten Balliauw:

Thank you, Maarten. It is a great suggestion! I will give it an update soon.

trackback
DotNetShoutout said:

Trackback from DotNetShoutout

Easy embed workflow in your application

Zachary Hunter
United States Zachary Hunter said:

This sounds much easier that what I've been reading about.  I got some new projects where I think WF would be a huge help, but I've been losting in getting started.  A lot of online demo do not provide source code, and in the process of manually trying to reproduce code based on instructions it seems the source articles always leave something missing.  Do you think you could throw a working example together based on this helper, something with a basic workflow/activity that shows your helper in action.  I get the gist of what WF is supposed to do, but I really want to see it in action on my machine and so I can follow the execution and see how all the magic happens.  If anybody has any suggestions on where to find good "complete" working WF sample/demo, I'd really appreciate the link!  Thanks!  --Zach

 Juliën Hanssens
United States Juliën Hanssens said:

@Zachary Hunter
Thanks for your positive feedback, Zachary. I will start writing on a practice based post which will demonstrate the usage of the above class in a basic, and hopefully inspirational, Workflow sample.

trackback
moggoly.me.uk said:

Trackback from moggoly.me.uk

Workflow Helper

Comments are closed