1. 程式人生 > 其它 >WCF學習——構建一個簡單的WCF應用(一) WCF學習——構建一個簡單的WCF應用(一)

WCF學習——構建一個簡單的WCF應用(一) WCF學習——構建一個簡單的WCF應用(一)

引用地址:https://www.cnblogs.com/JamelAr/p/7060698.html

WCF學習——構建一個簡單的WCF應用(一)

本文的WCF服務應用功能很簡單,卻涵蓋了一個完整WCF應用的基本結構。希望本文能對那些準備開始學習WCF的初學者提供一些幫助。

在這個例子中,我們將實現一個簡單的計算器和傳統的分散式通訊框架一樣,WCF本質上提供一個跨程序、跨機器、跨網路的服務呼叫。在本例中,客戶端和WCF應用服務通過執行在同一臺機器上的不同程序模擬。

 

步驟一、構建整個解決方案

     1.建立一個空白的解決方案

      

 


          2.新增四個專案和引用及關係

      

 


              Service.Interface  用於定義服務契約的類庫專案,引用WCF核心程式集System.ServuceModel.dll
              Service           用於定義服務型別的類庫專案,由於服務型別需要實現定義在ervice.Interface中相應的介面,因此需要引用Service.Interface
              Hosting           作為服務寄主的控制檯應用,該專案同時引用Service.Interface、System.ServuceModel.dll、Service
              Client          

 模擬服務的客服端控制檯應用  該醒目引用System.ServuceModel.dll

       

 

     

 

 

 

步驟二、建立服務契約(一般將服務契約定義為介面)

     WCF採用基於介面(MSDN上翻譯為:服務協定)的互動方式實現了服務功能,以及客戶端和服務端之間的鬆耦合。WCF包含五種型別的協定:服務協定、操作協定、訊息協定、錯誤協定和資料協定。

       從功能上講,服務協定將多個相關的操作聯絡在一起,組成單個功能單元。協定可以定義服務級設定,如服務的名稱空間、對應的回撥協定以及其他此類設定,以及各種操作。

      從訊息交換的角度來講,服務協定則定義了基於服務呼叫的訊息交換過程中, 請求訊息和回覆訊息的結構,以及採用的訊息交換模式。

      從使用程式語言的角度來講,協定是通過所選的程式語言建立一個介面,然後將 ServiceContractAttribute 屬性應用於該介面。通過實現該介面,可生成實際的服務程式碼。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.ServiceModel;
 7 
 8 namespace Service.Interface
 9 {
10     /// <summary>
11     /// 計算器
12     /// </summary>
13     [ServiceContract(Name = "CalculatorService",Namespace="http://www.artech.com/")]
14     public interface ICalculator
15     {
16         /// <summary>
17         /// 加
18         /// </summary>
19         /// <param name="x"></param>
20         /// <param name="y"></param>
21         /// <returns></returns>
22         [OperationContract]
23         double Add(double x,double y);
24 
25         /// <summary>
26         /// 減
27         /// </summary>
28         /// <param name="x"></param>
29         /// <param name="y"></param>
30         /// <returns></returns>
31         [OperationContract]
32         double Subtract(double x,double y);
33 
34         /// <summary>
35         /// 乘
36         /// </summary>
37         /// <param name="x"></param>
38         /// <param name="y"></param>
39         /// <returns></returns>
40         [OperationContract]
41         double Multiply(double x,double y);
42 
43         /// <summary>
44         /// 除
45         /// </summary>
46         /// <param name="x"></param>
47         /// <param name="y"></param>
48         /// <returns></returns>
49         [OperationContract]
50         double Divide(double x,double y);
51     }
52 }

 

 

步驟三、實現WCF服務契約

  

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using Service.Interface;
 7 
 8 namespace Service
 9 {
10     public class CalculatorService:ICalculator
11     {
12 
13  
14         public double Add(double x, double y)
15         {
16             return x + y;
17         }
18 
19         public double Subtract(double x, double y)
20         {
21             return x - y;
22         }
23 
24         public double Multiply(double x, double y)
25         {
26             return x * y;
27         }
28 
29         public double Divide(double x, double y)
30         {
31             return x / y;
32         }
33     }
34 }

 

步驟四、通過自我寄宿的方式寄宿服務

    WCF服務需要依存一個執行著的程序(宿主),服務寄宿就是為服務指定一個宿主的過程。WCF是一個基於訊息的通訊框架,採用基於終結點(Endpoint)的通訊手段。

       終結點主要由地址(Address)、繫結(Binding)和協定(Contract)三要素組成,如圖所示。由於三要素應為首字母分別為ABC,所以就有了易於記憶的公式:Endpoint = ABC。一個終結包含了實現通訊所必需的所有資訊。如下圖。

