1. 创建一个空白的项目,在其中创建Host – Windows Console Application,Client – Windows forms
Application和DataExchangeWorkflows – Activity Library这三个项目。创建后应该结构类似于下图:
2. 将工作流DataExchangeActivity.xaml设计为如下样式:
有几点需要注意:
1) 第一个Receive
Activity的CanCreateInstance必须为True,否则客户端调用此Receive无法生成实例(一个工作流只需要第一个的CanCreateInstance为True)
2) TicketId变量保存生成的工作流示例编号,在后面更新时客户端将根据TicketId来更新状态。
3)
_handler的类型是CorrelationHandle。_handler的作用是根据客户端发送过来的TicketId,搜索相匹配的工作流的TicketId。
4) 刚才说过,_handler是用于搜索相匹配的工作流的TicketId,在第二个Receive
Activity「CheckCredit」的ServiceContractName不能为空白,否则在设置CorrelationOn的属性的时候,选择Id属性会报”ServiceContractName
and OperationName properties of activity ‘Receive’ must be set in order to
generate XPath”这个错。
5) 需要设置三个Arguments,用于传递Receive Activity「CheckCredit」的参数。
6) 最后生成的XML如下:
1 <Activity mc:Ignorable="sap sap2010 sads" x:Class="DataExchangeWorkflows.DataExchangeActivity"
2
3 xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
4
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6
7 xmlns:mca="clr-namespace:Microsoft.CSharp.Activities;assembly=System.Activities"
8
9 xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel"
10
11 xmlns:sads="http://schemas.microsoft.com/netfx/2010/xaml/activities/debugger"
12
13 xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
14
15 xmlns:sap2010="http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation"
16
17 xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
18
19 xmlns:sco="clr-namespace:System.Collections.ObjectModel;assembly=mscorlib"
20
21 xmlns:ssx="clr-namespace:System.ServiceModel.XamlIntegration;assembly=System.ServiceModel"
22
23 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
24
25 <x:Members>
26
27 <x:Property Name="action" Type="InArgument(x:String)" />
28
29 <x:Property Name="reviewId" Type="InArgument(x:Int32)" />
30
31 <x:Property Name="comment" Type="InArgument(x:String)" />
32
33 </x:Members>
34
35 <sap2010:ExpressionActivityEditor.ExpressionActivityEditor>C#</sap2010:ExpressionActivityEditor.ExpressionActivityEditor>
36
37 <sap2010:WorkflowViewState.IdRef>DataExchangeWorkflows.DataExchangeActivity_1</sap2010:WorkflowViewState.IdRef>
38
39 <TextExpression.NamespacesForImplementation>
40
41 <sco:Collection x:TypeArguments="x:String">
42
43 <x:String>System</x:String>
44
45 <x:String>System.Collections.Generic</x:String>
46
47 <x:String>System.Data</x:String>
48
49 <x:String>System.Linq</x:String>
50
51 <x:String>System.Text</x:String>
52
53 <x:String>System.ServiceModel.Activities</x:String>
54
55 </sco:Collection>
56
57 </TextExpression.NamespacesForImplementation>
58
59 <TextExpression.ReferencesForImplementation>
60
61 <sco:Collection x:TypeArguments="AssemblyReference">
62
63 <AssemblyReference>Microsoft.CSharp</AssemblyReference>
64
65 <AssemblyReference>System</AssemblyReference>
66
67 <AssemblyReference>System.Activities</AssemblyReference>
68
69 <AssemblyReference>System.Core</AssemblyReference>
70
71 <AssemblyReference>System.Data</AssemblyReference>
72
73 <AssemblyReference>System.Runtime.Serialization</AssemblyReference>
74
75 <AssemblyReference>System.ServiceModel</AssemblyReference>
76
77 <AssemblyReference>System.ServiceModel.Activities</AssemblyReference>
78
79 <AssemblyReference>System.Xaml</AssemblyReference>
80
81 <AssemblyReference>System.Xml</AssemblyReference>
82
83 <AssemblyReference>System.Xml.Linq</AssemblyReference>
84
85 <AssemblyReference>mscorlib</AssemblyReference>
86
87 <AssemblyReference>DataExchangeWorkflows</AssemblyReference>
88
89 </sco:Collection>
90
91 </TextExpression.ReferencesForImplementation>
92
93 <Sequence sap2010:WorkflowViewState.IdRef="Sequence_1">
94
95 <Sequence.Variables>
96
97 <Variable x:TypeArguments="p:CorrelationHandle" Name="_handler" />
98
99 <Variable x:TypeArguments="x:Int32" Default="-1" Name="TicketId" />
100
101 </Sequence.Variables>
102
103 <Pick sap2010:WorkflowViewState.IdRef="Pick_1">
104
105 <PickBranch DisplayName="Branch1" sap2010:WorkflowViewState.IdRef="PickBranch_1">
106
107 <PickBranch.Trigger>
108
109 <p:Receive CanCreateInstance="True" sap2010:WorkflowViewState.IdRef="Receive_2" OperationName="ReceiveOrder" />
110
111 </PickBranch.Trigger>
112
113 <Sequence sap2010:WorkflowViewState.IdRef="Sequence_2">
114
115 <Assign sap2010:WorkflowViewState.IdRef="Assign_1">
116
117 <Assign.To>
118
119 <OutArgument x:TypeArguments="x:Int32">
120
121 <mca:CSharpReference x:TypeArguments="x:Int32">TicketId</mca:CSharpReference>
122
123 </OutArgument>
124
125 </Assign.To>
126
127 <Assign.Value>
128
129 <InArgument x:TypeArguments="x:Int32">
130
131 <mca:CSharpValue x:TypeArguments="x:Int32">new Random().Next()</mca:CSharpValue>
132
133 </InArgument>
134
135 </Assign.Value>
136
137 </Assign>
138
139 <p:InitializeCorrelation sap2010:WorkflowViewState.IdRef="InitializeCorrelation_1">
140
141 <p:InitializeCorrelation.Correlation>
142
143 <InArgument x:TypeArguments="p:CorrelationHandle">
144
145 <mca:CSharpValue x:TypeArguments="p:CorrelationHandle">_handler</mca:CSharpValue>
146
147 </InArgument>
148
149 </p:InitializeCorrelation.Correlation>
150
151 <InArgument x:TypeArguments="x:String" x:Key="Id">
152
153 <mca:CSharpValue x:TypeArguments="x:String">TicketId.ToString()</mca:CSharpValue>
154
155 </InArgument>
156
157 </p:InitializeCorrelation>
158
159 <WriteLine sap2010:WorkflowViewState.IdRef="WriteLine_1">
160
161 <InArgument x:TypeArguments="x:String">
162
163 <mca:CSharpValue x:TypeArguments="x:String">"流程被创建,编号为:" + TicketId.ToString()</mca:CSharpValue>
164
165 </InArgument>
166
167 </WriteLine>
168
169 </Sequence>
170
171 </PickBranch>
172
173 </Pick>
174
175 <Pick sap2010:WorkflowViewState.IdRef="Pick_2">
176
177 <PickBranch DisplayName="Branch1" sap2010:WorkflowViewState.IdRef="PickBranch_2">
178
179 <PickBranch.Trigger>
180
181 <p:Receive sap2010:WorkflowViewState.IdRef="Receive_3" OperationName="CheckCredit" ServiceContractName="ICheckCredit">
182
183 <p:Receive.CorrelatesOn>
184
185 <p:XPathMessageQuery x:Key="Id">
186
187 <p:XPathMessageQuery.Namespaces>
188
189 <ssx:XPathMessageContextMarkup>
190
191 <x:String x:Key="xgSc">http://tempuri.org/</x:String>
192
193 </ssx:XPathMessageContextMarkup>
194
195 </p:XPathMessageQuery.Namespaces>sm:body()/xgSc:CheckCredit/xgSc:id</p:XPathMessageQuery>
196
197 </p:Receive.CorrelatesOn>
198
199 <p:Receive.CorrelatesWith>
200
201 <InArgument x:TypeArguments="p:CorrelationHandle">
202
203 <mca:CSharpValue x:TypeArguments="p:CorrelationHandle">_handler</mca:CSharpValue>
204
205 </InArgument>
206
207 </p:Receive.CorrelatesWith>
208
209 <p:ReceiveParametersContent>
210
211 <OutArgument x:TypeArguments="x:String" x:Key="action">
212
213 <mca:CSharpReference x:TypeArguments="x:String">action</mca:CSharpReference>
214
215 </OutArgument>
216
217 <OutArgument x:TypeArguments="x:String" x:Key="comment">
218
219 <mca:CSharpReference x:TypeArguments="x:String">comment</mca:CSharpReference>
220
221 </OutArgument>
222
223 <OutArgument x:TypeArguments="x:Int32" x:Key="id">
224
225 <mca:CSharpReference x:TypeArguments="x:Int32">reviewId</mca:CSharpReference>
226
227 </OutArgument>
228
229 </p:ReceiveParametersContent>
230
231 </p:Receive>
232
233 </PickBranch.Trigger>
234
235 <If sap2010:WorkflowViewState.IdRef="If_1">
236
237 <If.Condition>
238
239 <InArgument x:TypeArguments="x:Boolean">
240
241 <mca:CSharpValue x:TypeArguments="x:Boolean">action.ToUpper() == "APPROVAL"</mca:CSharpValue>
242
243 </InArgument>
244
245 </If.Condition>
246
247 <If.Then>
248
249 <WriteLine sap2010:WorkflowViewState.IdRef="WriteLine_2">
250
251 <InArgument x:TypeArguments="x:String">
252
253 <mca:CSharpValue x:TypeArguments="x:String">"流程" + TicketId.ToString() + "通过审核"</mca:CSharpValue>
254
255 </InArgument>
256
257 </WriteLine>
258
259 </If.Then>
260
261 <If.Else>
262
263 <WriteLine sap2010:WorkflowViewState.IdRef="WriteLine_3">
264
265 <InArgument x:TypeArguments="x:String">
266
267 <mca:CSharpValue x:TypeArguments="x:String">"流程" + TicketId.ToString() + "被驳回"</mca:CSharpValue>
268
269 </InArgument>
270
271 </WriteLine>
272
273 </If.Else>
274
275 </If>
276
277 </PickBranch>
278
279 </Pick>
280
281 <sads:DebugSymbol.Symbol>d2BFOlxLZXZpbl9Eb2N1bWVudFx3b3Jrc3BhY2VcRGF0YUV4Y2hhbmdlU29sdXRpb25cRGF0YUV4Y2hhbmdlV29ya2Zsb3dzXERhdGFFeGNoYW5nZUFjdGl2aXR5LnhhbWwbLwOOAQ4CAQEyMzI3AgECNAVXDAIBM1gFjAEMAgEDNQdWFAIBNFkHiwEUAgEENws3egIBVzkJVRQCATVbC3QXAgEadgmKAQ4CAQU6C0UUAgFKRgtPJQIBPVALVBcCATZmEWZiAgEtaxFrXQIBJ3ERcV4CASFuEW5eAgEbeQ95bAIBBn0NgQEZAgEThAENiAEZAgEMQhFCYQIBUT0RPV4CAUtND01gAgFESRFJYgIBPlIPUm8CATd/EX9yAgEUhgERhgFxAgEN</sads:DebugSymbol.Symbol>
282
283 </Sequence>
284
285 <sap2010:WorkflowViewState.ViewStateManager>
286
287 <sap2010:ViewStateManager>
288
289 <sap2010:ViewStateData Id="Receive_2" sap:VirtualizedContainerService.HintSize="255,90" />
290
291 <sap2010:ViewStateData Id="Assign_1" sap:VirtualizedContainerService.HintSize="242,62" />
292
293 <sap2010:ViewStateData Id="InitializeCorrelation_1" sap:VirtualizedContainerService.HintSize="242,97" />
294
295 <sap2010:ViewStateData Id="WriteLine_1" sap:VirtualizedContainerService.HintSize="242,62" />
296
297 <sap2010:ViewStateData Id="Sequence_2" sap:VirtualizedContainerService.HintSize="264,425">
298
299 <sap:WorkflowViewStateService.ViewState>
300
301 <scg:Dictionary x:TypeArguments="x:String, x:Object">
302
303 <x:Boolean x:Key="IsExpanded">True</x:Boolean>
304
305 </scg:Dictionary>
306
307 </sap:WorkflowViewStateService.ViewState>
308
309 </sap2010:ViewStateData>
310
311 <sap2010:ViewStateData Id="PickBranch_1" sap:VirtualizedContainerService.HintSize="294,713" />
312
313 <sap2010:ViewStateData Id="Pick_1" sap:VirtualizedContainerService.HintSize="608,759" />
314
315 <sap2010:ViewStateData Id="Receive_3" sap:VirtualizedContainerService.HintSize="255,90" />
316
317 <sap2010:ViewStateData Id="WriteLine_2" sap:VirtualizedContainerService.HintSize="211,62" />
318
319 <sap2010:ViewStateData Id="WriteLine_3" sap:VirtualizedContainerService.HintSize="211,62" />
320
321 <sap2010:ViewStateData Id="If_1" sap:VirtualizedContainerService.HintSize="464,212" />
322
323 <sap2010:ViewStateData Id="PickBranch_2" sap:VirtualizedContainerService.HintSize="494,500" />
324
325 <sap2010:ViewStateData Id="Pick_2" sap:VirtualizedContainerService.HintSize="608,546" />
326
327 <sap2010:ViewStateData Id="Sequence_1" sap:VirtualizedContainerService.HintSize="630,1469">
328
329 <sap:WorkflowViewStateService.ViewState>
330
331 <scg:Dictionary x:TypeArguments="x:String, x:Object">
332
333 <x:Boolean x:Key="IsExpanded">True</x:Boolean>
334
335 </scg:Dictionary>
336
337 </sap:WorkflowViewStateService.ViewState>
338
339 </sap2010:ViewStateData>
340
341 <sap2010:ViewStateData Id="DataExchangeWorkflows.DataExchangeActivity_1" sap:VirtualizedContainerService.HintSize="670,1549" />
342
343 </sap2010:ViewStateManager>
344
345 </sap2010:WorkflowViewState.ViewStateManager>
346
347 </Activity>
3. Host项目引入System.Activities,
System.ServiceModel.Activities和System.ServiceModel。如下图所示:
4. 修改Host项目的program.cs如下:
1 static void Main(string[] args)
2
3 {
4
5 var host = new WorkflowServiceHost(
6
7 new DataExchangeActivity(),
8
9 new Uri("http://localhost:8080/WS"));
10
11
12
13 host.AddDefaultEndpoints();
14
15 host.Description.Behaviors.Add(
16
17 new ServiceMetadataBehavior() { HttpGetEnabled = true });
18
19
20
21 host.AddServiceEndpoint(
22
23 "IMetadataExchange",
24
25 MetadataExchangeBindings.CreateMexHttpBinding(),
26
27 "mex");
28
29
30
31 host.Open();
32
33 Console.WriteLine("Server is ready.");
34
35 Console.Read();
36
37 }
5. 编译Host,然后以Administrator身份运行host.exe,这时会启动WCF,终端窗口显示如下:
6. 这时打开浏览器,浏览http://localhost:8080/ws,会显示如下页面:
7. 打开VS Command Prompt(VS命令行终端),运行svcutil.exe http://localhost:8080/ws?wsdl。结果如下图。这时会生成两个文件,DataExchangeActivity.cs和output.config。将这两个文件copy到client项目中,output.config改名为app.config。
8. 修改Client的Form1,界面如下:
9. 代码如下(很简单就不解释了):
1 private void button1_Click(object sender, EventArgs e)
2
3 {
4
5 var proxy = new DataExchangeActivityClient();
6
7 proxy.ReceiveOrder();
8
9 }
10
11
12
13 private void button2_Click(object sender, EventArgs e)
14
15 {
16
17 var proxy = new CheckCreditClient();
18
19 proxy.CheckCredit(textAction.Text.Trim(), "", int.Parse(textId.Text));
20
21 }
10. 运行Client后,启动流程并且输入对应工作流的审批意见后,结果如下: