WF4.0实战(三):WCF服务

这篇文章,通过一个简单的WCF交互,讲解一下WF4.0中一组重要活动:Messaging,它包括:Receive
、ReceiveAndSendReply、Send、SendAndReceiveReply。这里将详细讲解ReceiveAndSendReply和SendAndReceiveReply两个活动的配置以及使用,以及它与普通的WCF的区别。

    如果你了解WCF,你一定知道WCF可以缩略为ABC。A :Address (服务在哪里?),B: Binding (怎么才能访问服务?),C: Contract (提供了哪些服务?)。既然同样也是WCF服务,WF4.0中WCF服务同样也存在ABC的概念。我将一步一步通过实现WF中的wcf服务的ABC来实现这个Demo,请你注意它与普通的WCF的区别。

     首先,我们定义一下用于数据交换的实体。

     定义Request消息ReservationRequest

代码
 1   [MessageContract(IsWrapped  =   false )]
 2       public   class  ReservationRequest
 3      {
 4           private  String _ISBN;
 5           private  String _Title;
 6           private  String _Author;
 7           private  Guid _RequestID;
 8           private  Branch _Requester;
 9           private  Guid _InstanceID;
10 
11           #region  Constructors
12           public  ReservationRequest()
13          {
14          }
15 
16           public  ReservationRequest(String title, String author, String isbn,
17              Branch requestor)
18          {
19              _Title  =  title;
20              _Author  =  author;
21              _ISBN  =  isbn;
22              _Requester  =  requestor;
23              _RequestID  =  Guid.NewGuid();
24          }
25 
26           public  ReservationRequest(String title, String author, String isbn,
27              Branch requestor, Guid id)
28          {
29              _Title  =  title;
30              _Author  =  author;
31              _ISBN  =  isbn;
32              _Requester  =  requestor;
33              _RequestID  =  id;
34          }
35           #endregion  Constructors
36 
37           #region  Public Properties
38          [MessageBodyMember]
39           public  String Title
40          {
41               get  {  return  _Title; }
42               set  { _Title  =  value; }
43          }
44 
45          [MessageBodyMember]
46           public  String ISBN
47          {
48               get  {  return  _ISBN; }
49               set  { _ISBN  =  value; }
50          }
51 
52          [MessageBodyMember]
53           public  String Author
54          {
55               get  {  return  _Author; }
56               set  { _Author  =  value; }
57          }
58 
59          [MessageBodyMember]
60           public  Guid RequestID
61          {
62               get  {  return  _RequestID; }
63               set  { _RequestID  =  value; }
64          }
65 
66          [MessageBodyMember]
67           public  Branch Requester
68          {
69               get  {  return  _Requester; }
70               set  { _Requester  =  value; }
71          }
72 
73          [MessageBodyMember]
74           public  Guid InstanceID
75          {
76               get  {  return  _InstanceID; }
77               set  { _InstanceID  =  value; }
78          }
79           #endregion  Public Properties
80      }

定义Response消息ReservationResponse:

代码
 1   [MessageContract(IsWrapped  =   false )]
 2       public   class  ReservationResponse
 3      {
 4           private   bool  _Reserved;
 5           private  Branch _Provider;
 6           private  Guid _RequestID;
 7 
 8           #region  Constructors
 9           public  ReservationResponse()
10          {
11          }
12 
13           public  ReservationResponse(ReservationRequest request,  bool  reserved,
14              Branch provider)
15          {
16              _RequestID  =  request.RequestID;
17              _Reserved  =  reserved;
18              _Provider  =  provider;
19          }
20           #endregion  Constructors
21 
22           #region  Public Properties
23          [MessageBodyMember]
24           public   bool  Reserved
25          {
26               get  {  return  _Reserved; }
27               set  { _Reserved  =  value; }
28          }
29 
30          [MessageBodyMember]
31           public  Branch Provider
32          {
33               get  {  return  _Provider; }
34               set  { _Provider  =  value; }
35          }
36 
37          [MessageBodyMember]
38           public  Guid RequestID
39          {
40               get  {  return  _RequestID; }
41               set  { _RequestID  =  value; }
42          }
43           #endregion  Public Properties
44      }

