共用方式為


操作格式器和操作選擇器

QueryStringFormatter 範例示範如何使用 Windows Communication Foundation (WCF) 擴充點,以不同於 WCF 預期的格式來允許訊息數據。 根據預設,WCF 格式器預期方法參數會包含在 元素下 soap:body 。 此範例展示如何實作自定義操作格式器,以剖析 HTTP GET 查詢字串中的參數數據,並利用該數據來叫用方法。

此範例是以實作服務合約的 ICalculator 為基礎。 它顯示如何將 Add、Subtract、Multiply 和 Divide 訊息變更為使用 HTTP GET 進行客戶端向伺服器的請求,並使用 POX 訊息的 HTTP POST 進行伺服器向客戶端的回應。

若要這樣做,此範例提供了下列內容:

  • QueryStringFormatter,分別針對客戶端和伺服器實作 IClientMessageFormatterIDispatchMessageFormatter ,並處理查詢字串中的數據。

  • UriOperationSelector,它會在伺服器上實作 IDispatchOperationSelector ,以根據 GET 要求中的作業名稱來執行作業分派。

  • EnableHttpGetRequestsBehavior 端點行為(以及相應的組態),會將必要的作業選取器新增至執行階段。

  • 示範如何將新的作業格式器插入執行階段。

  • 在此範例中,客戶端和服務都是控制台應用程式(.exe)。

備註

此範例的安裝程式和建置指示位於本主題結尾。

重要概念

QueryStringFormatter - 作業格式器是 WCF 中的元件,負責將訊息轉換成參數物件的數位,並將參數物件的數位轉換成訊息。 這會在用戶端上使用 IClientMessageFormatter 介面完成,並在伺服器端使用 IDispatchMessageFormatter 介面。 這些介面可讓使用者從 SerializeDeserialize 方法取得要求和回應訊息。

在此範例中, QueryStringFormatter 會實作這兩個介面,並在用戶端和伺服器上實作。

要求:

  • 此範例使用 TypeConverter 類別,將要求訊息中的參數數據轉換成字串並從字串轉換回來。 如果特定類型的TypeConverter不可用,範例格式器將擲回例外狀況。

  • 在用戶端的 IClientMessageFormatter.SerializeRequest 方法中,格式器會創建 URI,使用適當的 To 地址,並將操作名稱作為後綴附加上去。 這個名稱被用來調度伺服器上的適當作業。 然後,它會取得參數物件的陣列,並使用參數名稱及由 TypeConverter 類別轉換的值,將參數數據序列化至 URI 查詢字串。 ToVia 屬性接著會設定為這個 URI。 MessageProperties 是透過 Properties 屬性存取。

  • IDispatchMessageFormatter.DeserializeRequest 伺服器上的方法中,格式器會擷取 Via 傳入要求訊息屬性中的 URI。 它會將 URI 查詢字串中的名稱/值組剖析為參數名稱和值,並使用參數名稱和值填入傳入方法的參數數位。 請注意,作業分派已經發生,因此此方法中會忽略作業名稱後綴。

回應:

  • 在此範例中,HTTP GET 僅用於要求。 格式子會將回應的傳送委派給原本用來產生 XML 訊息的原始格式器。 此範例的其中一個目標是示範如何實作這類委派格式器。

UriPathSuffixOperationSelector 類別

介面 IDispatchOperationSelector 讓用戶能夠透過實作自己的邏輯來決定應將特定訊息分派給哪些作業。

在此範例中, UriPathSuffixOperationSelector 必須在伺服器上實作以選取適當的作業,因為作業名稱會包含在 HTTP GET URI 中,而不是訊息中的動作標頭。 此範例設定為只允許不區分大小寫的作業名稱。

方法 SelectOperation 會接收傳入的訊息,並在訊息屬性中查閱 Via URI。 它會從 URI 擷取作業名稱後綴、查閱內部數據表以取得訊息應該分派給的作業名稱,並傳回該作業名稱。

EnableHttpGetRequestsBehavior 類別(啟用 HTTP GET 請求行為的類別)

元件 UriPathSuffixOperationSelector 可以透過程序設計方式或透過端點行為進行設定。 此範例會實作 EnableHttpGetRequestsBehavior 行為,此行為是在服務的應用程式組態檔中指定。

在伺服器上:

OperationSelector設置為IDispatchOperationSelector的實作。

根據預設,WCF 會使用完全相符的地址篩選。 傳入訊息上的 URI 包含作業名稱後綴,後面接著包含參數數據的查詢字串,因此端點行為也會將位址篩選變更為前置詞比對篩選條件。 它為此目的使用 WCFPrefixEndpointAddressMessageFilter

