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:

注意:这里创建的是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 { getset; }
 5         public InArgument<bool> Reserved { getset; }
 6         public OutArgument<ReservationResponse> Response { getset; }
 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添加如下变量:

设置Receive活动:

    OperationName:RequestBook

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

    ServiceContractName:ILibraryReservation

    ILibraryReservation:true

设置SendReply

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

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

这样我们定义好了 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 { getset; }
 4         public InArgument<string> Author { getset; }
 5         public InArgument<string> ISBN { getset; }
 6         public OutArgument<ReservationRequest> Request { getset; }
 7         public OutArgument<string> RequestAddress { getset; }
 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添加如下参数:

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用于输出,如下图,详见代码:

这样设置好了客户端。

使用wcf服务:

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

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

运行程序:

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

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

整个运行的过程

如下图:

总结:

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

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

下载1:XMAL工作流代码

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

 

 



(全文完)


以下为广告部分

您部署的HTTPS网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

SSL检测评估

快速了解HTTPS网站安全情况。

安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

SSL证书工具

安装部署SSL证书变得更方便。

SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

SSL漏洞检测

让服务器远离SSL证书漏洞侵扰

TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

posted @ 2010-04-18 12:25  麒麟  阅读(7787)  评论(7编辑  收藏  举报