服务端的实现

一、C(Contract )

定义这个服务具体提供了哪些服务:

1      [ServiceContract]
2       public   interface  ILibraryReservation
3      {
4          [OperationContract]
5           void  RequestBook(ReservationRequest request);
6 
7          [OperationContract]
8           void  RespondToRequest(ReservationResponse response);
9      }

这里定义了两个方法:RequestBook、RespondToRequest。在普通的WCF中,一般做法是:通过一个类继承这个接口。在类中实现wcf的具体内容。而在WF4.0中,这里我将使用Messaging中的活动:ReceiveAndSendReply。

1、新建一个控制台应用程序WF3Demo:

WF4.0实战(三):WCF服务_第1张图片

注意:这里创建的是Console Application。而不是WorkflowConsoleApplication。

2、添加下面这些引用:

    System.Activities.dll

    System.ServiceModel.dll

    System.ServiceModel.Activities.dll

3、创建一个自定义活动CreateResponse,它用于创建返回给客户端的ReservationResponse对象,代码如下:

 1    // 这种是一个自定义的活动,用于创建一个ReservationResponse对象
 2       public   sealed   class  CreateResponse : CodeActivity
 3      {
 4           public  InArgument < ReservationRequest >  Request {  get set ; }
 5           public  InArgument < bool >  Reserved {  get set ; }
 6           public  OutArgument < ReservationResponse >  Response {  get set ; }
 7 
 8           protected   override   void  Execute(CodeActivityContext context)
 9          {
10               //  打开配置文件
11              Configuration config  =  ConfigurationManager
12                  .OpenExeConfiguration(ConfigurationUserLevel.None);
13              AppSettingsSection app  =
14                  (AppSettingsSection)config.GetSection( " appSettings " );
15 
16               //  创建ReservationResponse对象
17              ReservationResponse r  =   new  ReservationResponse
18                  (
19                      Request.Get(context),
20                      Reserved.Get(context),
21                       new  Branch
22                      {
23                          BranchName  =  app.Settings[ " Branch Name " ].Value,
24                          BranchID  =   new  Guid(app.Settings[ " ID " ].Value),
25                          Address  =  app.Settings[ " Address " ].Value
26                      }
27                  );
28               //  将Response保存到OutArgument
29              Response.Set(context, r);
30          }
31      }

5、添加一个名字为ProcessRequest工作流,在其中拖放一个ReceiveAndSendReply。

    在ProcessRequest添加如下变量:

WF4.0实战(三):WCF服务_第2张图片

设置Receive活动:

    OperationName:RequestBook

    Content: 设置Message data为request、设置Message type为ReservationRequest

    ServiceContractName:ILibraryReservation

    ILibraryReservation:true

设置SendReply

Content: 设置Message data为response、设置Message type 为ReservationResponse,如下图:

WF4.0实战(三):WCF服务_第3张图片

6、为了更好的诠释服务,在Receive活动和SendReply活动之间加入如下图活动,详细见代码。

WF4.0实战(三):WCF服务_第4张图片

这样我们定义好了 Contract

二、B(Binding)和A(Address )

    C实现之后,Binding和Address就简单了。这里Binding使用BasicHttpBinding,使用如下代码实现B和A:

 1   WorkflowService service  =   new  WorkflowService
 2              {
 3                  Name  =   " LibraryReservation " ,
 4                  Body  =   new  ProcessRequest(),
 5                  Endpoints  =
 6                  {
 7                       new  Endpoint
 8                      {
 9                          ServiceContractName = " ILibraryReservation " ,
10                          AddressUri  =   new  Uri( " http://localhost: "   +  adr  +  
11                               " /LibraryReservation " ),
12                          Binding  =   new  BasicHttpBinding(),
13                      }
14                  }
15              };
16 
17              System.ServiceModel.Activities.WorkflowServiceHost wsh  =
18                   new  System.ServiceModel.Activities.WorkflowServiceHost(service);
19 
20              wsh.Open();

至此,WF4中的wcf服务就这样简单的配置好了。