終結點三要素  

  • 地址(Address):一個指示可以查詢終結點的位置的地址。地址決定了服務的位置,解決了服務定址的問題
  • 繫結(Binding):一個指定客戶端如何與終結點進行通訊的繫結。繫結實現了通訊的所有細節,包括網路傳輸、訊息編碼,以及其他為實現某種功能(比如安全、可靠傳輸、事務等)對訊息進行的相應處理。WCF中具有一系列的系統定義繫結,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,
  • 協定(Contract):一個標識可用操作的協定。協定是對服務操作的抽象,也是對訊息交換模式以及訊息結構的定義。 
  • 行為(Behavior):一組指定終結點的本地實現細節的行為。 

      服務寄宿的目的就是開啟一個程序,為WCF服務應用提供一個執行的環境。通過為服務新增一個或多個終結點,使之暴露給潛在的服務呼叫者。服務呼叫者最終通過相匹配的終結點對該服務進行呼叫。

一)程式碼方式實現寄宿

 1        using Service;
 2             using Service.Interface;
 3             using System.ServiceModel;
 4             using System.ServiceModel.Description;
 5 
 6             namespace Hosting
 7             {
 8                 class Program
 9                 {
10                     static void Main(string[] args)
11                     {
12                         //在進行真正的開放時一般在配置檔案裡面進行配置新增終結點和服務行為的定義
13                         using(ServiceHost host = new ServiceHost(typeof(CalculatorService)))
14                         {
15                             //指定繫結和總結點的地址
16                             host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice");
17                             //資料的釋出
18                             if(host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
19                             {
20                                 //建立服務行為
21                                 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
22                                 //是否釋出元資料以便使用HTTPS/GET請求進行檢索
23                                 behavior.HttpGetEnabled = true;
24                                 //使用HTTPS/GET請求的元資料釋出的位置
25                                 behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorservice/metadata");
26                                 //新增到釋出上
27                                 host.Description.Behaviors.Add(behavior);
28                             }
29                             host.Opened += delegate
30                             {
31                                 Console.WriteLine("CalculatorService已經啟動,按任意鍵終止服務!");
32                             };
33                             //通訊狀態轉換到已開啟
34                             host.Open();
35                             Console.ReadLine();
36                         }
37                     }
38                 }
39             }

   1) WCF服務寄宿通過一個特殊的物件完成:ServiceHost。在上面的程式碼基本實現的功能說明,基於WCF服務應用的型別(typeof(CalculatorService))建立了ServieHost物件,並添加了一個終結點。具體的地址為http://127.0.0.1:3721/calculatorservice/metadata,採用了WSHttpBinding,並指定了服務協定的型別ICalculator。

        2) 鬆耦合是SOA的一個基本的特徵,WCF服務應用中客戶端和服務端的鬆耦合體現在客戶端只需要瞭解WCF服務基本的描述,而無需知道具體的實現細節,就可以實現正常的WCF服務呼叫。WCF服務的描述通過元資料(Metadata)的形式釋出出來。WCF中元資料的釋出通過一個特殊的服務行為ServiceMetadataBehavior實現。在上面提供的服務寄宿程式碼中,我們為建立的ServiceHost添加了ServiceMetadataBehavior,並採用了基於HTTP-GET的元資料獲取方式,元資料的釋出地址通過ServiceMetadataBehavior的HttpGetUrl指定。在呼叫ServiceHost的Open方法對服務成功寄宿後,我們可以通過該地址獲取服務相關的元資料。

 

     3) 執行已經生成的hosting.exe,

 

  4)然後在瀏覽器位址列上鍵入http://127.0.0.1:3721/calculatorservice/metadata,你將會得到以WSDL形式體現的服務元資料,如下圖所示。

 

二)配置檔案方式實現寄宿

        在實際應用中,對於WCF應用服務的寄宿,一般不會直接通過編碼的方式進行終結點的新增和服務行為的定義,而是通過寫配置檔案的方式實現,這樣可以方便修改。

       1)  現在我在Hosting專案中新增一個app.config配置檔案,把下面的配置資訊新增到配置檔案app.config中。

    

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3     <startup> 
 4         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 5     </startup>
 6   <system.serviceModel>
 7     
 8     <behaviors>
 9       <serviceBehaviors>
