WF XAML vs Code

I have been working with Windows Workflow Foundation (WF) for quite a while now and have been going back and forth on how I want to have the designer create my workflow. I figured I would blog about what I know (pro and con) about the two methods and see if I can spark some debate on the subject. The decision on how the workflow is created is made every time you choose a workflow template from the Visual Studio Designer. The two choices are (1) workflow with definition expressed as Xaml and user code in a separate code file or (2) workflow with definition and user code in same code file. These description of option 2 is a little off (I took it from the VS designer) because two physical files are really created one where you put your code and the second where VS puts it’s code and is in the form “xxx.designer.cs” in my case since I use C#. So what’s the big deal you ask?

The deal with the two workflow formats listed above is how you use them, how easy it is to work with them and how hard it is to modify things. How you use them really focuses on one thing which is are you going to work with the workflows dynamically. If not than you really don’t care how they are represented. If you work with a workflow dynamically using XAML you going to load the workflows using an XmlReader like this.

 

 

        using (XmlReader reader = XmlReader.Create(“Workflow1.xoml”))
        {
            WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader);
            instance.Start();
        }

If you plan to do things this way you have a few things to consider. One is how difficult it is going to be to edit the XAML since currently there is no intellisence support in VS for it. Second is how hard it is going to be to debug things. Here is a contrived example I came up with. The following works and there are not errors.

<SequentialWorkflowActivity x:Class=”WorkflowRepresentationChoices.Workflow2″ x:Name=”Workflow2″ xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/workflow“>
 <CodeActivity x:Name=”codeActivity1″ ExecuteCode=”codeActivity1_ExecuteCode” />
</SequentialWorkflowActivity>

Next I changed CodeActivity to CodeeActivity.

<SequentialWorkflowActivity x:Class=”WorkflowRepresentationChoices.Workflow2″ x:Name=”Workflow2″ xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/workflow“>
 <CodeeActivity x:Name=”codeActivity1″ ExecuteCode=”codeActivity1_ExecuteCode” />
</SequentialWorkflowActivity>

Now when I compile I get the following error “Could not deserialize object. The type ‘System.Workflow.Activities.CodeeActivity’ could not be resolved.”. The problem with this is that I don’t get much help from the editor in where this is. No squiggly lines or anything. Now this is by no means a show stopper but it is a productivity issue that you should think about. To continue on the debugging topic for just a little more think about the errors you could encounter when calling workflowRuntime.CreateWorkflow(reader) in the above code sample. If the XAML has errors like our contrived example above you will be dealing with the WorkflowValidationFailedException which is thrown if the XAML is invalid. This exception will contain data that you can use to figure out what is going on but again this is another added level of complexity you need to be aware of. Finally there is the issue of code behind. Since the XAML is just that a XAML file your code behind is not included. This changes how you can create a workflow and really forces you to use a more complex approach to workflow development that can sometimes require creating a custom activity to perform some simple logic that could have been done in code behind. So before you read on I want to make one thing clear. The XAML approach is not bad and provides possibilities not available in the code version but there are some things to think about if you use it.

Now let’s look at the code version. This style is similar to what the WinForms designer has been doing for a while. You have a series of .NET code statements that build up a workflow. The above activity example looks like this in the code version.

/// <summary>
/// Required method for Designer support – do not modify
/// the contents of this method with the code editor.
/// </summary>
System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
    this.CanModifyActivities = true;
    this.codeActivity1 = new System.Workflow.Activities.CodeActivity();
    //
    // codeActivity1
    //
    this.codeActivity1.Name = “codeActivity1”;
    this.codeActivity1.ExecuteCode += new System.EventHandler(this.codeActivity1_ExecuteCode);
    //
    // Workflow1
    //
    this.Activities.Add(this.codeActivity1);
    this.Name = “Workflow1”;
    this.CanModifyActivities = false;
}

The work in the code behind version happens in the InitializeComponent method and at the end of the method the Code activity is added to the workflow. So with this approach you do get intellisence and it is easy to debug but it’s a little harder to read and you don’t get any ability to dynamically bring in a workflow since the code to create it (see below) requires the type of the workflow. Now I want to say that you can create a workflow dynamically in this case but you have to use a little reflection to make it happen and it’s not a easy as the above XmlReader code.

            using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowRepresentationChoices.Workflow1));
                instance.Start();

            }

The other thing in your favor here is that the workflow will be compiled and validated when you load it. In the case of the XAML and the XmlReader the validation occurs as the workflow is created.

So with all of this said what do you choose? If you are a code person you choose the code version and if you need to do things dynamically you use reflection. If you are an xml person you use XAML and you design you workflows in an abstract manner (use activities for everything) if you want to load them dynamically. Of course if you are doing things dynamically and do have a bunch of files in a directory, being able to open them up in an editor and seeing what they do can be helpful. For me I so desperately want a full fledged intellisense XAML editor that I can use to go back and forth with like I can do in WPF. I just love that experience.

Leave a Reply

Your email address will not be published. Required fields are marked *