Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Get Your Code Flowing Faster with Windows WorkFlow Foundation : Page 3

Activities, decisions, and rules often feel like constraints for human beings, but for applications they are the lifeblood of making things work. Windows Workflow Foundation presents a new programming paradigm that lets these declarative principles guide your coding.




Application Security Testing: An Integral Part of DevOps

Using a Windows Application as a Workflow Host
In the previous section you saw how to create a sequential workflow console application. Using the sample application, you saw how the workflow interacts directly with the user through the console. In that sample, the console application is the workflow host as it essentially hosts the workflow and executes it.

A much more realistic approach would be to use a Windows application (or ASP.NET Web application) as a workflow host, with the workflow working in the background. In this section, you will learn how to use a Windows application as a workflow host and how it interacts with the workflow.

The application you will build in this section is a simple interest rate comparator. Suppose you have some money to deposit in the bank. Some banks offer different interest rates for different currencies, and hence you want to maximize your returns by investing your money in the currency that offers the highest returns. Here are the assumptions:

  • The principle is in Singapore Dollars (SGD).
  • The interest rate for US Dollars (USD) is 5% p.a. for amounts less than or equal to US$10,000, 7% for amounts greater than US$10,000.
  • The interest rate for Chinese Yuan (CNY) is 4% p.a. for amounts less than or equal to ¥10,000, 8% for amounts greater than ¥10,000.
  • US$1 = SGD$1.59 and ¥1 = SGD$0.20.
The above interest rates and exchange rates are hypothetical and are purely used for illustration purposes only.

Creating the Workflow Library
First, create a new Sequential Workflow Library application using Visual Studio 2005 (see Figure 13).

Figure 13. Create a new Sequential Workflow Library application.
Figure 14. The completed workflow is shown.

In the Workflow Designer, drag and drop the following activities:
  • Parallel
  • Code

The Parallel activity allows you to perform two different activities in parallel.

Set the Name property of the first Code control to USDInterests and set its ExecuteCode property to CalculateUSDInterests.

Set the Name property of the second Code control to CNYInterests and set its ExecuteCode property to CalculateCNYInterests.

The workflow should now look like Figure 14.

In the code-view of Workflow1.vb, enter the code that follows in boldface type:

