Introduction

Windows WorkFlow (WF) is a powerful framework for creating enterprise level workflows. Such power also brings great complexity. Much of WF is "roll your own", you are provided the core components but much of the required elements are up to you to provide. There are many ways of hosting workflows, this article describes hosting workflows using .asmx web services.

This example project shows a complete WF solution composed of a DotNetNuke module communicating with a WF workflow hosted in the Open Source project IWebWF (IWebWF.com). The project is called Vacation Requests and it allows users to make requests for time off from work. The requests will be processed by the workflow using the following business rules:

If Employee has enough days available and they are requesting less than 4 days, automatically approve the request.

If they don’t have enough days available, or more than 3 days are requested, then require approval.

This article examines the project using the following outline:

Overview of Vacation Request 2.0

Set-up

Make a request

How to call a web service dynamically

Approve a request

Create a CheckDigit and call the Vacation Request Workflow web service

Call the DNN web service and update the record

Logging

DNN Module

History Page

IWebWF

Using the IWebCore for Logging and Emails

Status page shows actively persisted workflows

Details page identifies the workflow

Security

Workflow is "disconnected". It only uses web services in and out.

The CheckDigit is used to open and close "the door"

Overview of Vacation Request 2.0

The following diagram shows the basic structure of the Vacation Request application:

The "front-end" of the application resides in a module running in the DotNetNuke website. The "back-end" processing for the application resides in the workflow running in the IWebWF website. The DotNetNuke module and the workflow communicate using web services.

The DotNetNuke module exposes the following web services:

UpdateVacationRequest - Allows the workflow the ability to update a vacation request record.

GetUserDetails - Provides details about a vacation request including the days a user has available.

ApproveRequest - Allows the DNN module the ability to approve a vacation request.

WF workflows can be hosted in a number of different ways. A workflow could even be hosted in the DotNetNuke website. This design was chosen because it allows the solution to be scaled by adding multiple instances of the IWebWF application. In addition, the workflow components and persistence services can be resource intensive. It is desirable to off-load this from the DotNetNuke website.

Windows Communication Foundation (WCF) can be used instead of the .asmx web services described in this solution. While this works, WCF introduces complications when constructing the WCF services that provide unnecessary challenges, such as needing complex configuration files to bind the protocol and the transport.

DotNetNuke

Log in as an administrator and click the [Set Webservice URL] link and set the web service link to point to the VacationRequest.asmx page in the IWebWF site.

The [Edit Users Vacation Days] (from the main page of the module) allows the administrator to set the available days for users.

Also, ensure the DNN admin account has an email address and the SMTP settings are configured in the DNN site.

Make a Request

A vacation request starts in the DNN module. It makes a web service call to the workflow web service. The DNN module creates a random number and saves it in the database as a CheckDigit. The RequestID, the CheckDigit, the Portal administrator and users email addresses are passed to the workflow web service.

Creating a proxy in DNN to call an external web service

To allow a DNN module to call an external web service and change the address dynamically, a VacationWebService project is created that contains a normal .asmx web proxy that connects to the workflow web service in the IWebWF site.

The project is compiled and the VacationWebService.dll file that is created, is placed in the "Bin" directory of the DNN site. This allows you to instantiate the class with code such as this:

The VacationRequestWorkflow.cs file contains the workflow logic for the workflow.

The StartVacationRequest activity is bound to the StartWorkflow web method that starts the workflow. After the workflow is started, the wsGetUserDetails activity calls the GetUserDetails web service in the DNN site.

The workflow is able to set the web address dynamically by wiring-up a method to the Invoking event and setting the url of the .asmx web proxy that points to the web service in the DNN module.

// Set the URL to the web service to the URL that was passed whe the Workflow was started
wsVacationRequest.WebService objWebService = (wsVacationRequest.WebService)e.WebServiceProxy;
objWebService.Url = WebService;

The workflow calls this web service method in the DNN site which returns information about the vacation request:

After the workflow receives the information about the vacation request, the process reaches the ifElseActivity_ProcessRequest decision point. There are three possible activity groups that could be processed based on the values received from the DNN web service.

When you right-click on the TerminateWorkflowBranch...

and select Properties, you will be able to see the see the rule conditions that determine the execution of that branch (the days requested, and the vacation days are 0).

The same process can be performed to see the rule conditions for the NeedsApprovalBranch (the days requested is more than 3 days, or the days requested is more than the vacation days, or the vacation days minus the days requested would be less than 0).

The ApprovedBranch does not have a rule condition and will be executed by default if the rule conditions for TerminateWorkflowBranch and NeedsApprovalBranch are not met (the ifElseActivity branches are evaluated from left-to-right).

Approve a Request

If the days requested and the vacation days are 0 the workflow will terminate. If a request is for less than 4 days and there are sufficient days available, the request is automatically approved. An email is sent to the user, and the workflow terminates.