10         <behavior name="metadataBehavior">
11           <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:3721/calculatorservice/metadata" />
12         </behavior>
13       </serviceBehaviors>
14     </behaviors> 
15     
16     <services>
17       <service  behaviorConfiguration="metadataBehavior" name="Service.CalculatorService">
18         <endpoint address="http://127.0.0.1:3721/calculatorservice"
19             binding="wsHttpBinding" bindingConfiguration="" contract="Service.Interface.ICalculator" />
20       </service>
21     </services>
22     
23   </system.serviceModel>
24 </configuration>

 

 

 

   2)  增加app.config配置檔案與配置資訊之後,我們原來寫的寄宿程式碼就不能使用了,需要進行服務寄宿程式碼的修改,而且程式碼會變的更簡潔,只需幾行程式碼就可以了。程式碼如下。

   

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using Service;
 7 using Service.Interface;
 8 using System.ServiceModel;
 9 using System.ServiceModel.Description;
10 
11 namespace Hosting
12 {
13     class Program
14     {
15         static void Main(string[] args)
16         {
17             using(ServiceHost host = new ServiceHost(typeof(CalculatorService)))
18             {
19                 ////指定繫結和終結點的地址
20                 //host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorService");
21                 ////資料的釋出
22                 //if(host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
23                 //{
24                 //    //建立服務行為
25                 //    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
26                 //    //是否釋出元資料以便使用HTTPS/GET請求進行檢索
27                 //    behavior.HttpGetEnabled = true;
28                 //    //使用HTTPS/GET請求的元資料釋出的位置
29                 //    behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorService/metadata");
30                 //    //新增到釋出上
31                 //    host.Description.Behaviors.Add(behavior);
32                 //}
33                 host.Opened += delegate
34                 {
35                     Console.WriteLine("CalculatorService已經啟動,按任意鍵終止服務!");
36                 };
37                 //通訊狀態轉換到已開啟
38                 host.Open();
39                 Console.ReadLine();
40             }
41         }
42     }
43 }

 

    3) 執行hosting.exe應用程式,結果如下圖。

  

 

 

 下一章節講怎麼通過客戶端去呼叫我們成功寄宿後的服務 (歡迎關注)

 

 原始碼地址:

 

    https://github.com/JamelsAr/WcfServicesFirst

 

    https://github.com/JamelsAr/WcfServicesSecond

 

    https://github.com/JamelsAr/WcfServicesThird

 

本文的WCF服務應用功能很簡單,卻涵蓋了一個完整WCF應用的基本結構。希望本文能對那些準備開始學習WCF的初學者提供一些幫助。

在這個例子中,我們將實現一個簡單的計算器和傳統的分散式通訊框架一樣,WCF本質上提供一個跨程序、跨機器、跨網路的服務呼叫。在本例中,客戶端和WCF應用服務通過執行在同一臺機器上的不同程序模擬。

 

步驟一、構建整個解決方案

     1.建立一個空白的解決方案

      

 


          2.新增四個專案和引用及關係

      

 


              Service.Interface  用於定義服務契約的類庫專案,引用WCF核心程式集System.ServuceModel.dll
              Service           用於定義服務型別的類庫專案,由於服務型別需要實現定義在ervice.Interface中相應的介面,因此需要引用Service.Interface
              Hosting           作為服務寄主的控制檯應用,該專案同時引用Service.Interface、System.ServuceModel.dll、Service
              Client           模擬服務的客服端控制檯應用  該醒目引用System.ServuceModel.dll

       

 

     

 

 

 

