程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF4.0實戰(三):WCF服務

WF4.0實戰(三):WCF服務

編輯:關於.NET

這篇文章,通過一個簡單的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 { 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添加如下變量:

設置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 { 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添加如下參數:

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<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服務。等待客戶端的調用,如下圖:

輸入回車,啟動客戶端的工作流,來調用WCF服務,輸入結果如下:

整個運行的過程

如下圖:

總結:

這篇文章講述了在WF4.0中使用WCF服務。WF中的WCF與普通的WCF,在原理上是一致的,但是在形式上區別很大。WF4.0中提供了一組活動 ,這樣比直接使用WCF更加簡單和直觀。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved