DCSIMG
December 2006 - Posts - Guy Burstein's Blog

Guy Burstein's Blog

Developer Evangelist @ Microsoft

News

Guy Burstein The Bu

Disclaimer
Postings are provided 'As Is' with no warranties and confer no rights.

Guy Burstein LinkedIn Profile

TwitterCounter for @bursteg

December 2006 - Posts

wca.exe - Workflow Communication Activities Generation

wca.exe - Workflow Communication Activities Generation

I have already written about External Data Exchange mechanism in Windows Workflow Foundation earlier.  I mentioned that using CallExternalMethod and HandleExternalEvent activities is the way to communicate with the hosting environment.
Using these activities, you have to define which External Data Exchange Interface to use, the method to call (or the event to register for) and the arguments. Isn't there a way to create a "Strongly typed" communication activities for a specific Data Exchange Interface?

Well, it turns out there is…

WCA (short name for Workflow Communication Activities) is a tool that when given an assembly which contains External Data Exchange Interface(s), creates custom activities for calling the interface methods and handling the interface events.

Using wca.exe

If you have a Data Exchange interface in a project (it can be either .dll or .exe) that looks somewhat similar to this:

[ExternalDataExchange]

public interface IDocumentApproval

{

    // Send document for approval

    void RequestDocumentApproval(Guid documentId, String approver);

    void ApproveDocument(Guid documentId, String approver);

 

    // Received document for approval

    event EventHandler<DocumentEventArgs> DocumentApproved;

}

You can use wca.exe (located in C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin) with the assembly name as parameter to generate the communication activities. For example:
wca.exe DocumentApproval.dll

The wca.exe will have the following output:

Processing interface 'Bursteg.Samples.WF.wca.IDocumentApproval'
  Generating InvokeMethod for 'RequestDocumentApproval'
  Generating InvokeMethod for 'ApproveDocument'

Wrote file: IDocumentApproval.Invokes.cs
  Generating EventSink for 'DocumentApproved'
Wrote file: IDocumentApproval.Sinks.cs
Done processing.  Exiting.

Examining the output of the tool, you can see that 2 files were created: IDocumentApproval.Invokes.cs that contains 2 Activities that Inherit from CallExternalMethod activity, and IDocumentApproval.Sinks.cs that contains a single activity that inherits from HandleExternalEvent activity. The generated activities match the definition of the original External Data Exchange Interface.

Using wca.exe from Visual Studio

wca.exe is a very useful tool, but will be more convenient to use if it is available within the development environment.

In order to add it as a tool, follow these steps:
1. from Tools menu, select External Tools.
2. In the External Tools Dialog, add a new tool and set the following properties:
Title: WCA (You can change this one…)
Command: C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\wca.exe
Arguments: $(TargetName)$(TargetExt) /o:$(ProjectDir) /c
Initial Directory: $(TargetDir)

wca.exe  Workflow Communication Activities

Using the above settings will generate the output files in the project's directory using the .dll in the target directory (bin\debug).

From now on, you can select any project that contains a External Data Exchange Interface definition, and from the Tools menu select to execute WCA tool. After generating the communication activities, use the "Show All Files" button in the solution explorer to view the new files, and to include them in your project.

Enjoy!

Workflow Persistence Point with PersistActivity | PersistOnClose

Workflow Persistence Point with PersistActivity | PersistOnClose

Workflow Persistence Point The WF runtime persists workflow instances to the persistence store when the execution of an activity with System.Workflow.ComponentModel.PersistOnCloseAttribute on it is completed. One good out-of-the-box example is the TransactionScopeActivity: When it's execution is completed, the Workflow Runtime persists the Workflow instance using the Persistence Service.
If you have a point in your business process where you want to persist the instance of the workflow, and this point is not right after a TransactionScopeActivity has been completed, you can use an activity that will tell the runtime that now is the time to persist. Actually, the activity does nothing, and it is only decorated with PersistOnClose Attribute.

Such an activity will look like:

[PersistOnClose]
public partial class PersistActivity : Activity

{

    public PersistActivity()

    {

        InitializeComponent();

    }

 

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

    {

        return ActivityExecutionStatus.Closed;

    }

}

And you've just created a Workflow Persistence Point with PersistActivity.

Enjoy!

Enterprise Library 3.0 December 2006 CTP is out!

Enterprise Library 3.0 first CTP (December 2006 CTP) is available at http://www.codeplex.com/entlib.

This CTP includes a partial implementation of the Validation Application Block, Application Block Software Factory, Visual Studio-integrated config tool, DAAB enhancements and more.

You can download the CTP from here. You'll also find the release notes for this CTP in this page.

Enjoy!

Receive Windows Live Alerts from my Blog

As of today, you can register and receive updates from my blog using Windows Live Alerts. Just click the Windows Live Alerts icon by my picture, and you're updated.

If you want to setup alerts for your blog, just follow the instructions shown at this page.