步驟二、建立服務契約(一般將服務契約定義為介面)

     WCF採用基於介面(MSDN上翻譯為:服務協定)的互動方式實現了服務功能,以及客戶端和服務端之間的鬆耦合。WCF包含五種型別的協定:服務協定、操作協定、訊息協定、錯誤協定和資料協定。

       從功能上講,服務協定將多個相關的操作聯絡在一起,組成單個功能單元。協定可以定義服務級設定,如服務的名稱空間、對應的回撥協定以及其他此類設定,以及各種操作。

      從訊息交換的角度來講,服務協定則定義了基於服務呼叫的訊息交換過程中, 請求訊息和回覆訊息的結構,以及採用的訊息交換模式。

      從使用程式語言的角度來講,協定是通過所選的程式語言建立一個介面,然後將 ServiceContractAttribute 屬性應用於該介面。通過實現該介面,可生成實際的服務程式碼。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.ServiceModel;
 7 
 8 namespace Service.Interface
 9 {
10     /// <summary>
11     /// 計算器
12     /// </summary>
13     [ServiceContract(Name = "CalculatorService",Namespace="http://www.artech.com/")]
14     public interface ICalculator
15     {
16         /// <summary>
17         /// 加
18         /// </summary>
19         /// <param name="x"></param>
20         /// <param name="y"></param>
21         /// <returns></returns>
22         [OperationContract]
23         double Add(double x,double y);
24 
25         /// <summary>
26         /// 減
27         /// </summary>
28         /// <param name="x"></param>
29         /// <param name="y"></param>
30         /// <returns></returns>
31         [OperationContract]
32         double Subtract(double x,double y);
33 
34         /// <summary>
35         /// 乘
36         /// </summary>
37         /// <param name="x"></param>
38         /// <param name="y"></param>
39         /// <returns></returns>
40         [OperationContract]
41         double Multiply(double x,double y);
42 
43         /// <summary>
44         /// 除
45         /// </summary>
46         /// <param name="x"></param>
47         /// <param name="y"></param>
48         /// <returns></returns>
49         [OperationContract]
50         double Divide(double x,double y);
51     }
52 }

 

 

步驟三、實現WCF服務契約

  

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using Service.Interface;
 7 
 8 namespace Service
 9 {
10     public class CalculatorService:ICalculator
11     {
12 
13  
14         public double Add(double x, double y)
15         {
16             return x + y;
17         }
18 
19         public double Subtract(double x, double y)
20         {
21             return x - y;
22         }
23 
24         public double Multiply(double x, double y)
25         {
26             return x * y;
27         }
28 
29         public double Divide(double x, double y)
30         {
31             return x / y;
32         }
33     }
34 }

 

步驟四、通過自我寄宿的方式寄宿服務

    WCF服務需要依存一個執行著的程序(宿主),服務寄宿就是為服務指定一個宿主的過程。WCF是一個基於訊息的通訊框架,採用基於終結點(Endpoint)的通訊手段。

       終結點主要由地址(Address)、繫結(Binding)和協定(Contract)三要素組成,如圖所示。由於三要素應為首字母分別為ABC,所以就有了易於記憶的公式:Endpoint = ABC。一個終結包含了實現通訊所必需的所有資訊。如下圖。

終結點三要素  

  • 地址(Address):一個指示可以查詢終結點的位置的地址。地址決定了服務的位置,解決了服務定址的問題
  • 繫結(Binding):一個指定客戶端如何與終結點進行通訊的繫結。繫結實現了通訊的所有細節,包括網路傳輸、訊息編碼,以及其他為實現某種功能(比如安全、可靠傳輸、事務等)對訊息進行的相應處理。WCF中具有一系列的系統定義繫結,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,
  • 協定(Contract):一個標識可用操作的協定。協定是對服務操作的抽象,也是對訊息交換模式以及訊息結構的定義。 
  • 行為(Behavior):一組指定終結點的本地實現細節的行為。 

      服務寄宿的目的就是開啟一個程序,為WCF服務應用提供一個執行的環境。通過為服務新增一個或多個終結點,使之暴露給潛在的服務呼叫者。服務呼叫者最終通過相匹配的終結點對該服務進行呼叫。