客户端调用:

    对于调用一般的WCF,可以通过添加service引用或者通过命令自动生成调用wcf的代码。这与WF4.0不同,这里我使用SendAndReceiveReply活动来调用WCF服务。

1、首先自定义一个活动CreateRequest,用于创建一个提交wcf服务ReservationRequest对象。

 1       public   sealed   class  CreateRequest : CodeActivity
 2      {
 3           public  InArgument < string >  Title {  get set ; }
 4           public  InArgument < string >  Author {  get set ; }
 5           public  InArgument < string >  ISBN {  get set ; }
 6           public  OutArgument < ReservationRequest >  Request {  get set ; }
 7           public  OutArgument < string >  RequestAddress {  get set ; }
 8 
 9           protected   override   void  Execute(CodeActivityContext context)
10          {
11               //  打开配置文件,得到请求的地址
12              Configuration config  =  ConfigurationManager
13                  .OpenExeConfiguration(ConfigurationUserLevel.None);
14              AppSettingsSection app  =
15                  (AppSettingsSection)config.GetSection( " appSettings " );
16 
17               //  使用输入参数创建一个ReservationRequest对象
18              ReservationRequest r  =   new  ReservationRequest
19                  (
20                      Title.Get(context),
21                      Author.Get(context),
22                      ISBN.Get(context),
23                       new  Branch
24                      {
25                          BranchName  =  app.Settings[ " Branch Name " ].Value,
26                          BranchID  =   new  Guid(app.Settings[ " ID " ].Value),
27                          Address  =  app.Settings[ " Address " ].Value
28                      }
29                  );
30 
31               // 将request保存到OutArgument中 
32              Request.Set(context, r);
33 
34               //  将address保存到OutArgument
35              RequestAddress.Set(context, app.Settings[ " Request Address " ].Value);
36          }
37      }

2、添加一个名字为SendRequest的工作流,在其中拖放一个SendAndReceiveReply活动,以及一个CreateRequest活动,将CreateRequest活动拖放到Send前面。

3、在ProcessRequest添加如下变量:

 在ProcessRequest添加如下参数:

WF4.0实战(三):WCF服务_第5张图片

4、设置Send:

    OperationName:RequestBook

    Content: 设置Message data为request、设置Message type为ReservationRequest

    ServiceContractName:ILibraryReservation

    Endpoint:Endpoint

    Endpoint.Binding:BasicHttpBinding

    EndpointAddress:New Uri("http://localhost/:" + requestAddress + "/LibraryReservation")

5、设置ReceiveReplyForSend

    将ReceiveReplyForSend的Content的Message data设为response,将ReceiveReplyForSend的Content的Message type设为ReservationResponse

6、为了便于观察,添加几个WriteLine用于输出,如下图,详见代码:

WF4.0实战(三):WCF服务_第6张图片

这样设置好了客户端。

使用wcf服务:

我们只需启动ProcessRequest这个工作流来调用wcf服务:

 1              IDictionary < string object >  input  =   new  Dictionary < string object >  
 2              {
 3                  {  " Title "  ,  " Gone with the Wind "  },
 4                  {  " Author " " Margaret Mitchell "  },
 5                  {  " ISBN " " 9781416548898 "  }
 6              };
 7 
 8              IDictionary < string object >  output  =
 9                  WorkflowInvoker.Invoke( new  SendRequest(), input);
10              ReservationResponse resp  =  (ReservationResponse)output[ " Response " ];

运行程序:

启动WCF服务。等待客户端的调用,如下图:

WF4.0实战(三):WCF服务_第7张图片

输入回车,启动客户端的工作流,来调用WCF服务,输入结果如下:

整个运行的过程

如下图:

WF4.0实战(三):WCF服务_第8张图片

总结:

    这篇文章讲述了在WF4.0中使用WCF服务。WF中的WCF与普通的WCF,在原理上是一致的,但是在形式上区别很大。WF4.0中提供了一组活动,这样比直接使用WCF更加简单和直观。

欢迎加入博客园WF4.0技术交流群:51262864

下载1:XMAL工作流代码

下载2:CS工作流代码下载

 

作者:朱祁林
出处:http://zhuqil.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

你可能感兴趣的:(工作,service,活动,application,WCF,binding)