年前辭職-WCF入門學習(4)


前言

上一篇的學習中碰到一個問題,用地址http://localhost:8080/mex 訪問元數據的時候一直提示400 bad request 錯誤,因為時間太晚了,查了好幾遍代碼,也沒有發現問題。剛剛又試驗了一下,解決方案分兩步

①用管理員方式運行vs,

② 將

<serviceMetadata httpGetEnabled="true" />
改成
<serviceMetadata httpGetEnabled="true" httpGetUrl="mex"/>

也就是 我們給他指定一個httpGetUrl,至於為什么這么做,是參考的serviceMetadata

最后,要說關於mex endpoint的作用,通俗的來講就是只要客戶端訪問這個地址,他就可以知道關於這個WCF服務一些說明介紹。

第四集 WCF service implementing multiple service contracts

假設有這樣的場景,有個公司需要通過http 給外網提供一個公共服務,同時又需要通過tcp協議給公司防火牆內的內容用戶提供另一個服務,並且,還不想寫多個WCF服務。

所以這一集主要兩點,

  • 在一個WCF服務中實現兩個contract
  • 通過endpoint配置對外界提供這兩個服務 contract

關於如何搭建一個WCF服務,可以參考上一篇,這集只講一些其他的重點。

 

首先是新建一個類庫,然后添加一個WCF服務項,取名CompanyService。然后打開ICompanyService.cs,刪除里面原先的ICompanyService接口,添加如下兩個接口。

    [ServiceContract]
    public interface ICompanyPublicService
    {
        [OperationContract]
        string GetPublicInformation();
    }

    [ServiceContract]
    public interface ICompanyConfidentialService
    {
        [OperationContract]
        string GetConfidentialInformation();
    }
解釋一下,我們定義了兩個合約,一個是公用PublicService ,一個是機密的ConfidentialService,里面分別有各自的GetInformation方法。
然后打開CompanyService.cs 文件,修改里面的CompanyService 類為如下內容:
    public class CompanyService : ICompanyPublicService, ICompanyConfidentialService
    {
        public string GetConfidentialInformation()
        {
            return "這是機密內網的服務";
        }

        public string GetPublicInformation()
        {
            return "這是外網的公共服務";
        }
    }

解釋一下,我們的服務名稱依舊沒有改變,還是CompanyService,但是他實現了上面定義的兩個有ServiceContract特性的契約接口。

類定義完畢,然后是配置文件部分。關於整體的配置文件,請看上一篇,下面是完整代碼。

  <system.serviceModel>
    <services>
      <service name="Part4.CompanyService" behaviorConfiguration="mexBehavior">
        <endpoint address="CompanyService" binding="basicHttpBinding" contract="Part4.ICompanyPublicService"></endpoint>
        <endpoint address="CompanyService" binding="netTcpBinding" contract="Part4.ICompanyConfidentialService"></endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/"/>
            <add baseAddress="net.tcp://localhost:8090/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors >
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="mex"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

因為自己也是初學者,所以在手寫的時候還是會碰到一些問題。比如 service節點 的name 屬性,表示服務的名字,內容是實現接口的帶命名空間的類名;而endpoint里面的contract的名字是定義的時候的帶命名空間的接口名字。同時,為了讓客戶端可以通過添加服務引用的方式來調用,不要忘記了mex endpoint ,以及serviceMetadata元素。

 

然后新建一個控制台程序,用來托管這個服務。關於如何創建,依舊查看上一篇。啟動服務。

QQ截圖20150111170138

完成之后編寫客戶端代碼來調用。

 

我們新建一個Asp.net 的空網站,然后添加服務引用:

QQ截圖20150111161257 

可以看到,CompanyService里面包含了兩個服務。點擊確定,查看一下網站的web.config 文件。

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ICompanyPublicService" />
            </basicHttpBinding>
            <netTcpBinding>
                <binding name="NetTcpBinding_ICompanyConfidentialService" />
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8080/CompanyService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_ICompanyPublicService"
                contract="CompanyService.ICompanyPublicService" name="BasicHttpBinding_ICompanyPublicService" />
            <endpoint address="net.tcp://localhost:8090/CompanyService" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_ICompanyConfidentialService"
                contract="CompanyService.ICompanyConfidentialService" name="NetTcpBinding_ICompanyConfidentialService">
                <identity>
                    <userPrincipalName value="LOUSAIBIAO\Sheldon" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

這些都是自動生成的代碼,用來配合我們客戶端的調用。

然后給網站添加一個新頁面,拖兩個button ,兩個label (你們都懂得)大致就這個效果。

QQ截圖20150111170615

編寫兩個button的點擊事件。

    protected void Button1_Click(object sender, EventArgs e)
    {
        //因為有多個endpoint ,所以要指定名字
         var client = new CompanyPublicServiceClient("BasicHttpBinding_ICompanyPublicService");
        Label1.Text = client.GetPublicInformation();
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        var client = new CompanyConfidentialServiceClient("NetTcpBinding_ICompanyConfidentialService");
        Label2.Text = client.GetConfidentialInformation();
    }

調試運行該網站,並點擊按鈕,得到如下結果。

QQ截圖20150111170803

至此,實現方面的介紹完畢,有一點要說明的,因為我們是在vs上本機調試,說以,兩個button都能獲取的數據,但如果是過防火牆的外網來訪問,在沒有給控制面板中的防火牆添加額外的入站出站規則的時候,GetConfidential 方法是無效的。

介紹完畢,Thank you。


免責聲明!

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



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