若要實作內容型路由,路由服務會使用 MessageFilter 實作來檢查訊息的特定區段,例如位址、端點名稱或特定 XPath 語句。 如果 .NET Framework 4.6.1 所提供的訊息篩選器都不符合您的需求,您可以建立基 MessageFilter 類的新實作來建立自定義篩選。
設定路由服務時,您必須定義描述 FilterElement 類型的篩選元素(objects),以及建立篩選所需的任何支持數據,例如要搜尋訊息內的特定字串值。 請注意,建立篩選元素只會定義個別訊息篩選;若要使用篩選條件來評估和路由訊息,您也必須定義篩選數據表 (FilterTableEntryCollection)。
篩選表格中的每個項目都會參照篩選元素,並指定當訊息符合篩選條件時,被路由到的用戶端端點。 篩選數據表專案也可讓您指定備份端點的集合 (BackupEndpointCollection),其會定義訊息清單,當傳送至主要端點時傳輸失敗時,訊息將會傳送至該端點。 這些端點會依照指定的順序嘗試,直到成功為止。
訊息篩選
路由服務所使用的訊息篩選會提供常見的訊息選取功能,例如評估訊息傳送至的端點名稱、SOAP 動作,或訊息傳送至的位址或地址前綴。 篩選條件也可以與 AND 條件結合,只有當訊息同時符合這兩個篩選條件時,才會將訊息路由到終端節點。 您也可以藉由建立自己的 實作 MessageFilter來建立自定義篩選。
下表列出 FilterType 路由服務所使用的、實作特定訊息篩選的類別,以及必要的 FilterData 參數。
| 篩選器類型 | 說明 | 篩選數據意義 | 範例篩選 |
|---|---|---|---|
| 行動 | 使用類別 ActionMessageFilter 來比對包含特定動作的訊息。 | 要篩選的動作。 | <filter name="action1" filterType="Action" filterData="http://namespace/contract/operation" /> |
| 端點地址 | 使用 類別 EndpointAddressMessageFilter ,搭配 IncludeHostNameInComparison == true 來比對包含特定位址的訊息。 |
要篩選的位址(在 To 標頭中)。 | <filter name="address1" filterType="EndpointAddress" filterData="http://host/vdir/s.svc/b" /> |
| 端點地址前綴 | 使用 類別 PrefixEndpointAddressMessageFilter ,搭配 IncludeHostNameInComparison == true 來比對包含特定位址前置詞的訊息。 |
使用最長前置碼匹配進行篩選的地址。 | <filter name="prefix1" filterType="EndpointAddressPrefix" filterData="http://host/" /> |
| 和 | 使用 StrictAndMessageFilter 類別來評估這兩個條件,然後傳回結果。 | 未使用 filterData;改為 filter1 和 filter2 擁有對應消息過濾器的名稱(也在表格中),這些名稱應該要以 AND 的方式結合。 | <filter name="and1" filterType="And" filter1="address1" filter2="action1" /> |
| 習慣 | 擴充 MessageFilter 類別並具有接受字串的建構函式的使用者定義型別。 | customType 屬性是要建立之類別的完整類型名稱;filterData 是建立篩選時要傳遞至建構函式的字串。 | <filter name="custom1" filterType="Custom" customType="CustomAssembly.CustomMsgFilter, CustomAssembly" filterData="Custom Data" /> |
| 端點名稱 | 使用 類別 EndpointNameMessageFilter ,根據抵達的服務端點名稱比對訊息。 | 服務端點的名稱,例如:「serviceEndpoint1」。 這應該是路由服務上公開的其中一個端點。 | <filter name="stock1" filterType="Endpoint" filterData="SvcEndpoint" /> |
| MatchAll | 使用類別 MatchAllMessageFilter 。 此篩選器會匹配所有抵達的訊息。 | filterData 未被使用。 此過濾器將始終匹配所有訊息。 | <filter name="matchAll1" filterType="MatchAll" /> |
| XPath | 使用 類別 XPathMessageFilter 來比對訊息內的特定 XPath 查詢。 | 比對訊息時要使用的 XPath 查詢。 | <filter name="XPath1" filterType="XPath" filterData="//ns:element" /> |
下列範例定義了使用 XPath、EndpointName 和 PrefixEndpointAddress 訊息篩選器的篩選條目。 此範例也會示範如何使用 RoundRobinFilter1 和 RoundRobinFilter2 專案的自定義篩選。
<filters>
<filter name="XPathFilter" filterType="XPath"
filterData="/s12:Envelope/s12:Header/custom:RoundingCalculator = 1"/>
<filter name="EndpointNameFilter" filterType="EndpointName"
filterData="calculatorEndpoint"/>
<filter name="PrefixAddressFilter" filterType="PrefixEndpointAddress"
filterData="http://localhost/routingservice/router/rounding/"/>
<filter name="RoundRobinFilter1" filterType="Custom"
customType="RoutingServiceFilters.RoundRobinMessageFilter,
RoutingService" filterData="group1"/>
<filter name="RoundRobinFilter2" filterType="Custom"
customType="RoutingServiceFilters.RoundRobinMessageFilter,
RoutingService" filterData="group1"/>
</filters>
備註
僅僅定義篩選並不會導致訊息被篩選條件評估。 篩選條件必須新增至篩選數據表,然後與路由服務公開的服務端點相關聯。
命名空間數據表
使用 XPath 篩選時,包含 XPath 查詢的篩選數據可能會因為命名空間的使用而變得非常大。 為了減輕這個問題,路由服務提供使用命名空間數據表來定義您自己的命名空間前置詞的能力。
命名空間數據表是 物件的集合 NamespaceElement ,定義可用於 XPath 之通用命名空間的命名空間前置詞。 以下是命名空間數據表中包含的預設命名空間和命名空間前置詞。
| 前綴 | Namespace |
|---|---|
| s11 | http://schemas.xmlsoap.org/soap/envelope |
| s12 | http://www.w3.org/2003/05/soap-envelope |
| wsaAugust2004 | http://schemas.xmlsoap.org/ws/2004/08/addressing |
| wsa10 | http://www.w3.org/2005/08/addressing |
| sm | http://schemas.microsoft.com/serviceModel/2004/05/xpathfunctions |
| tempuri | http://tempuri.org |
| 爵士 | http://schemas.microsoft.com/2003/10/Serialization |
當您知道將在 XPath 查詢中使用特定命名空間時,您可以將它新增至命名空間數據表以及唯一的命名空間前置詞,並在任何 XPath 查詢中使用前置詞,而不是完整命名空間。 下列範例會定義 命名空間 "http://my.custom.namespace"的 「custom」 前置詞,然後用於 filterData 中包含的 XPath 查詢中。
<namespaceTable>
<add prefix="custom" namespace="http://my.custom.namespace/"/>
</namespaceTable>
<filters>
<filter name="XPathFilter" filterType="XPath" filterData="/s12:Envelope/s12:Header/custom:RoundingCalculator = 1"/>
</filters>
篩選數據表
雖然每個篩選元素都會定義可套用至訊息的邏輯比較,但篩選數據表會提供篩選專案與目的地用戶端端點之間的關聯。 篩選數據表是 物件的具名集合 FilterTableEntryElement ,可定義篩選條件、主要目的地端點和替代備份端點清單之間的關聯。 篩選數據表專案也可讓您為每個篩選條件指定選擇性優先順序。 下列範例會定義兩個篩選,然後定義一個篩選數據表,讓每個篩選條件與目的地端點產生關聯。
<routing>
<filters>
<filter name="AddAction" filterType="Action" filterData="Add" />
<filter name="SubtractAction" filterType="Action" filterData="Subtract" />
</filters>
<filterTables>
<table name="routingTable1">
<filters>
<add filterName="AddAction" endpointName="Addition" />
<add filterName="SubtractAction" endpointName="Subtraction" />
</filters>
</table>
</filterTables>
</routing>
篩選評估優先順序
根據預設,篩選數據表中的所有專案都會同時評估,而所評估的訊息會路由傳送至與每個相符篩選專案相關聯的端點。 如果多個篩選器的評估結果為 true,而且訊息是單向或雙向的,則訊息會被多點傳送至所有符合篩選條件的端點。 要求-回復訊息不能進行多播,因為只能有一個回復傳回給客戶端。
您可以指定每個篩選的優先順序級,以實作更複雜的路由邏輯;路由服務會先評估優先順序最高的所有篩選。 如果訊息符合此層級的篩選條件,則不會處理優先順序較低的篩選。 例如,傳入的單向訊息會先針對優先順序為 2 的所有篩選進行評估。 此訊息不符合此優先順序層級的任何篩選,因此接下來會將訊息與優先順序為1的篩選進行比較。 兩個優先順序 1 篩選條件符合訊息,而且因為它是單向訊息,因此它會路由傳送至這兩個目的地端點。 由於在優先級 1 的篩選條件中找到符合條件,因此不會評估優先級 0 的篩選條件。
備註
如果未指定優先順序,則會使用預設優先順序 0。
下列範例會定義篩選數據表,指定數據表中所參考篩選條件的優先順序為 2、1 和 0。
<filterTables>
<filterTable name="filterTable1">
<add filterName="XPathFilter" endpointName="roundingCalcEndpoint"
priority="2"/>
<add filterName="EndpointNameFilter" endpointName="regularCalcEndpoint"
priority="1"/>
<add filterName="PrefixAddressFilter" endpointName="roundingCalcEndpoint"
priority="1"/>
<add filterName="MatchAllMessageFilter" endpointName="defaultCalcEndpoint"
priority="0"/>
</filterTable>
</filterTables>
在上述範例中,如果訊息符合 XPathFilter,則會路由傳送至 roundingCalcEndpoint,而且不會評估數據表中的進一步篩選,因為所有其他篩選條件的優先順序較低。 不過,如果訊息不符合 XPathFilter,則會針對下一個較低優先順序、EndpointNameFilter 和 PrefixAddressFilter 的所有篩選進行評估。
備註
可能的話,請使用獨佔篩選,而不是指定優先順序,因為優先順序評估可能會導致效能降低。
備份清單
篩選數據表中的每個篩選都可以選擇性地指定備份清單,這是端點的具名集合 (BackupEndpointCollection)。 這個集合包含一份已排序的端點清單,當傳送至CommunicationException中指定的主要端點時發生EndpointName,訊息將會傳送至這些端點。 下列範例會定義名為 「backupServiceEndpoints」 的備份清單,其中包含兩個端點。
<filterTables>
<filterTable name="filterTable1">
<add filterName="MatchAllFilter1" endpointName="Destination" backupList="backupEndpointList"/>
</filterTable>
</filterTables>
<backupLists>
<backupList name="backupEndpointList">
<add endpointName="backupServiceQueue" />
<add endpointName="alternateServiceQueue" />
</backupList>
</backupLists>
在上述範例中,如果傳送至主要端點「目的地」失敗,路由服務會嘗試依列出的順序傳送至每個端點,先傳送至backupServiceQueue,然後在傳送至backupServiceQueue 失敗時傳送至 alternateServiceQueue。 如果所有備份端點都失敗,則會傳回錯誤。