wcf advanced activity development
TRANSCRIPT
-
8/12/2019 Wcf Advanced Activity Development
1/30
Session Code: CV.27
Integrating WCF andWorkflow, Advanced activity
development
Marcel de VriesMicrosoft MVP Team System
http://blogs.infosupport.co m/marcelvmarce
mailto:[email protected]://blogs.infosupport.com/marcelvmailto:[email protected]:[email protected]:[email protected]://blogs.infosupport.com/marcelv -
8/12/2019 Wcf Advanced Activity Development
2/30
Agenda
Integrating WCF in workflow Building activities basics Design time behavior
Type Converters Activity Designer Runtime behavior
Activity Code Generator Additional features
Attached Dependency properties Activity Validator
Summary
-
8/12/2019 Wcf Advanced Activity Development
3/30
Integrating WCF in workflow
WCF requires a class that implements a servicecontract and that is hosted in a service host
[ServiceContract(Namespace= "http://www.beyonddotnet.com/WCFTestInterface" )]public interface WCFTEstInterface{
[OperationContract ]string SayHello();[OperationContract(IsOneWay= true, Action= "DoNothing2") ]void DoNothing();
}
public class WCFTEstInterfaceImpl : WCFTEstInterface{
public string SayHello(){}public void DoNothing(){}
}
-
8/12/2019 Wcf Advanced Activity Development
4/30
Workflows are classes derived from activityand are hosted in a WorkflowRuntime
How can we combine the two? Create activities that can hold the service
operation definitions Generate a class that implements the interfaces
and applies the correct attributes
Create an implementation that can bootstrap theload/creation of a workflow when a WCF callcomes in
Integrating WCF in workflow
-
8/12/2019 Wcf Advanced Activity Development
5/30
Workflow Host e.g IIS
Integrating WCF in workflowGenerated codehandlingthe incoming call
Load/Create WF
Process WF
Return result
Client
-
8/12/2019 Wcf Advanced Activity Development
6/30
Activity Component ModelEach activity has an associated set of componentsComponents are associated through attributes on the Activity DefinitionIf not specified, parents attributes are applied
Required
Optional(defaults provided)
[Designer(typeof(MyDesigner))]
[ActivityCodeGenerator(typeof(MyCodeGen))]
[ActivityValidator(typeof(MyValidator))]
public class MyActivity: Activity {...}
Activity
CodeGenerator
Designer
Validator
Serializer Services
Workflow Runtime
-
8/12/2019 Wcf Advanced Activity Development
7/30
Building the activities Design time behavior
Pick interface using WF type picker dialog Create a dropdown containing methods available on Interface Add parameter that can be bound based on selected method in
interface
Generate WCF code that handles incoming call Validate if activities are configured correctly
Runtime behavior Register an event queue to wait on until notified by generated
code to start processing
At continuation bind parameters based on binding expressions Output activity returns results
-
8/12/2019 Wcf Advanced Activity Development
8/30
Implementing Design timebehavior
-
8/12/2019 Wcf Advanced Activity Development
9/30
Design time behavior Interface Property
Implementing the Interface property Dependency property of type Type Attached a TypeBrowserEditor using attributes
Need to implement ITypeFilter to show only interfaces we are
interested in
public bool CanFilterType( Type type , bool throwOnError){
// Display only interfacesreturn (type.IsInterface);
}[Browsable( false )]public string FilterDescription{
get { return "Choose an interface you want to expose as a ServiceContract" ; }}
-
8/12/2019 Wcf Advanced Activity Development
10/30
Design time behavior Method Property
Method property needs a custom value provider,since it must show all methods available in theselected interface Done by adding attribute to property providing custom
TypeProvider When a method is selected in the grid you need
to trigger that the parameters are exposed to theproperty grid as bindable properties Triggering is done by specifying attribute to the
Method attribute [RefreshProperties(RefreshProperties.All)]
And is handled in the designer OnActivityChanged
-
8/12/2019 Wcf Advanced Activity Development
11/30
Design time behavior Parameters property
Parameters property needs to be a dynamiclist of bindable parameters depending on theavailable arguments of the selected Methodin the interface This is done by creating the Parameters property
of type WorkflowParameterBindingCollectionand implementing designer behavior
Designer takes care of adding bindable propertiesto this collection in the PreFilterPropertiesmethod
-
8/12/2019 Wcf Advanced Activity Development
12/30
Design time behavior
Implementing the designer PreFilterProperties must use reflection to get
all parameters for the selected method Adds a new PropertyDescriptor for each
parameter Eacht property is Bindable in the property grid
Each property has the BindUITypeEditorattached
-
8/12/2019 Wcf Advanced Activity Development
13/30
-
8/12/2019 Wcf Advanced Activity Development
14/30
DEMO:Creating the design timebehavior
Implementing Design time behavior forWCFActivities Type Property Method Property Parameters property
-
8/12/2019 Wcf Advanced Activity Development
15/30
Implementing Runtime behavior Runtime behavior must do the following
For each incoming message load or create theappropriate workflow
Yield the thread to the workflow so it can execute until
it becomes idle in the WCF Input activity Register a synchronization object when output isgenerated by the workflow
There is an associated output activity Yield the thread again to execute the workflow
between the input and output activity Binds the message data to parameters set in the designer Communicate back the results of the call when
synchronization object is signaled
-
8/12/2019 Wcf Advanced Activity Development
16/30
Workflow Host e.g IIS
Generated codehandlingthe incoming call
Load/Create WF
Queue MessageData
Return result
Yield Thread
Register andwait on queue
Register WaitObject
Yield Thread
Dequeue &Bind params
Wait for WaitObject
-
8/12/2019 Wcf Advanced Activity Development
17/30
Implementing Runtime behavior WCFInput Must register a queue to receive the data
Done using a base class that handles queue management. Only Implement ProcessQueueItem
Generated code will pass message data for
processing in the queue
protected override bool ProcessQueueItem( ActivityExecutionContext context,object item)
{
object [] inputParameters = (object [])item;ProcessParameters(inputParameters);return true ;
}
-
8/12/2019 Wcf Advanced Activity Development
18/30
Implementing Runtime behavior
ProcessParameters binds the providedmessage data to the workflow properties
private void ProcessParameters( object [] inputParameters)
{MethodInfo methodInfo = InterfaceType.GetMethod(MethodName);int parameterIndex = 0;foreach (ParameterInfo paramInfo in methodInfo.GetParameters()){
if (Parameters.Contains(paramInfo.Name)){
WorkflowParameterBinding parameterBinding = Parameters[paramInfo.Name];parameterBinding.Value = inputParameters[parameterIndex++];
}}
}
Activity metadata
WCF message data
-
8/12/2019 Wcf Advanced Activity Development
19/30
Demo
Show generic WCF call handling Show Input activity implementation
-
8/12/2019 Wcf Advanced Activity Development
20/30
Implementing Runtime behavior
Most of the WCF handling can beprogrammed in a base class that handleseach call Only parameter binding is done in the input
activity itself, rest is WCF plumbing Some code needs to be generated to expose
the service contract This is done using an ActivityCodeGenerator
Generate a class that implements the selected methodsignatures in the input activities Add WCF attributes to those methods so they can be
exposed to WCF
-
8/12/2019 Wcf Advanced Activity Development
21/30
Implementing runtime behavior
Activity Code Generator Invoked during the compilation cycle of a
workflow project
Use CodeDom to add you custom code Use reflector to see what you generated WF Program compilation steps:
1. XAML deserialization & code generation
2. Activity Validation3. Activity code Generation4. Code Compilation
-
8/12/2019 Wcf Advanced Activity Development
22/30
Implementing runtime behavior
What needs to be generated? The call to HandleWCFCall for each input
activity in the workflow[ServiceContract (Name ="TestWorkflow1" )]public class TestWorkflow1_wcfContractImpl : WCFCallHander { // Methods
[OperationContract ( Action ="ActivatingCall" )]private string ActivatingCall ()
{object [] p r m t rs = new object [0];return (string ) base .HandleWCFCall (true , false , typeof (TestWorkflow1 ),
"WCFTEstInterface" , "ActivatingCall" , "System.String" , parameters);}
}
http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.ServiceContractAttribute/.ctor()http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.ServiceContractAttribute/property:Name:Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1_wcfContractImplhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://WCFActivities:1.0.0.0:e316e0e29ca8f225/WCFActivities.WCFCallHanderhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.OperationContractAttribute/.ctor()http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.OperationContractAttribute/property:Action:Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1_wcfContractImpl/ActivatingCall():Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://WCFActivities:1.0.0.0:e316e0e29ca8f225/WCFActivities.WCFCallHander/HandleWCFCall(Boolean,Boolean,System.Type,String,String,String,Object[]):Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://WCFActivities:1.0.0.0:e316e0e29ca8f225/WCFActivities.WCFCallHander/HandleWCFCall(Boolean,Boolean,System.Type,String,String,String,Object[]):Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Objecthttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1_wcfContractImpl/ActivatingCall():Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.OperationContractAttribute/property:Action:Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.OperationContractAttribute/.ctor()http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://WCFActivities:1.0.0.0:e316e0e29ca8f225/WCFActivities.WCFCallHanderhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://TestLibrary:1.0.0.0/TestLibrary.TestWorkflow1_wcfContractImplhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.ServiceContractAttribute/property:Name:Stringhttp://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.ServiceModel:3.0.0.0:b77a5c561934e089/System.ServiceModel.ServiceContractAttribute/.ctor() -
8/12/2019 Wcf Advanced Activity Development
23/30
Activity code generation
Done by building an ActivityCodeGenerator
You receive a codedom representation ofyour workflow implementation Search for a definition of a class called
_wcfimpl If not found create one using code dom and adding
it to the namenspace Add a new method signature using code dom
to the generated class
-
8/12/2019 Wcf Advanced Activity Development
24/30
Demo
Show generation using ActivityCodeGenerator
-
8/12/2019 Wcf Advanced Activity Development
25/30
Additional Designtime features
Attached Properties WCF has some settings you would like to set
once on each workflow
Namespace, ServiceName, GeneratedClassName You can use attached properties for this
purpose Requires designer to add IExtenderProvider during
initialization for each attached property Requires a ExtenderProvider for each property Value can be retrieved using the GetValue()
method on the activity you attached the property to
-
8/12/2019 Wcf Advanced Activity Development
26/30
Additional Designtime Features Designer Validation
A validator can check if the properties that got assigned to youractivity are correct
Requires you to implement a class derived from ActivityValidator You implement the Validate method
You apply the validator to the activity using the ActivityValidator attribute At validation you have the full instantiated activity tree at your
disposal Can do complex validation cross the tree
Check if an input activity has an associated output activity when retrun
value != void Your validator is activated in compilation cycle! Therefore validation is normally used for metadata validation
26
-
8/12/2019 Wcf Advanced Activity Development
27/30
Demo
Attached properties Activity Validator
-
8/12/2019 Wcf Advanced Activity Development
28/30
Codeplex version
Codeplex version contains additional feature Correlation based on attributes Leaves the client from knowing and returning the
message headers At the Data/Operation contract an attribute isadded that will do the correlation
Done using a WCF behavior
Required few changes in code gen, since thereyou need to add attributes to the serviceoperations
-
8/12/2019 Wcf Advanced Activity Development
29/30
Q&A
More information Activities shown today
www.codeplex.com/WCFActivities
http://blogs.infosupport.com/marcelv MSDN forums Workflow SDK
http://www.codeplex.com/WCFActivitieshttp://blogs.infosupport.com/marcelvhttp://blogs.infosupport.com/marcelvhttp://blogs.infosupport.com/marcelvhttp://www.codeplex.com/WCFActivities -
8/12/2019 Wcf Advanced Activity Development
30/30
Evaluation form
Vul je evaluatieformulier in en maak kansop een van de prachtige prijzen!!
Fill out your evaluation form and win one ofthe great prizes!!
Session Code: CV.27