訓練
QueryStringFormatter 範例示範如何使用 Windows Communication Foundation (WCF) 擴充點,以不同於 WCF 預期的格式允許訊息資料。 根據預設,WCF 格式器預期方法參數包含在soap:body
項目中。 此範例會示範如何實作自訂作業格式器,而這個作業格式器會剖析 HTTP GET 查詢字串中的參數資料,然後使用該資料叫用方法。
此範例是以實作ICalculator
服務合約的使用者入門為基礎。 它會示範如何將 Add、Subtract、Multiply 和 Divide 訊息變更為針對用戶端對伺服器的要求使用 HTTP GET,以及針對伺服器對用戶端的回應使用具有 POX 訊息的 HTTP POST。
為了此示範,範例提供下列各項:
QueryStringFormatter
,會分別對用戶端和伺服器實作 IClientMessageFormatter 和 IDispatchMessageFormatter,並處理查詢字串中的資料。UriOperationSelector
,會在伺服器上實作 IDispatchOperationSelector,以根據 GET 要求中的作業名稱執行作業分派。EnableHttpGetRequestsBehavior
端點行為 (以及對應的組態),會將必要的作業選取器加入至執行階段。示範如何將新作業格式器插入至執行階段。
在這個範例中,用戶端和服務都是主控台應用程式 (.exe)。
注意
此範例的安裝程序與建置指示位於本主題的結尾。
QueryStringFormatter
- 作業格式器是 WCF 中的元件,負責將訊息轉換為參數物件的陣列,以及將參數物件的陣列轉換為訊息。 此轉換是透過用戶端上的 IClientMessageFormatter 介面和伺服器上的 IDispatchMessageFormatter 介面來完成。 這些介面都可讓使用者從 Serialize
和 Deserialize
方法中取得要求和回應訊息。
在這個範例中,QueryStringFormatter
會實作這兩個介面,並且在用戶端和伺服器上實作。
要求:
此範例會使用 TypeConverter 類別,將要求訊息中的參數資料與字串互相轉換。 如果特定型別無法使用 TypeConverter,則範例格式器會擲回例外狀況。
在用戶端的
IClientMessageFormatter.SerializeRequest
方法中,格式器會使用適當的收件者地址來建立 URI,並將作業名稱附加為後置字元。 這個名稱會分派至伺服器上的適當作業。 接著會採用參數物件的陣列,並使用 TypeConverter 類別轉換的參數名稱和值,將參數資料序列化為 URI 查詢字串。 然後會將 To 和 Via 屬性設定為這個 URI。 MessageProperties 是透過 Properties 屬性來存取。在伺服器的
IDispatchMessageFormatter.DeserializeRequest
方法中,格式器會在傳入要求訊息屬性中擷取Via
URI。 這個格式器會將 URI 查詢字串中的名稱/值組剖析為參數名稱和值,並使用參數名稱和值填入 (Populate) 傳遞至方法的參數陣列。 請注意,已進行作業分派,因此這個方法會忽略作業名稱後置字元。
回應:
- 在這個範例中,HTTP GET 只能用於要求。 格式器會將傳送回應的職責委派給原始格式器,但已使用原始格式器來產生 XML 訊息。 這個範例的其中一個目標就是告訴您如何實作此種委派格式器。
IDispatchOperationSelector 介面可讓使用者實作自己的邏輯,而這是特定訊息應該分派的作業。
在這個範例中,由於作業名稱是包含在 HTTP GET URI,而非訊息的動作標頭中,因此必須在伺服器上實作 UriPathSuffixOperationSelector
才能選取適當的作業。 會將範例設定為僅允許不會區分大小寫的作業名稱。
SelectOperation
方法接著採用傳入訊息,並在其訊息屬性中查詢 Via
URI。 該方法會從 URI 中擷取作業名稱後置字元、查閱內部表格以取得應將訊息分派至的作業名稱,然後傳回該作業名稱。
您可以透過程式設計的方法或端點行為來設定 UriPathSuffixOperationSelector
元件。 此範例會實作EnableHttpGetRequestsBehavior
行為,而這個行為是由服務的應用程式組態檔中所指定。
在伺服器上:
將 OperationSelector 設定為 IDispatchOperationSelector 實作。
根據預設,WCF 會使用完全符合的位址篩選條件。 傳入訊息上的 URI 包含作業名稱後置字元,後面跟著包含參數資料的查詢字串,因此端點行為也會將位址篩選條件變更為開頭相符的篩選條件。 為了這個目的,會使用 WCFPrefixEndpointAddressMessageFilter。
指定格式器的作業行為都是獨一無二。 預設一定會對每個作業實作一個這樣的行為,以建立所需的作業格式器。 不過,這些行為看起來就像其他作業行為,其他屬性無法識別這些行為。 若要安裝取代行為,實作必須尋找預設由 WCF 型別載入器安裝的特定格式器行為,並在預設行為之後取代該行為或新增相容的行為。
在呼叫 CommunicationObject.Open 之前,可以透過程式設計方式設定這些作業格式器行為,或在預設行為之後指定要執行的作業行為來設定。 不過,無法輕易地透過端點行為 (以及組態) 來設定作業格式器行為,因為行為模型不允許取代其他行為,否則會修改描述樹狀。
在用戶端上:
必須實作 IClientMessageFormatter 實作,因此可將要求轉換為 HTTP GET 要求,並針對回應委派至原始格式器。 呼叫 EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior
Helper 方法即可完成此動作。
這個動作必須在呼叫 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
Helper 方法以做為用戶端 (請參閱先前的程式碼範例),即可完成此動作。這個動作必須在呼叫 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() 之前新增作業格式器。
當您執行範例時,作業要求和回應會顯示在用戶端主控台視窗中。 這四個作業 (Add、Subtract、Multiply 和 Divide) 都必須成功。
若要建置解決方案,請依照建置 Windows Communication Foundation 範例中的指示操作。
若要在單一或多部電腦組態中執行此範例,請遵循執行 Windows Communication Foundation 範例中的指示進行。