Enjoy!

Advanced Workflow Session @ Microsoft Developer Academy

Microsoft Israel is having the biggest event ever been in Israel for developers this January. I am very excited towards this event both about the technologies that will be discussed there, but mostly because I am one of the people who is going to talk about them!
I'll be giving a talk about Windows Workflow Foundation which I have been playing with for the last 6 month! The session is called "Technology In Action! Windows Workflow Foundation Advanced Techniques", and requires some background in WF, since we will go deep into some advanced and very interesting scenarios using WF showing large amount of coding. If you are into watching what WF can do, you should not miss this session. You will go out with great insight about the power that this technology can add to your applications.

See you there!

Software Factory + Application Block = Software Factory Application Block!

"One of the coolest new capabilities in Enterprise Library v3 is the Application Block Software Factory. As its name ever-so-subtly suggests, this will be a software factory for building your own application blocks. We'll be including an early drop of this factory in the first preview release of Enterprise Library v3..."

Check out Tom's blog for more details...

Enjoy!

Are you ready for PDC07?

PDC 2007

 

 

PDC 2007

PDC07 Finally announced! I know I want to be there... How about you?

Build workflow rules using Code Dom and Rules API

A short reminder about rules and conditions

Condition - Expression that evaluates to True or False
Rule – Modeled as:
   If <Condition>
   Then <RuleAction(s)>
   Else <RuleAction(s)>
RuleSet - Collection of Rules with a set of execution semantics.

The RuleSet Editor that ships with Windows Workflow Foundation may be very convenient for developers, but for the end-user or even the business analyst it might not.
Building another user interface for editing rules, developers use CodeDom in order to create their rules conditions and actions on-the-fly.

Both conditions and actions are just code expressions or statements expressed with CodeDom. In order to use them in the context of rules, they must be wrapped with designated wrappers.

Assuming that my custom object (which the rules will be executed on) look like:

public class Technology

{

    public Technology(string tech)

    {

        this.technology = tech;

        this.rocks = false;

    }

 

    private string technology;

    private bool rocks;

 

    public string TechnologyName

    {

        get { return technology; }

        set { technology = value; }

    }     

 

    public bool Rocks

    {

        get { return rocks; }

        set { rocks = value; }

    }

}

Now, I want to create a rule that checks if the technology name is “WF”, and sets rocks property if it is. Describing it with (pseudo) code, the rule looks like:

if (this.Technology == "WF")

    this.Rocks = true;

else

    this.Rocks = false;

Let’s separate the code required to build this rule into several parts:

Building the Condition

// this.

CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression();

 

// .Technology

CodePropertyReferenceExpression technologyRef = new CodePropertyReferenceExpression(thisRef, "TechnologyName");

 

// "WF"

CodePrimitiveExpression wfConstant = new CodePrimitiveExpression("WF");

 

// if ( this.Technology == "WF" )

CodeBinaryOperatorExpression cond = new CodeBinaryOperatorExpression();

cond.Left = technologyRef;

cond.Operator = CodeBinaryOperatorType.ValueEquality;

cond.Right = wfConstant;

Building the ThanAction and ElseAction

// .Technology

CodePropertyReferenceExpression rocksRef = new CodePropertyReferenceExpression(thisRef, "Rocks");

 

// true

CodePrimitiveExpression trueExpression = new CodePrimitiveExpression(true);

 

// false

CodePrimitiveExpression falseExpression = new CodePrimitiveExpression(false);

 

// this.Rocks = true;

CodeAssignStatement assignTrue = new CodeAssignStatement();

assignTrue.Left = rocksRef;

assignTrue.Right = trueExpression;

 

// this.Rocks = true;

CodeAssignStatement assignFalse = new CodeAssignStatement();

assignFalse.Left = rocksRef;

assignFalse.Right = falseExpression;

Wrapping with Workflow Rules objects

// Wrap it all togother

Rule rule = new Rule("rule1");

rule.Condition = new RuleExpressionCondition(cond);

rule.ThenActions.Add(new RuleStatementAction(assignTrue));

rule.ElseActions.Add(new RuleStatementAction(assignFalse));


// Create a RuleSet

RuleSet rs = new RuleSet();

rs.ChainingBehavior = RuleChainingBehavior.None;

rs.Rules.Add(rule);

Executing the RuleSet over an instance of Technology class

Technology t1 = new Technology("WF");

// Validate RuleSet

RuleValidation validation = new RuleValidation(typeof(Technology), null);

rs.Validate(validation);

ValidationErrorCollection errors = validation.Errors;

 

if (errors.Count > 0)

{

    // TODO: Check if there are any errors and handle   

}

 

// Execute

RuleExecution execution = new RuleExecution(validation, t1);               

rs.Execute(execution);

 

Console.WriteLine("{0} {1}!", t1.TechnologyName, (t1.Rocks ? "Rocks" : "does not rock at all!"));           

What is the expected result?

Enjoy!