WCF學習之旅——第一個WCF示例(三)


WCF學習之旅目錄

WCF學習之旅——第一個WCF示例(一)

WCF學習之旅——第一個WCF示例(二)

WCF學習之旅——第一個WCF示例(三)

第五步:創建客戶端

      WCF應用服務被成功寄宿后,WCF服務應用便開始了服務調用請求的監聽工作。此外,服務寄宿將服務描述通過元數據的形式發布出來,相應的客戶端就可以獲取這些元數據。接下來我們來創建客戶端程序進行服務的調用。

      1) 現在請先運行服務寄宿程序(Hosting.exe)。

      2) 在Visual Studio 2015的“解決方案資源管理器”中,把WinClient項目展開,左鍵選中“引用”,點擊鼠標右鍵,彈出菜單,在彈出的上下文菜單中選擇“添加服務引用(Add Service References)”。如下圖。

       3) 此時會彈出一個對話框,如下圖所示。在對話框中的“地址”輸入框中輸入服務元數據發布的源地址:http://127.0.0.1:8888/BookService/metadata,並在“命名空間”輸入框中輸入一個命名空間,然后點擊“確定”按鈕(如下圖)。Visual studio 2015會自動生成一系列用於服務調用的代碼和配置。

 

 添加服務引用

     4)  在Visual Studio 2015自動生成的類中,包含一個服務協定接口、一個服務代理對象和其他相關的類。被客戶端直接用於服務調用的是一個繼承自 ClientBase<IBookService>並實現了IBookService接口的服務代理類BookServiceClient。 如下圖。

 

     5)BookServiceClient的具體實現如下圖。

 

 

      6) 我們可以實例化BookServiceClient對象,執行相應方法調用WCF服務操作。客戶端進行WCF服務調用的代碼如下:

 

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WinClient { public partial class FrmBook : Form { public FrmBook() { InitializeComponent(); } private void btnGetBook_Click(object sender, EventArgs e) { BookServiceRef.Books book = new BookServiceRef.Books(); BookServiceRef.BookServiceClient bookSvrClient = new BookServiceRef.BookServiceClient(); textBoxMsg.Text= bookSvrClient.GetBook("3"); book = XMLHelper.DeSerializer<BookServiceRef.Books>(textBoxMsg.Text); txtBookId.Text = book.BookID.ToString(); txtAuthorID.Text = book.AuthorID.ToString(); textBoxName.Text = book.Name; textBoxCategory.Text = book.Category.ToString(); textBoxPrice.Text = book.Price.ToString(); } } }

 

運行后的結果,如下圖。

 

第六步:客戶端通過ChannelFactory<T>方式調用WCF服務

      客戶端通過服務代理對象進行服務的調用,上面的例子通過創建自動生成的繼承自ClientBase<T>的類型對象進行服務調用。實際上,我們還具有另外一種創建服務代理的方法,就是通過ChannelFactory<T>。此外,WCF采用基於協定的服務調用方法,從上面的例子我們也可以看到,Visual Studio 2015在進行服務引用添加的過程中,會在客戶端創建一個與服務端等效的服務協定接口。在我們的例子中,由於服務端和客戶端都是在同一個解決方案中,完全可以讓服務端和客戶端引用相同的協定。

       1)  為了實現通過ChannelFactory<T>調用WCF服務的功能,我們需要添加一個新的項目,命名為SCF.Contracts,把原來在SCF. WcfService項目中的IBookService.cs文件移到SCF.Contracts項目中,同時變更命名空間。SCF. WcfService與WinClient項目同時添加對SCF.Contracts項目的引用。最后的項目結構如下圖。

 

       2)  我們將通過於這個SCF.Contracts項目中的IBookService服務協定接口,使用 ChannelFactory<IBookService>創建服務代理對象,直接進行相應的服務調用。我們先實現全部在代碼中實現基於 ChannelFacotory<T>進行服務代理的創建和服務調用的方式。代碼如下:

