Pure XOML workflows and a custom root activity

Last week during my Workflow Foundation presentation I was asked a question about using a custom root activity with pure XOML workflows. This is always a bit of a drag to get working, especially because you need to do two things, one for the designer and the other for the runtime.

Let’s start with the following setup.
Solution
WorkflowConsoleApplication4
ActualWorkflow.xoml
WorkflowLibrary4
BaseWorkflow.cs

The BaseWorkflow.cs contains the class BaseWorkflow that is derived from SequentialWorkflowActivity and is the base class we want to use for our ActualWorkflow.xoml.

namespace WorkflowLibrary4

{

public sealed partial class BaseWorkflow : SequentialWorkflowActivity

{

// The actual code

}

}

 

Next we need to add the following to the AssemblyInfo.cs in the WorkflowLibrary4 project:
[assembly: XmlnsDefinition(“urn:WorkflowLibrary4″, “WorkflowLibrary4″)]

 

This associates the schema urn:WorkflowLibrary4 with the assembly and is needed by the workflow designer.

Next add a project reference to WorkflowLibrary4 from WorkflowConsoleApplication4.

Next we need to create the workflow with the same namespace declaration:

<ns0:BaseWorkflow x:Name=ActualWorkflow xmlns=http://schemas.microsoft.com/winfx/2006/xaml/workflow xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml xmlns:ns0=urn:WorkflowLibrary4>

    <!– Add the remainder of the workflow here. –>

</ns0:BaseWorkflow>

The important part is the xmlns:ns0=urn:WorkflowLibrary4> declaration and the <ns0:BaseWorkflow root element.

Rebuild and you should be able to double click on the xoml file and open it in the workflow designer. Go ahead and add any extra activities.

 

So far so good but now we need to run it.

In order for the WorkflowRuntime to know about the BaseWorkflow type we need to add a TypeProvider runtime service. Add the following to the Program.cs:

TypeProvider typeProvider = new TypeProvider(null);

typeProvider.AddAssembly(Assembly.GetAssembly(typeof(BaseWorkflow)));

workflowRuntime.AddService(typeProvider);

 

Next we are ready to load the workflow definition and start one this way:

try

{

XmlReader reader = XmlReader.Create(“ActualWorkflow.xoml”);

XmlReader rules = XmlReader.Create(“ActualWorkflow.rules”);

WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader, rules, null);

instance.Start();

 

waitHandle.WaitOne();

}

catch (WorkflowValidationFailedException ex)

{

// Display load/validation errors

foreach (ValidationError error in ex.Errors)

Console.WriteLine(error.ErrorText);

}

 

In this example I used a declarative rule so there is an additional rules file. Another tidbit is the exception of type WorkflowValidationFailedException that is raised if something is wrong when loading the workflow. The Errors collection will provide the details of what is wrong. The most often seen error in a case like this is the error that some object could not be deserialized. If this happens in the designer first rebuild the solution and if the error persists make sure the namespace in the AssemblyInfo.cs and the ActualWorkflow.xoml actually match up. If the same error occurs at runtime also check if there is a TypeProvider with the assembly in question added to the workflow runtime.

Enjoy!

11 thoughts on “Pure XOML workflows and a custom root activity

  1. I’m facing the same problem but when trying to load the designer in a re-hosted designer environment, Do you have any info about that? thanks

  2. I got problem for loading dll.

    Error: “CreateInstance failed for type ‘ActivitiesLibrary.BaseWorkflow’. Exception has been thrown by the target of an invocation. ”
    my solution has two project: one is “consoleProject” which contains one No-code(pure xoml) workflow(wf.xoml) and program.cs .
    one is “ActivitiesLibrary” which contains one custom activity and one BaseWorkflow(custom root activity:contains the class BaseWorkflow that is derived from SequentialWorkflowActivity and is the base class we want to use for our wf.xoml. )

    So consoleProject needs to get .dll generated by ActivitiesLibrary. the thing is it only works when i Manually add the reference to consoleProject. if I delete the reference and use addAssemblyReference to get the path. it wont work.

    Here is the codes:
    the baseWorkflow classe in “ActivitiesLibrary”
    namespace ActivitiesLibrary
    {
    public sealed partial class BaseWorkflow : SequentialWorkflowActivity
    {
    // The actual code
    }
    }

    the xml file of wf.xoml in “consoleProject”
    xmlns:ns0="clr-namespace:ActivitiesLibrary;Assembly=ActivitiesLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">

    Program.cs
    TypeProvider typeProvider = new TypeProvider(WorkflowRuntime);
    typeProvider.AddAssemblyReference(@”F:\Activities.dll”);
    workflowRuntime.AddService(typeProvider);
    try
    {
    XmlReader reader = XmlReader.Create(“wf.xoml”);
    WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader, null, null);
    instance.Start();

  3. hi, Iam trying a similar example. I am able to run the xoml workflows, but when I try to monitor them using hte Workflow Monitor, I get an exception “+ e {“Could not load type ‘ProcessDocWorkflowLibrary.BaseWorkFlow’ from assembly ‘ProcessDocWorkflowLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’.”:”ProcessDocWorkflowLibrary.BaseWorkFlow”} System.Exception {System.TypeLoadException}

    Can you please suggest me where I am making a mistake.

    The BaseWOrkflow resides in the ProcessDocWorkflowLibrary (xoml + code). The rest of the workflows derive from this base workflow and are xoml only.

  4. Thanks anywayz, I was able to resolve the issue. It was due to the Publictoken being null. I created a strong name and signed the assembly. and used the generated public token in the xoml file , installed the assembly into the GAC. After all this I was able to run the xoml workflow as well as monitor the it.

  5. I’m developing a workflow designer and currently I can create state based and sequencial workflows with custom activities using that and save them to a SQL database as XOML. But when I tried to load previously created ( by my designer) workflow models which uses custom activities to the workflow designer, it says my custom activity type could not be resolved. Workflows without any custom activity can be load easily without any error. This error occurred in

    _designSurface.BeginLoad(wfLoader);
    method. I also printed all the types currently in TypeProvider of wfLoader and it had all the required activities. Can you give me some help to resolve this problem as quickly as possible? I only have two days to complete and demonstrate the project :(

  6. Hi. one question, what about the execute_code of an activity?,
    is possible to add its equivalent in the xoml and rules files?

Leave a Reply

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


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>