安裝操作格式化工具

指定格式器的作業行為是獨特的。 每個作業預設都會實作一種這類行為,以建立必要的作業格式器。 不過,這些行為看起來只是另一個作業行為;任何其他屬性都無法識別它們。 若要安裝取代行為,實作必須尋找 WCF 類型載入器預設所安裝的特定格式器行為,並取代它或新增相容的行為,以在預設行為之後執行。

在呼叫 CommunicationObject.Open 之前,可以透過程式碼設定這些作業格式器行為,或指定預設行為之後執行的作業行為。 不過,由於行為模型不允許行為取代其他行為,或修改描述樹狀結構,因此無法輕易設定端點行為(因此透過組態設定)。

在用戶端上:

必須實作 IClientMessageFormatter 以便將要求轉換成 HTTP GET 要求,並將回應委派給原格式器處理。 這是藉由呼叫 EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior 協助程式方法來完成。

必須在呼叫 CreateChannel 之前完成此操作。

void ReplaceFormatterBehavior(OperationDescription operationDescription, EndpointAddress address)
{
    // Remove the DataContract behavior if it is present.
    IOperationBehavior formatterBehavior = operationDescription.Behaviors.Remove<DataContractSerializerOperationBehavior>();
    if (formatterBehavior == null)
    {
        // Remove the XmlSerializer behavior if it is present.
        formatterBehavior = operationDescription.Behaviors.Remove<XmlSerializerOperationBehavior>();
        ...
    }

    // Remember what the innerFormatterBehavior was.
    DelegatingFormatterBehavior delegatingFormatterBehavior = new DelegatingFormatterBehavior(address);
    delegatingFormatterBehavior.InnerFormatterBehavior = formatterBehavior;
   operationDescription.Behaviors.Add(delegatingFormatterBehavior);
}

在伺服器上:

  • IDispatchMessageFormatter介面必須實作,以便讀取 HTTP GET 要求,並委派給原始格式器以撰寫回應。 做法是呼叫與用戶端相同的 EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior 協助程式方法(請參閱先前的程式代碼範例)。

  • 必須在呼叫 Open 之前完成此動作。 在此範例中,我們會示範如何在呼叫 Open之前手動修改格式器。 達成相同目的的另一種方法是定義類別來繼承 ServiceHost,並在開啟之前進行對 EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior 的呼叫(如需範例,請參閱主控檔和範例)。

用戶體驗

在伺服器上:

  • 伺服器 ICalculator 實作不需要變更。

  • 服務 App.config 必須使用自訂 POX 系結,將 messageVersion 元素的 textMessageEncoding 屬性設定為 None

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    
  • 服務的 App.config 也必須指定自定義元素 EnableHttpGetRequestsBehavior,將其新增至行為延伸模組區段並加以使用。

    <behaviors>
      <endpointBehaviors>
        <behavior name="enableHttpGetRequestsBehavior">
          <enableHttpGetRequests />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    
    <extensions>
      <behaviorExtensions>
        <!-- Enabling HTTP GET requests: Behavior Extension -->
        <add
          name="enableHttpGetRequests"           type="Microsoft.ServiceModel.Samples.EnableHttpGetRequestsBehaviorElement, QueryStringFormatter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
    
  • 在呼叫 Open之前新增作業格式子。

在用戶端上:

  • 用戶端實作不需要變更。

  • 用戶端的 App.config 必須使用自訂 POX 系結,將messageVersion元素的textMessageEncoding屬性設定為None。 與服務不同的是,客戶端必須啟用手動尋址,以便能夠修改傳出郵件的收件者位址。

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport manualAddressing="True" />
        </binding>
      </customBinding>
    </bindings>
    
  • 用戶端的 App.config 必須指定與伺服器相同的自定義 EnableHttpGetRequestsBehavior

  • 在呼叫 CreateChannel()之前新增作業格式子。

當您執行範例時,作業要求和回應會顯示在用戶端控制台視窗中。 這四個作業(加、減、乘和除)都必須成功。

要設定、建置和執行範例,請執行以下步驟:
  1. 請確定您已針對 Windows Communication Foundation 範例 執行One-Time 安裝程式。

  2. 若要建置解決方案,請遵循 建置 Windows Communication Foundation 範例中的指示。

  3. 若要在單一或跨計算機組態中執行範例,請遵循執行 Windows Communication Foundation 範例 中的指示。