private void buttonChannelFactory_Click(object sender, EventArgs e) { using (ChannelFactory<IBookService> channelFactory = new ChannelFactory<IBookService> (new WSHttpBinding(), "http://127.0.0.1:8888/BookService")) { IBookService proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { textBoxMsg.Text = proxy.GetBook("4"); Books book = XMLHelper.DeSerializer<Books>(textBoxMsg.Text); txtBookId.Text = book.BookID.ToString(); txtAuthorID.Text = book.AuthorID.ToString(); textBoxName.Text = book.Name; textBoxCategory.Text = book.Category.ToString(); textBoxPrice.Text = book.Price.ToString(); } } }

 

        3)  點擊“ChannelFactory方式”按鈕之后,結果如下圖。

 

       4)  由於終結點是WCF進行通信的唯一手段,ChannelFactory<T>本質上是通過指定的終結點創建用於進行服務調用的服務代理。在上面的代碼中,在創建ChannelFactory<T>的時候再在構造函數中指定終結點的相關要素(協定通過范型類型表示,地址和綁定則通過參數指定)。上面這種直接在代碼中寫相應地址與綁定的方法,對於后期的維護不方便。在實際的WCF應用中,一般在配置文件中寫地址與綁定,然后通過讀取配置文件的方式來實現服務調用。我們在app.config配置文件中配置指定終結點的三要素,並為相應的終結點指定一個終結點配置名稱(BookService)。配置信息如下:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IBookService" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://127.0.0.1:8888/BookService" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBookService" contract="SCF.Contracts.IBookService" name="WSHttpBinding_IBookService">
                <identity>
                    <userPrincipalName value="DEVELOPER\Administrator" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

</configuration>

 

 

        5)  接下來我們通過配置信息來創建ChannelFactory<T>對象,此時無須再指定終結點的綁定和地址了,而只須制定對應的終結點配置名稱。代碼如下。

 

  private void buttonChannelConfig_Click(object sender, EventArgs e) { using (ChannelFactory<IBookService> channelFactory = new ChannelFactory<IBookService>("WSHttpBinding_IBookService")) { IBookService proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { textBoxMsg.Text = proxy.GetBook("5"); Books book = XMLHelper.DeSerializer<Books>(textBoxMsg.Text); txtBookId.Text = book.BookID.ToString(); txtAuthorID.Text = book.AuthorID.ToString(); textBoxName.Text = book.Name; textBoxCategory.Text = book.Category.ToString(); textBoxPrice.Text = book.Price.ToString(); } } }

 

        6) 點擊“ChannelFactorys配置方式”按鈕之后,結果如下圖。

 

 

 

注: 我在編寫這個示例項目的過程中遇到了以下問題:

WCF由於目標計算機積極拒絕,無法連接錯誤

錯誤描述:新建的WCF類庫項目,由WinForm程序托管,托管的時候沒有錯誤,但是在客戶端引用服務的時候,卻找不到服務,而且 如果打開多個服務也不會報端口占用錯誤。

解決思路:

1)檢查配置文件,看配置信息是否寫的正確,不行

2)重啟電腦,不行

3)把配置方式改成了直接代碼方式,不行

4)不寄宿WCF服務的情況下引用服務,提示一樣的錯誤。我打開監聽端口仔細找,沒有找到我定義的8888端口。看來WCF服務寄宿沒有成功,如果寄宿成功,端口肯定是在監聽狀態。

解決辦法:首先去掉using,然后再試,引用服務成功,調用也成功。原來當使用using時,如果using被釋放,則host會被using關閉,所以服務打開之后,然后就立即被關閉了。請仔細觀察下面兩段代碼的區別。

錯誤代碼:

 

 static void Main(string[] args) { try { using (ServiceHost host = new ServiceHost(typeof(BookService))) { host.Opened += delegate { Console.WriteLine("BookService,使用配置文件,按任意鍵終止服務!"); }; host.Open(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.Read(); }

 

正確代碼:

static void Main(string[] args) { try { using (ServiceHost host = new ServiceHost(typeof(BookService))) {
host.Opened
+= delegate { Console.WriteLine("BookService,使用配置文件,按任意鍵終止服務!"); }; host.Open(); Console.Read(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } }

 


免責聲明!

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



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