Welcome to Windows Workflow Foundation (WF)
Top Tasks :

WF Community Bloggers

Tuesday, May 20, 2008 - Posts

  • Runtime modification of workflow's

    Modifying already executing workflow's is a very powerful option. Now, as with most advanced options, not something you are going to need every day but certainly something to be aware of and use when the needed.

     

    First lets take a quick look at why we would want to modify an already running workflow in the first place.

    Consider the following scenario. You have long running, lets assume a year on average, and part of the workflow has to do with shipping products. And lets assume that the shipping is done by any one of a number op shippers and that this involves multiple steps, sort of a mini workflow itself, which are different for each shipper. Now you could add a big IfElseActivity with a branch for each possible shipper and be done with it. But now suppose the company starts doing business with a new shipper. So you go and add an branch to the IfElseActivity and implement the new shipper, no big deal. But all already running workflow's are based upon the original workflow without the new shipper, so they cannot use the new shipper. And if the new shipper is a lot cheaper that means you have to explain why all the additional shipping costs are made :-(

    So how to solve a problem like this?

    Well is we decide to add the shipping activity to the workflow at runtime, at the moment we actually need it, we get the flexibility we need. In fact it even makes the workflow simpler as we don't need to implement the big IfElseActivity. And in software development simple is good :-)

     

    So what do we actually need to change an executing WorkflowInstance? The class to start with is the WorkflowChanges. This WorkflowChanges object has a property named TransientWorkflow that lets us get to the actual workflow definition. Now we can use this to add the activities we want. In fact we can also change or remove activities as well.

    One easy way is to add a SequenceActivity as a placeholder where you want to add your new functionality like this:

    image

    Adding an extra activity is done from codeActivity3 (actually the second in the workflow) with the following code:

    WorkflowChanges changes = new WorkflowChanges(this);
    
    SequenceActivity activity = 
        (SequenceActivity)changes.TransientWorkflow.GetActivityByName("dynamicActivity");
    
    NewActivity newActivity = new NewActivity();
    newActivity.TextToPrint = "This is a dynamically added activity!";
    activity.Activities.Add(newActivity);
    
    ValidationErrorCollection validationErrors = changes.Validate();
    if (!validationErrors.HasErrors)
        try
        {
            ApplyWorkflowChanges(changes);
        }
        catch (WorkflowValidationFailedException ex)
        {
            validationErrors = ex.Errors;
        }
    
    foreach (var error in validationErrors)
        Console.WriteLine(error);
    

     

    The most important thing to notice is that the ApplyWorkflowChanges is the one that actually changes the running WorkflowInstance. And if the update fails for some reason an WorkflowValidationFailedException is thrown with a property Errors that is a collection of ValidationError objects.

    Before using the ApplyWorkflowChanges function we van validate the changes. This will catch some, but not all possible, errors so just validating and removing the try/catch is not recommended.

    Enjoy!

    www.TheProblemSolver.nl
    http://wiki.WindowsWorkflowFoundation.eu

  • Validating workflow activity metadata

    There are several options for validating properties on a custom activity.

    Besides the possibility of using an ActivityValidator as described here we can also use the ValidationOptionAttribute. Now the ValidationOptionAttribute isn't useful all the time and only for a limited set of properties.

    First of all the limited set of properties. This will only work for dependency properties defined with DependencyPropertyOptions.Metadata. This makes them metadata and they cannot be changed at runtime, only design time.

    The second is the limitation in that is can only enforce a required field. No specific values or even an error tekst.

    So using this is a little weird to. With the ValidationOptionAttribute being an attribite the first thing that comes to mind is decorating the property with it. Well that doesn't seem to do anything Sad.

    [ValidationOption(ValidationOption.Required)]
    public string MyMetadataProperty
    {
        get
        {
            return ((string)(base.GetValue(ValidatedActivity.MyMetadataPropertyProperty)));
        }
        set
        {
            base.SetValue(ValidatedActivity.MyMetadataPropertyProperty, value);
        }
    }
    

    No in fact what you need to do is add it to the DependencyProperty constructor like this:

    public static DependencyPropertyMyMetadataPropertyProperty =
        DependencyProperty.Register("MyMetadataProperty",
        typeof(string),
        typeof(ValidatedActivity),
        newPropertyMetadata(DependencyPropertyOptions.Metadata,
            newAttribute[] { newValidationOptionAttribute ValidationOption.Required) }));

    Not very inuitive at all.

    I guess the only benefit of this is not having to include a ActivityValidator but as far as I am concerned this is not a big benefit.

    Enjoy!

    www.TheProblemSolver.nl
    http://wiki.WindowsWorkflowFoundation.eu

<May 2008>
SuMoTuWeThFrSa
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Copyright © 2006 Microsoft Corporation. All Rights Reserved. | Terms of Use | Privacy Statement | Contact Us