一)程式碼方式實現寄宿

 1        using Service;
 2             using Service.Interface;
 3             using System.ServiceModel;
 4             using System.ServiceModel.Description;
 5 
 6             namespace Hosting
 7             {
 8                 class Program
 9                 {
10                     static void Main(string[] args)
11                     {
12                         //在進行真正的開放時一般在配置檔案裡面進行配置新增終結點和服務行為的定義
13                         using(ServiceHost host = new ServiceHost(typeof(CalculatorService)))
14                         {
15                             //指定繫結和總結點的地址
16                             host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice");
17                             //資料的釋出
18                             if(host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
19                             {
20                                 //建立服務行為
21                                 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
22                                 //是否釋出元資料以便使用HTTPS/GET請求進行檢索
23                                 behavior.HttpGetEnabled = true;
24                                 //使用HTTPS/GET請求的元資料釋出的位置
25                                 behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorservice/metadata");
26                                 //新增到釋出上
27                                 host.Description.Behaviors.Add(behavior);
28                             }
29                             host.Opened += delegate
30                             {
31                                 Console.WriteLine("CalculatorService已經啟動,按任意鍵終止服務!");
32                             };
33                             //通訊狀態轉換到已開啟
34                             host.Open();
35                             Console.ReadLine();
36                         }
37                     }
38                 }
39             }

   1) WCF服務寄宿通過一個特殊的物件完成:ServiceHost。在上面的程式碼基本實現的功能說明,基於WCF服務應用的型別(typeof(CalculatorService))建立了ServieHost物件,並添加了一個終結點。具體的地址為http://127.0.0.1:3721/calculatorservice/metadata,採用了WSHttpBinding,並指定了服務協定的型別ICalculator。

        2) 鬆耦合是SOA的一個基本的特徵,WCF服務應用中客戶端和服務端的鬆耦合體現在客戶端只需要瞭解WCF服務基本的描述,而無需知道具體的實現細節,就可以實現正常的WCF服務呼叫。WCF服務的描述通過元資料(Metadata)的形式釋出出來。WCF中元資料的釋出通過一個特殊的服務行為ServiceMetadataBehavior實現。在上面提供的服務寄宿程式碼中,我們為建立的ServiceHost添加了ServiceMetadataBehavior,並採用了基於HTTP-GET的元資料獲取方式,元資料的釋出地址通過ServiceMetadataBehavior的HttpGetUrl指定。在呼叫ServiceHost的Open方法對服務成功寄宿後,我們可以通過該地址獲取服務相關的元資料。

 

     3) 執行已經生成的hosting.exe,

 

  4)然後在瀏覽器位址列上鍵入http://127.0.0.1:3721/calculatorservice/metadata,你將會得到以WSDL形式體現的服務元資料,如下圖所示。

 

二)配置檔案方式實現寄宿

        在實際應用中,對於WCF應用服務的寄宿,一般不會直接通過編碼的方式進行終結點的新增和服務行為的定義,而是通過寫配置檔案的方式實現,這樣可以方便修改。

       1)  現在我在Hosting專案中新增一個app.config配置檔案,把下面的配置資訊新增到配置檔案app.config中。

    

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3     <startup> 
 4         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 5     </startup>
 6   <system.serviceModel>
 7     
 8     <behaviors>
 9       <serviceBehaviors>
10         <behavior name="metadataBehavior">
11           <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:3721/calculatorservice/metadata" />
12         </behavior>
13       </serviceBehaviors>
14     </behaviors> 
15     
16     <services>
17       <service  behaviorConfiguration="metadataBehavior" name="Service.CalculatorService">
18         <endpoint address="http://127.0.0.1:3721/calculatorservice"
19             binding="wsHttpBinding" bindingConfiguration="" contract="Service.Interface.ICalculator" />
20       </service>
21     </services>
22     
23   </system.serviceModel>
24 </configuration>

 

 

 

   2)  增加app.config配置檔案與配置資訊之後,我們原來寫的寄宿程式碼就不能使用了,需要進行服務寄宿程式碼的修改,而且程式碼會變的更簡潔,只需幾行程式碼就可以了。程式碼如下。

   

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using Service;
 7 using Service.Interface;
 8 using System.ServiceModel;
 9 using System.ServiceModel.Description;
10 
11 namespace Hosting
12 {
13     class Program
14     {
15         static void Main(string[] args)
16         {
17             using(ServiceHost host = new ServiceHost(typeof(CalculatorService)))
18             {
19                 ////指定繫結和終結點的地址
20                 //host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorService");
21                 ////資料的釋出
22                 //if(host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
23                 //{
24                 //    //建立服務行為
25                 //    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
26                 //    //是否釋出元資料以便使用HTTPS/GET請求進行檢索
27                 //    behavior.HttpGetEnabled = true;
28                 //    //使用HTTPS/GET請求的元資料釋出的位置
29                 //    behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorService/metadata");
30                 //    //新增到釋出上
31                 //    host.Description.Behaviors.Add(behavior);
32                 //}
33                 host.Opened += delegate
34                 {
35                     Console.WriteLine("CalculatorService已經啟動,按任意鍵終止服務!");
36                 };
37                 //通訊狀態轉換到已開啟
38                 host.Open();
39                 Console.ReadLine();
40             }
41         }
42     }
43 }

 

    3) 執行hosting.exe應用程式,結果如下圖。

  

 

 

 下一章節講怎麼通過客戶端去呼叫我們成功寄宿後的服務 (歡迎關注)

 

 原始碼地址:

 

    https://github.com/JamelsAr/WcfServicesFirst

 

    https://github.com/JamelsAr/WcfServicesSecond

 

    https://github.com/JamelsAr/WcfServicesThird