This post will teach you how you can develop local services for the workflow and call them using CallExternalMethodActivity.
Sample source code included
INTRODUCTION
Most of the modern applications that are getting developed around the world ,uses workflow somewhere.Workflow is the set of activities which gets executed in a predefined flow or it can also be dependent to some external events occuring outside the workflow. You can incorporate the workflow into any business process like
- New Order Entering
- Approval Management
- Document Management
The scope of workflow is endless. So that was a very broad definition of the workflow, I won't dive into much details as I assume that the readers of this post has already have some hands on workflow programming. If not then I request them to revisit this post after getting their hands dirty on some workflow coding. You can get started
here. The idea of this post is to introduce to the Workflow Local Services and how to call these services methods using CallExternalMethodActivity
Workflow Local Services
These services are add-ons to your workflow , they are consumed by the workflow runtime during the execution of the workflow. As a workflow author you are in full command when to call any methods of these services. As these services are implemented centrically , they can be used by multiple workflow instances. The methods on the local services are called in a synchronous manner, so as a author or developer of the workflow you must ensure that the method execution does not take a long time. To implement the workflow local services you must follow the following sequence.
- Create a interface in any programming language of your choice which acts like a contract and has all the methods and events defined which will be implemented by the service class. This interface must be decorated with ExternalDataExchange attribute.
- Write a C# class or any other programming language that you prefer, that implements the above contract
- Add the instance of this service class to the workflow runtime.
There are more than one way by which you can call the methods by creating the instance of the service class
- By overrding the virtual method of the base activity class, method name is "OnActivityExecutionContextLoad"
- Loading the service class instance from App.config, This is the best way in the scenarios where you can change the implementations of method without actual rebuilding your workflow as everything is parameterized in the configuration file
- Using the CallExternalMethodActivity
I shall be talking about the last method, why I chose this method because it requires no code for instantiating the service class , you only need to set the few properties of this activity and you are done. the less Code we write , the less Errors we get :).
To demonstrate the usage of Local Services with CallExternalMethodActivity , I have develop a calculator workflow example. The next section describes it in detail
Local Services in Action
The calculator workflow will be a sequential workflow which will accepts three arguments from the host application . These arguments will be two numbers and third operator sign (+,-.*,/). it will return the Calculator class object as the output parameter of CallExternalMethodActivity. So first things first let us get started with code of the local services implementation. We need to first define the Interface or the service contract.Here is the code of the same.
namespace WorkFlowLocalSvcsDemo
{
///
/// The Calculator contract interface it should be decorated with ExternalDataExchange for workflow to recognize
///
[ExternalDataExchange]
public interface ICalculator
{
Calculator Add(double Number1, double Number2);
Calculator Substract(double Number1, double Number2);
Calculator Multiply(double Number1, double Number2);
Calculator Divide(double Number1, double Number2);
}
}
The calculator service contract or interface has four functions defined which returns the Calculator class object.Also note that it is decorated with ExternalDataExchange attribute as I had initially mentioned. Now let us examine the Calculator class which will be the output of Workflow and will be returned to the host application.
namespace WorkFlowLocalSvcsDemo
{
///
/// The output class of the workflow, it should be mark as Serializable
///
[Serializable]
public class Calculator
{
public double Number1 { get; set; }
public double Number2 { get; set; }
public double Result { get; set; }
public string Operator { get; set; }
}
}
The Calculator class code is self explanatory , just simple four properties.It is important to mark this class with Serializable attribute as it would be flowing from Workflow to host application. Now let us dig into the code of CalculatorService class which will implement the Calculator contract.
namespace WorkFlowLocalSvcsDemo
{
///
/// This class will implement the ICalculator Contract
///
public class CalculatorService :ICalculator
{
#region ICalculator Members
Calculator calc = new Calculator() ;
Calculator ICalculator.Add(double Number1, double Number2)
{
calc.Number1 = Number1;
calc.Number2 = Number2;
calc.Operator = "+";
calc.Result = Number1 + Number2;
return calc;
}
Calculator ICalculator.Substract(double Number1, double Number2)
{
calc.Number1 = Number1;
calc.Number2 = Number2;
calc.Operator = "-";
calc.Result = Number1 - Number2;
return calc;
}
Calculator ICalculator.Multiply(double Number1, double Number2)
{
calc.Number1 = Number1;
calc.Number2 = Number2;
calc.Operator = "*";
calc.Result = Number1 * Number2;
return calc;
}
Calculator ICalculator.Divide(double Number1, double Number2)
{
calc.Number1 = Number1;
calc.Number2 = Number2;
calc.Operator = "/";
calc.Result = Number1 / Number2;
return calc;
}
#endregion
}
}
The Calcualtor service class implements the ICalcualtor interface and returns Calculator class object.
Workflow
As shown in the figure , the calculator is a sequential workflow with multi branches of IfElseActivity. All the operations of calculator (Addition,Substraction,Multiplication ,Divison andInvalidOperator ) are implemented as the branches of the IfElseActivity. Within each operator branch except for the InvalidOperator branch , CallExternalMethodActivity is the child of the branch activity. The CodeActivity is the child of InvalidOperator branch activity. As discussed above , the CallExternalMethodActivity dosen't require any code just setting few properties.So let us check out what needs to be configure in Additionmethod , which is CallExternalMethodActivity.
As shown in the figure the most important property of this activity is InterfaceType , which is set to ICalculator Interface. Clicking on the eclipse button on this property will list all the interfaces. If you don't find , make sure that your interface is decorated with ExternalDataExchange attribute. The second property is the MethodName that you need to invoke. In this case as this the AdditionMethod , I have selected the Add method. The Method input and output parameters (ReturnValue) are provided by dependent properties of the workflow. One more interesting property is MethodInvoking, you can use this property to pre execute some code before the execution of the actual method by CallExternalMethodActivity. This is perfect place to initialize some code which may be required for the actual method execution.In this case there was no such need hence it has been left blank.
Set all the properties in the similiar manner for all the other operations for Calculator to complete the workflow.
The host application is the Windows Forms. It has a simple user interface. Two Text boxes , which accepts the two numbers and a Combo box which accepts the operator sign. Then there is a button which starts the workflow. The output of the workflow is displayed in the form of messagebox in the WorkflowCompleted event.
CLOSURE
It is worth the efforts spent on learning WF. I develop software and I gues you too are doing the same otherwise you would not reading this post. Today's clients are very demanding and they want to use this technology. I invested my efforts and time to learn this technology and it yeilding fruits to me now.I am applying it in my software solutions today.
Download code from
here (Rename the file extension from .doc to .rar)