For all other situations, the NeedsApprovalBranch branch is executed. This branch contains activities that call the web service in the DNN site to update the record. It sets the record as needing approval, and sends an email to the administrator indicating that there is a record that needs approval.

The workflow then proceeds to the WaitForApproval activity. This activity contains the ApprovalWebService group.

The WaitForApproval activity is a WhileActivity that will stay in a loop until the Code Condition is met. It will not break out of the loop until the value of CheckIsTimeToStop methodreturns true.

The wsApprovalRequest_Input activity is the first activity in the ApprovalWebService group. The wsApprovalRequest_Input activity is bound to the ApproveRequest web method in the workflow. It will now wait for a web service call from the DNN site to approve the request.

DNN Module

When logged into the DNN site as an administrator, the [Approve Requests] link will take you to the approval page.

The following code creates a new random CheckDigit and calls the workflow web service:

Vacation Request Workflow

The workflow receives the approval call from the DNN site and processes the activities in the ApprovalProcess activity group. The wsUpdateVacationRequestApproval activity calls the following UpdateVacationRequest web service method in the DNN site to update the record:

In the workflow, the isTimeToStop value is set to true which causes the CheckIsTimeToStop method to return true.

#region CheckIsTimeToStop
// This method will return the value of isTimeToStop// The value of isTimeToStop will be set by other// methods in the workflowprivatevoid CheckIsTimeToStop(object sender, ConditionalEventArgs e)
{
e.Result = !(isTimeToStop);
}
#endregion

This causes WaitForApproval activity to stop and the workflow terminates. The process is complete.

Logging

When workflows are running it is hard to know what is going on without logging.

The DNN module provides some logging by clicking on the [History] link (when logged in as an administrator).

The VacationRequest workflow project contains a reference to the IWebCore project that allows it to easily log actions with code such as this:

The logged events show in the administration page in the IWebWF website.

In addition, the workflow status page in the IWebWF website shows any currently persisted workflows. These are workflows that are waiting for some sort of action before they can terminate. The persistence service automatically saves the state of idled workflows and automatically reactivates them when needed. This allows long running workflows to survive during server restarts.

Clicking on a workflow GUID on the Status page displays the workflow name and it's activities.

Security

Windows workflow allows you to design security in any way you prefer. This example uses the following security design:

The workflow is "disconnected". It only communicates using web services

The workflow does not "believe" any information passed to it. The available days for an employee cannot be passed to it directly. When the workflow is started, it uses the vacation RequestID and the CheckDigit to retrieve the information needed for it's calculations. This prevents a hacker from passing false information.

The web service methods in the DNN module only allow records to be retrieved and updated for a short period of time. In most cases only a few seconds. The DNN module essentially "opens the door" by creating a record and sending the RequestID and the CheckDigit to the workflow. The workflow updates the record and then sets the CheckDigit to 0. This "closes the door" to the record.

Versioning

If you deploy a workflow and you change it while you still have workflows that are still running using the old version, you will get an error when those workflows try to re-load. To avoid this, you will need to use workflow versioning.

Comments and Discussions

Hi guys,I’m trying to install/set up IWebWF workflows.
I’m getting the error “Object reference not set to an instance of an object” when I’m on installation process of the Workflow on IIS 7 (windows server 2008 R2) on the step of “Install Database Scripts”
Install Database Scripts

Object reference not set to an instance of an object

Any idea from where is coming? The Sql 2008 is different machine.
Thanks in advance.
Crizz,

Sorry but this was written many years ago The only thing I could think of is you can try to run the script manually (02.00.00.SqlDataProvider) in SQL server to see what operation it is having a problem with.

On the DotNetNuke side you need only install the DotNetNuke module (like normal using the install wizard). You don't need to alter the web.config in te DotNetNuke website. The DotNetNuke site simply communicates with IWebWF through web services.

Hi Michel, I'm trying to use IWebWF with Tracking Service enabled, due to I need to monitor my workflows. I added the line " <add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.00000.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" /> " in the web.config (IWebWF site) but I get an error, the workflow stop working.
Do you know why I cann´t use Tracking Service with IWebWF?

Thanks for the follow-up. The problem I had was that when installing IWebWF it writes a sql connection string. The SQL connection for Tracking Services gets erased. I put in a web.config setting to tell the Tracking Services to get it's sql connection from the main sql connection string and it "ignore it".

Now, If you put the setting in manually then I guess it works. Perhaps you can post a sample of the web.config settings for others?

I'm including a part of my web.config file that works with Tracking service. I saw in a book that is necessary to load this class: SharedConnectionWorkflowCommitWorkBatchService, to get Persistent and Tracking services running together.

Regards, José
(Sorry, I'm trying to include a part of my web.config file, but the editor used by Code Project cut it )