Public class Workflow1 Inherits SequentialWorkflowActivity Private _amount As Single Private _USDInterestsAmount As Single Private _CNYInterestsAmount As Single Const SGDTOUSD As Single = 1.59 Const SGDTOCNY As Single = 0.2 Public ReadOnly Property USDInterestsAmount() As Single Get Return _USDInterestsAmount * SGDTOUSD End Get End Property Public ReadOnly Property CNYInterestsAmount() As Single Get Return _CNYInterestsAmount * SGDTOCNY End Get End Property Public WriteOnly Property Amount() As Single Set(ByVal value As Single) Me._amount = value End Set End Property Public Sub New() MyBase.New() InitializeComponent() End Sub Private Sub CalculateUSDInterests( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Dim USDEqv As Single = _amount / SGDTOUSD If USDEqv <= 10000 Then _USDInterestsAmount = CSng(USDEqv * 0.05) ElseIf USDEqv > 10000 Then _USDInterestsAmount = CSng(USDEqv * 0.07) End If End Sub Private Sub CalculateCNYInterests( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Dim CNYEqv As Single = _amount / SGDTOCNY If CNYEqv <= 10000 Then _CNYInterestsAmount = CSng(CNYEqv * 0.04) ElseIf CNYEqv > 10000 Then _CNYInterestsAmount = CSng(CNYEqv * 0.08) End If End Sub End Class

Essentially, you are doing the following:
  • Declaring three private member variables to store the principle amount (_amount), the interest amount for USD (_USDInterestsAmount), and the interest amount for CNY (_CNYInterestsAmount).
  • Defining two constants (SGDTOUSD and SGDTOCNY) containing the exchange rate of USD and CNY. For simplicity I am hard-coding the exchange here. In real-life, you can get the rate from a Web service.
  • Defining two read-only properties—USDInterestsAmount and CNYInterestsAmount—to allow the workflow host to access the calculated interest rates.
  • Defining a write-only property (Amount) to let the workflow host set the principle amount.
  • Defining the two subroutines (CalculateUSDInterests() and CalculateCNYInterests()) for the ExecuteCode property of the two Code activites. Here, you will calculate the interests for USD and CNY deposits.
As you can see, the workflow library interacts with host primarily through properties exposed by the workflow library.

Creating the Workflow Host
With the workflow library created, let's create a Windows application to act as the host for the workflow. In Solution Explorer, right-click on the solution name and add a new Windows Application project. Name the project C:\WorkFlowWindowsApplication.

Add the references to the following DLLs (see also Figure 15):

  • System.Workflow.Activities
  • System.Workflow.ComponentModel
  • System.Workflow.Runtime

  • Figure 15. Add the references to the three WF DLLs.
    Figure 16. Populate the Form1 with Label, TextBox, and Button controls as shown.

    In the default Form1, populate it with the following controls (see also Figure 16):
    • Label controls
    • TextBox controls
    • Button control
    In the code-behind of Form1, import the following namespaces:

    Imports System.Workflow.Runtime Imports System.Threading

    Declare the following member variable:

    Public Class Form1 Private WaitHandle As AutoResetEvent

    In the event handler for the Calculate button, you will create an instance of the WorkflowRuntime class. The WorkflowRuntime class exposes functionality required by a host application as well as services to configure and control the workflow runtime engine. It also receives notification of changes to both the workflow runtime engine and any of its workflow instances. Here, you will add two event handlers to monitor the completion and termination events of the workflow: WorkflowCompleted and WorkflowTerminated.

    The principle amount used for calculating interest amounts is used to create an instance of the WorkflowInstance object, together with the workflow library (WorkflowLibrary1.Workflow1) you created earlier. You need to pass in the Amount property through the use of the Dictionary object:

    Private Sub btnCalculate_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnCalculate.Click WaitHandle = New AutoResetEvent(False) '---Create the WorkflowRuntime--- Using workflowRuntime As New WorkflowRuntime() '---monitor workflow events--- AddHandler workflowRuntime.WorkflowCompleted, _ AddressOf OnWorkflowCompleted AddHandler workflowRuntime.WorkflowTerminated, _ AddressOf OnWorkflowTerminated '---prepare the parameters to be passed into the workflow--- Dim parameters As Dictionary(Of String, Object) = _ New Dictionary(Of String, Object)() parameters.Add("Amount", CSng(txtAmount.Text)) '---Create and start an instance of the workflow--- Dim workflowInstance As WorkflowInstance workflowInstance = _ workflowRuntime.CreateWorkflow( _ GetType(WorkflowLibrary1.Workflow1), parameters) workflowInstance.Start() '---wait for the event to be signaled--- WaitHandle.WaitOne() End Using End Sub

    When the workflow has completed execution, the OnWorkflowCompleted() event will be fired. Here, you will obtain the calculated interest rates exposed by the workflow (as read-only properties) through the OutputParameters collection in the WorkflowCompletedEventArgs object. As this event runs in a separate thread, you need to take special care when updating the TextBox controls by using delegates.

    '---fired when the workflow instance is completed--- Private Sub OnWorkflowCompleted( _ ByVal sender As Object, _ ByVal e As WorkflowCompletedEventArgs) WaitHandle.Set() '---update the txtCNYInterests TextBox control--- If Me.txtCNYInterests.InvokeRequired Then Me.txtCNYInterests.Invoke( _ New EventHandler(Of WorkflowCompletedEventArgs) _ (AddressOf Me.OnWorkflowCompleted), _ New Object() {sender, e}) Else Me.txtCNYInterests.Text = _ e.OutputParameters("CNYInterestsAmount").ToString() End If '---update the txtUSDInterests TextBox control--- If Me.txtUSDInterests.InvokeRequired Then Me.txtUSDInterests.Invoke( _ New EventHandler(Of WorkflowCompletedEventArgs) _ (AddressOf Me.OnWorkflowCompleted), _ New Object() {sender, e}) Else Me.txtUSDInterests.Text = _ e.OutputParameters("USDInterestsAmount").ToString() End If End Sub

    Figure 17. When you test the application you should be able to see the interest rate for each currency.
    Finally, service the OnWorkflowTerminated event, which will be fired when the workflow is terminated.

    Private Sub OnWorkflowTerminated( _ ByVal sender As Object, _ ByVal e As WorkflowTerminatedEventArgs) Console.WriteLine(e.Exception.Message) WaitHandle.Set() End Sub

    That's it! Right click on WorkflowWindowsApplication in Solution Explorer and select Set as Startup Project. Then press F5 to debug the application. Enter an amount to calculate the interest for each currency and click the Calculate button. You will see the interest rate for each currency (see Figure 17).

    You should also observe that you can change the logic of the application by modifying the code in the workflow. For large-scale systems, this is a great benefit as you can now modify the workflow of the system without worrying about the front end.

    In this article, you have seen the basics of Windows Workflow Foundation and how you can create workflow-enabled applications using Visual Studio 2005. In subsequent articles, I will dive into other detailed features of Windows WF.

    Wei-Meng Lee is a Microsoft MVP and founder of Developer Learning Solutions, a technology company specializing in hands-on training on the latest Microsoft technologies. He is an established developer and trainer specializing in .NET and wireless technologies. Wei-Meng speaks regularly at international conferences and has authored and coauthored numerous books on .NET, XML, and wireless technologies. He writes extensively on topics ranging from .NET to Mac OS X. He is also the author of the .NET Compact Framework Pocket Guide, ASP.NET 2.0: A Developer's Notebook (both from O'Reilly Media, Inc.), and Programming Sudoku (Apress). Here is Wei-Meng's blog.
    Comment and Contribute






    (Maximum characters: 1200). You have 1200 characters left.



    Thanks for your registration, follow us on our social networks to keep up-to-date