寄宿於CS程序的WCF服務


最近項目中,需要對外部程序提供服務接口,用來進行數據交互和部分設備控制。由於都是使用的.NET平台開發的,因此想到使用WCF服務。之前也用過WCF服務,但是當初使用的時候是通過IIS寄宿的,有些地方不太讓人滿意,一則是同一個軟件要部署兩個地方,CS的桌面程序和寄宿於IIS的WCF服務部分,二則是由於系統本身問題,使用的是SQLite數據庫,無法實現多線程訪問,造成了數據重復,容易造成數據不一致。所以現在准備把WCF服務寄宿於CS程序中,這樣就解決了以上兩個問題。

由於對WCF一知半解,只知道按部就班的使用,從明白過其中的道理,所以在網上找了些教程[1],實現了自己的想法,但其中碰到不少問題,想來還是記下,或許以后還有用處。

本文使用一個最簡單的控制台應用程序,同時通過使用WcfTestClient.exe測試,來完成這個示例。

一、在代碼中實現並配置WCF服務。

在VS2012中創建一個控制台應用程序項目CsWcf,並添加接口ICalculator作為契約接口、類CalculatorService作為服務實現此接口中的操作方法,代碼如下:

1. ICalculator.cs--服務契約

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.ServiceModel;
   6:  
   7: namespace CsWcf
   8: {
   9:     [ServiceContract]
  10:     public interface ICalculator
  11:     {
  12:         [OperationContract]
  13:         double Add(double x, double y);
  14:     }
  15: }

2. CalculatorService.cs--服務實現

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.ServiceModel;
   6:  
   7: namespace CsWcf
   8: {
   9:     public class CalculatorService:ICalculator
  10:     {
  11:         public double Add(double x, double y)
  12:         {
  13:             return x + y;
  14:         }
  15:     }
  16: }

3. 在Program.cs中的Main函數中,添加如下代碼,實現WCF服務的寄宿,並開啟服務。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://192.168.1.102:10002/CalculatorService");
   4:  
   5:     if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
   6:     {
   7:         ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
   8:         behavior.HttpGetEnabled = true;
   9:         behavior.HttpGetUrl = new Uri("http://192.168.1.102:10002/CalculatorService");
  10:         host.Description.Behaviors.Add(behavior);
  11:     }
  12:  
  13:     host.Opened += delegate
  14:     {
  15:         Console.WriteLine("CalculaorService已經啟動,按任意鍵終止服務!");
  16:     };
  17:  
  18:     host.Open();
  19:     Console.Read();
  20: }

4. F5調試執行,服務開啟后,打開WcfTestClient,添加服務地址,可以正確調用Add服務函數。

但是,以上將服務相關配置寫到代碼中了,這不利於后面的安裝和部署。所以需要將配置信息放置在config配置文件中。

二,使用配置文件動態配置WCF服務

配置app.config文件,實現WCF服務的可配置性。在項目中添加應用程序配置文件,並添加以下內容:

   1: <system.serviceModel>
   2:   <behaviors>
   3:     <serviceBehaviors>
   4:       <behavior name="metadataBehavior">
   5:         <serviceMetadata httpGetEnabled="true" httpGetUrl="http://192.168.1.102:10002/CalculatorService/metadata" />
   6:       </behavior>
   7:     </serviceBehaviors>
   8:   </behaviors>
   9:   <services>
  10:     <service behaviorConfiguration="metadataBehavior" name="CsWcf.CalculatorService">
  11:       <endpoint address="http://192.168.1.102:10002/calculatorservice" binding="wsHttpBinding" 
  12:                 contract="CsWcf.ICalculator"  />
  13:       <endpoint address="http://192.168.1.102:10002/calculatorservice/MEX/" binding="mexHttpBinding" 
  14:                   contract="IMetadataExchange"  />
  15:     </service>
  16:   </services>
  17: </system.serviceModel>

同時需要刪除Program.cs中的配置代碼:

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     host.Opened += delegate
   4:     {
   5:         Console.WriteLine("CalculaorService已經啟動,按任意鍵終止服務!");
   6:     };
   7:  
   8:     host.Open();
   9:     Console.Read();
  10: }

F5調試執行,與剛剛的執行結果一樣!此處要特別注意:配置節中的第二個endpoint,即MEX配置,一定要加上,否則會出現如下錯誤:

錯誤: 無法從 http://192.168.1.102:10002/CalculatorService 獲取元數據如果是您有權訪問的 Windows (R) Communication Foundation 服務,請檢查是否已啟用在指定地址發布元數據。有關啟用元數據發布的幫助,請參閱 http://go.microsoft.com/fwlink/?LinkId=65455 上的 MSDN 文檔。WS-Metadata Exchange 錯誤 URI: http://192.168.1.102:10002/CalculatorService 元數據包含無法解析的引用:“http://192.168.1.102:10002/CalculatorService”。 Sendera:BadContextToken無法處理消息。這很可能是因為操作“http://schemas.xmlsoap.org/ws/2004/09/transfer/Get”不正確,或因為消息包含無效或過期的安全上下文令牌,或因為綁定之間出現不匹配。如果由於未處於活動狀態導致服務中止了該通道,則安全上下文令牌無效。若要防止服務永久中止閑置會話,請增加服務終結點綁定上的接收超時。HTTP GET Error URI: http://192.168.1.102:10002/CalculatorService 下載“http://192.168.1.102:10002/CalculatorService”時出錯。 請求因 HTTP 狀態 400 失敗: Bad Request。

我在Artech的文章[1]中學習中並沒有看到第二個終結點的配置,所以運行的時候一直出錯,找了好久才找到這個解決辦法,可以參考“WCF Part 4 : Make your service visible through metadata”這篇文章[2]

三、其它機器訪問權限限制的解決辦法

以上兩步驟,我們完成了WCF服務的寄宿、發布和訪問,但是如果在其它計算機上訪問此WCF服務時,會發現權限提示:

無法滿足對安全令牌的請求,因為身份驗證失敗!

這個時候,默認的安全是計算機名和用戶名做為權限要求。如果想讓其他用戶也可以隨時訪問到些WCF服務,就需要修改配置文件中的安全級別,設置<security>的mode為None就可以了。同時更改一個endpoint的bindingConfiguration="wsHttpBindingConfiguration"。

   1: <bindings>
   2:   <wsHttpBinding>
   3:     <binding name="wsHttpBindingConfiguration" maxReceivedMessageSize="20971510">
   4:       <readerQuotas maxStringContentLength="20971520" maxArrayLength="20971520"/>
   5:       <security mode="None"/>
   6:     </binding>
   7:   </wsHttpBinding>
   8: </bindings>

再次運行此服務,其它計算機上也可以訪問此服務了。

總結:WCF用起來簡單,“制作”起來貌似也很簡單,和寫其它的代碼基本無異,但是真正使用起來的時候,卻又經常碰到這樣那樣的問題,個人感覺WCF是一個極其精密的儀器,操作簡單,但是儀器的操作步驟和順序卻比較麻煩,而且零部件不牢固,經常脫落損壞,所以要想更好的使用它,需要對它有個很好的了解才是。由於現在網絡的存在,好多東西都是用的時候搜索一下,基本沒有系統、深入的學習過,這對以后的學習和工作經驗的積累都用處不太大。

[1] Artech, 我的WCF之旅(1):創建一個簡單的WCF程序

[2] Dennis van der Stelt, WCF Part 4 : Make your service visible through metadata


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM