Workflow:实现一个简单的审批流程

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后,启动流程并且输入对应工作流的审批意见后,结果如下:

 

源代码下载

 

posted @ 2014-05-13 14:22  GreatK  阅读(4535)  评论(0编辑  收藏  举报