Click here to Skip to main content
Click here to Skip to main content

Best Practice Architecture with Workflow Foundation (WF)

, 10 Jun 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
This article demonstrates how WF can be consumed as a business layer.

Download BestPracticeArchitectureWWF.zip

When to go for Workflow Foundation

  1. For long-running business process.
  2. Frequently Changing Business Logic or Rules.
  3. When need visual model/execution of the process.

Introduction

In this post I am going to demonstrate how you can architect enterprise application using WWF. You can find lots of learning stuff for Window Workflow Foundation but difficult to find is how to adjust and where to adjust it in architecture.

Architecture diagram

Have a look to architecture diagram, in this UI is interacting with business layer via WCF service. WF is used as part of business layer. You can also put WF service in front of WCF but then you will not know the entities of WCF in UI. As per best practice nothing should be directly exposed to UI layer, so it is not good idea to put WF as library in UI Layer. Generally people use WF for business rules, State persistence, Transaction or for some kind of time taking process so I would suggest to put it in Business layer. In my attached sample, for simplicity I am not involving entity framework and DB part. But off course you can add Entity framework with POCO classes. There are lot of articles are available on this so I don’t think you should face any kind of difficulty in implementation. In future I shall also come up with some sample on this.

Background

To implement this application, I am going to use the following technologies:

To implement this project person should have basic knowledge of .net technologies like C#, ASP.NET, WCF, WF.

Sample Proof of Concept

ADD blank solution name as ‘BestPracticeArchitectureWWF’.

