WF4 Persistence tester code + multiple approvals and rejections
(Also look at a much more detailed approval/rejection solution on MSDN)
The below solution simply uses a Flow Chart level boolean variable and a FlowDecision element to show one approval/rejection scenario.
The flow has one task activity and one approval.
If the 2nd is rejected, it goes back to the first one.
We can configure any number of such sequential related activities.
The test code is configured for persistence too so you can end your app anytime and restart any persisted workflows later.
Open the sln, change the connection string and hit ctrl+f5 to test.
Use the below SQL on your DB if you forget to note the GUIDs from the console output.
(Look at the previous post to see how to configure the persistence tables on your DB for WF4)
select * from [System.Activities.DurableInstancing].[InstancesTable]
********************
SubmitTaskName.cs
********************
********************
Workflow1.xaml
********************
********************
Program.cs
This code can be used to start, persist and restart any persisted workflow for a given bookmark name
********************
The below solution simply uses a Flow Chart level boolean variable and a FlowDecision element to show one approval/rejection scenario.
The flow has one task activity and one approval.
If the 2nd is rejected, it goes back to the first one.
We can configure any number of such sequential related activities.
The test code is configured for persistence too so you can end your app anytime and restart any persisted workflows later.
Open the sln, change the connection string and hit ctrl+f5 to test.
Use the below SQL on your DB if you forget to note the GUIDs from the console output.
(Look at the previous post to see how to configure the persistence tables on your DB for WF4)
select * from [System.Activities.DurableInstancing].[RunnableInstancesTable]
********************
SubmitTaskName.cs
********************
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Activities; namespace WorkflowConsoleApplication1 { public sealed class SubmitTaskName : NativeActivity { public InArgument<string> TaskName { get; set; } public OutArgument<bool> Approved { get; set; } protected override bool CanInduceIdle { get { return true; } } protected override void Execute(NativeActivityContext context) { Console.WriteLine("Created Bookmark on " + TaskName.Get(context)); context.CreateBookmark("SubmitTaskName_BookMark", new BookmarkCallback(OnBookmarkCallback)); } void OnBookmarkCallback(NativeActivityContext context, Bookmark bookmark, object val) { Approved.Set(context, (bool)val); Console.WriteLine(TaskName.Get(context) + " resuming bookmark on " + val.ToString()); } } }
********************
Workflow1.xaml
********************
<Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication1.Workflow1" sap:VirtualizedContainerService.HintSize="880,676" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:WorkflowConsoleApplication1" 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" 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.Threading;assembly=System.Core" xmlns:st1="clr-namespace:System.Threading;assembly=System" xmlns:st2="clr-namespace:System.Text;assembly=mscorlib" xmlns:st3="clr-namespace:System.Threading;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Flowchart sad:XamlDebuggerXmlReader.FileName="c:\users\user1\documents\visual studio 2010\Projects\WF4Extensions\WorkflowConsoleApplication1\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="840,636"> <Flowchart.Variables> <Variable x:TypeArguments="x:Boolean" Default="False" Name="Approved" /> Flowchart.Variables> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">Falsex:Boolean> <av:Point x:Key="ShapeLocation">270,2.5av:Point> <av:Size x:Key="ShapeSize">60,75av:Size> <av:PointCollection x:Key="ConnectorLocation">300,77.5 300,107.5 300,129av:PointCollection> <x:Double x:Key="Width">826.5x:Double> 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,129av:Point> <av:Size x:Key="ShapeSize">200,22av:Size> <av:PointCollection x:Key="ConnectorLocation">300,151 300,181 270,181 270,239av:PointCollection> scg3:Dictionary> sap:WorkflowViewStateService.ViewState> <local:SubmitTaskName Approved="{x:Null}" sap:VirtualizedContainerService.HintSize="200,22" TaskName="Task1" /> <FlowStep.Next> <FlowStep x:Name="__ReferenceID1"> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <av:Point x:Key="ShapeLocation">170,239av:Point> <av:Size x:Key="ShapeSize">200,22av:Size> <av:PointCollection x:Key="ConnectorLocation">270,261 270,291 305,291 305,322.5av:PointCollection> scg3:Dictionary> sap:WorkflowViewStateService.ViewState> <local:SubmitTaskName Approved="[Approved]" sap:VirtualizedContainerService.HintSize="200,22" TaskName="Task2" /> <FlowStep.Next> <FlowDecision x:Name="__ReferenceID2" Condition="[Approved = True]" sap:VirtualizedContainerService.HintSize="60,75"> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <av:Point x:Key="ShapeLocation">260,322.5av:Point> <av:Size x:Key="ShapeSize">60,75av:Size> <x:String x:Key="FalseLabel">Rejectedx:String> <x:String x:Key="TrueLabel">Approvedx:String> <av:PointCollection x:Key="FalseConnector">320,360 430,360 430,140 400,140av:PointCollection> <av:PointCollection x:Key="TrueConnector">260,360 154.5,360 154.5,490 184.5,490av:PointCollection> scg3:Dictionary> sap:WorkflowViewStateService.ViewState> <FlowDecision.True> <FlowStep x:Name="__ReferenceID3"> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <av:Point x:Key="ShapeLocation">184.5,459.5av:Point> <av:Size x:Key="ShapeSize">211,61av:Size> scg3:Dictionary> sap:WorkflowViewStateService.ViewState> <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="WF Completed" /> FlowStep> FlowDecision.True> <FlowDecision.False> <x:Reference>__ReferenceID0x:Reference> FlowDecision.False> FlowDecision> FlowStep.Next> FlowStep> FlowStep.Next> FlowStep> Flowchart.StartNode> <x:Reference>__ReferenceID0x:Reference> <x:Reference>__ReferenceID1x:Reference> <x:Reference>__ReferenceID2x:Reference> <x:Reference>__ReferenceID3x:Reference> Flowchart> Activity>
********************
Program.cs
********************
using System; using System.Linq; using System.Activities; using System.Activities.Statements; using System.Activities.DurableInstancing; using System.Runtime.DurableInstancing; using System.Threading; namespace WorkflowConsoleApplication1 { class Program { static AutoResetEvent InstanceUnloaded = new AutoResetEvent(false); static bool WfEnded = false; static WorkflowApplication initWorkflowApplication(InstanceStore Store) { WorkflowApplication App = new WorkflowApplication(new Workflow1()); App.PersistableIdle = (e) => { return PersistableIdleAction.Unload; }; App.Unloaded = (workflowApplicationEventArgs) => { Console.WriteLine("WorkflowApplication has Unloaded"); InstanceUnloaded.Set(); }; App.Completed = (workflowApplicationCompletedEventArgs) => { Console.WriteLine("WorkflowApplication has Completed in the {0} state.", workflowApplicationCompletedEventArgs.CompletionState); WfEnded = true; }; App.InstanceStore = Store; return App; } static void Main(string[] args) { InstanceStore Store = new SqlWorkflowInstanceStore(@"ENTER A WORKING CONNECTION STRING HERE"); InstanceHandle Handle = Store.CreateInstanceHandle(); InstanceView View = Store.Execute(Handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); Handle.Free(); Store.DefaultInstanceOwner = View.InstanceOwner; WorkflowApplication App = initWorkflowApplication(Store); Guid Id; Console.WriteLine("Enter GUID (or 'New'): "); string StringId = Console.ReadLine(); while (!Guid.TryParse(StringId, out Id)) { if (StringId == "New") break; Console.WriteLine("Enter GUID (or 'New'): "); StringId = Console.ReadLine(); } if (StringId == "New") { // New workflow App.Run(); InstanceUnloaded.WaitOne(); Id = App.Id; Console.WriteLine("GUID: {0}", Id); } Console.WriteLine("Enter y or n (or nothing to exit): "); string Status = Console.ReadLine(); while (!string.IsNullOrEmpty(Status)) { if (WfEnded) return; App = initWorkflowApplication(Store); App.Load(Id); App.ResumeBookmark("SubmitTaskName_BookMark", Status=="y"); InstanceUnloaded.WaitOne(); Console.WriteLine("Enter y or n (or nothing to exit): "); Status = Console.ReadLine(); } } } }
Comments
Post a Comment