Business Layer (C# Library)

Add C# library project to existing solution. Add following code for method in ‘Class1.cs’. This method will take one parameter and return it with some modification. This is the place where you can call to database by using entity framework.

public static string BusinessMethod(string parm1) 
{
    return parm1 + " Returned by Business layer.";
}

Business Layer (WF Activity)

Add WF Activity library project to existing solution.

In Activity1.xaml add flowchart.

Drag Sequence to indicated place.

Select Sequence and declare 2 arguments in argument tab as shown in screen shot. One is to accept argument and another to return.

Now drag two more activities to Sequence as shown in above screen shot. One is Assign activity and another is Invoke Method from Primitive group panel. In Assign activity will assign Argument2 variable to Argument1 + “Modified in WF”. Invoke method is used to call business C# library. Add reference to C# library. To call library method set Target Type as class. Method name simply type ‘BusinessMethod’. No need to fill TargetObject(In TargetType and TargetObject one need to be filled). One strange thing is even though you work in c# project in Activities expression it takes only vb code.

Finally XAML of this activity will look like this. No need to modify anything in XAML but some time you rename something it fails to change in XAML then we need to look into it.

<Activity mc:Ignorable="sap" x:Class="ActivityLibrary1.Activity1" 
  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" 
  xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation>" 
  xmlns:b="clr-namespace:BusinessClassLibrary1;assembly=BusinessClassLibrary1" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" 
  xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" 
  xmlns:s="clr-namespace:System;assembly=mscorlib" 
  xmlns:s1="clr-namespace:System;assembly=System" 
  xmlns:s2="clr-namespace:System;assembly=System.Xml" 
  xmlns:s3="clr-namespace:System;assembly=System.Core" 
  xmlns:s4="clr-namespace:System;assembly=System.ServiceModel" 
  xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" 
  xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" 
  xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation</a>" 
  xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" 
  xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" 
  xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" 
  xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" 
  xmlns:sd="clr-namespace:System.Data;assembly=System.Data" 
  xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" 
  xmlns:st="clr-namespace:System.Text;assembly=mscorlib" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<x:Members>
<x:Property Name="argument1" Type="InArgument(x:String)" />
<x:Property Name="argument2" Type="OutArgument(x:String)" />
</x:Members>
<sap:VirtualizedContainerService.HintSize>654,676</sap:VirtualizedContainerService.HintSize>
<mva:VisualBasic.Settings>Assembly references and imported namespaces 
             for internal implementation</mva:VisualBasic.Settings>
<Flowchart sad:XamlDebuggerXmlReader.FileName=
  "C:\ManojWork\Article\BestPracticeArchitectureWWF\BestPracticeArchitectureWWF\ActivityLibrary1\Activity1.xaml" 
  sap:VirtualizedContainerService.HintSize="614,636">
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">False</x:Boolean>
<av:Point x:Key="ShapeLocation">270,2.5</av:Point>
<av:Size x:Key="ShapeSize">60,75</av:Size>
<av:PointCollection x:Key="ConnectorLocation">300,77.5 300,127.5</av:PointCollection>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<Flowchart.StartNode>
<FlowStep x:Name="__ReferenceID0">
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<av:Point x:Key="ShapeLocation">200,127.5</av:Point>
<av:Size x:Key="ShapeSize">200,51</av:Size>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<Sequence sap:VirtualizedContainerService.HintSize="264,352">
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<Assign sap:VirtualizedContainerService.HintSize="242,58">
<Assign.To>
<OutArgument x:TypeArguments="x:String">[argument1]</OutArgument>
</Assign.To>
<Assign.Value>
<InArgument x:TypeArguments="x:String">[argument1 + "Modified in WF"]</InArgument>
</Assign.Value>
</Assign>
<InvokeMethod sap:VirtualizedContainerService.HintSize="242,130" 
          MethodName="BusinessMethod" TargetType="b:Class1">
<InvokeMethod.Result>
<OutArgument x:TypeArguments="x:String">[argument2]</OutArgument>
</InvokeMethod.Result>
<InArgument x:TypeArguments="x:String">[argument1]</InArgument>
</InvokeMethod>
</Sequence>
</FlowStep>
</Flowchart.StartNode>
<x:Reference>__ReferenceID0</x:Reference>
</Flowchart>
</Activity>

Build the WF Activity and add reference to WCF Service.

Service Layer (WCF)

Add WCF service. In Service1.svc.cs add following code to call activity. Don’t forget to update contract in IService1.cs.

public string GetData(string value)
{
    ActivityLibrary1.Activity1 ca = new ActivityLibrary1.Activity1();
    ca.argument1 = value.ToString();
    IDictionary<string, object> dr = new Dictionary<string, object>();
    dr.Add("argument1",value);
    var output = WorkflowInvoker.Invoke(ca,dr);
    string st = output["argument2"].ToString();
    return string.Format("You entered: {0}", st);
}

This method takes string variable from UI and process it in WF Activity and in C# business library. Build WCF service.

UI(ASP.NET)

Add Asp.net project to existing solution. In place of ASP.NET you can use Silverlight/WPF project too. If you want to see how WCF can be called in Silverlight project see my other Article.

Add service reference to this project. Now come to Default.aspx to add some controls as per following code.

<h2>
WF Calling Sample
<br />
<asp:Label ID="Label2" runat="server" Text="Enter Your Name: ">
</asp:Label><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</h2>

Add click event for button. In code behind we are going to call WCF service.

protected void Button1_Click(object sender, EventArgs e)
{
    Service1Client sr = new ServiceReference1.Service1Client();
    int i = 0;
    if (int.TryParse(TextBox1.Text, out i))
    {
        Label1.Text = sr.GetData(i);
    }
    else
        Label1.Text = "Please enter Number only.";
}

Set Web Application as startup project and Default.aspx as Startup page. Run the application. Enter name and click Button to get modified from WF activity and C# Business library. Hope this idea will help you in designing applications.

Summary

In this article you have learned how you can utilize WF activities in business layer. Hope this would be pretty simple example to elaborate architecture.

If this article helps you in designing/coding application don’t forget to hit voting option. Please comment your suggestions and improvements.

Happy coding!!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

ManojKumar19
Architect
United States United States
Manoj Kumar

Architect, Lead Software Engineer and Senior BI Developer | Microsoft Certified Technology Specialist(MCTS) | Exp in C#, ASP.Net, MVC, Razor View Engine and EF Code First, HTML5, CSS3, JQuery, Javascript, AngularJS, JSON, AJAX, KnockoutJS, Silverlight, WPF, WCF, WF, SSRS, SSAS, SSIS, ETL, SQL Server, Usability/User Experience etc.

He lives with his wife Supriya and daughter Tisya in Bay Area.
Follow on   LinkedIn

Comments and Discussions

 
Questionworkflow foundation architecture PinmemberRaja Chandrasekaran2-Aug-14 4:31 
QuestionWorkflowApplication as a host instead of WorkflowInvoker as a host Pinmemberwkalter29-Jan-13 0:36 
GeneralMy vote of 4 Pinmemberwkalter29-Jan-13 0:23 
GeneralMy vote of 2 PinmemberPrasyee31-Aug-12 2:54 
QuestionFormatting PinmvpMehdi Gholam10-Jun-12 0:17 
AnswerRe: Formatting PinmemberManojKumar1910-Jun-12 7:00 
SuggestionRe: Formatting PinmemberVitaly Tomilov10-Jun-12 8:19 
AnswerRe: Formatting PinmemberManojKumar1910-Jun-12 8:29 
GeneralRe: Formatting PinmemberAndreas Gieriet10-Jun-12 13:08 
SuggestionCouple things PinmemberTim Corey9-Jun-12 6:12 
GeneralRe: Couple things PinmemberManojKumar199-Jun-12 14:26 
AnswerRe: Couple things PinmemberTim Corey9-Jun-12 14:47 
GeneralRe: Couple things PinmemberManojKumar199-Jun-12 17:12 
AnswerRe: Couple things PinmemberTim Corey9-Jun-12 17:20 
GeneralRe: Couple things PinmemberManojKumar199-Jun-12 20:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150414.1 | Last Updated 11 Jun 2012
Article Copyright 2012 by ManojKumar19
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid