總結WCF中截獲消息的幾種方式(二)
上文中談到了WCF截獲消息有四種方式1) 路由法 2) 自定義綁定法 3)實現接口法 4) 跟蹤診斷法,上篇文章總結WCF中截獲消息的幾種方式詳細的闡述了前面兩種,本文著重闡述后面兩種實現方式
3. 接口實現法
WCF已經考慮到了開發人員想通過自定義代碼截獲消息的需求,在WCF中,Binding,Contract,Address是構成了EndPoint,他們是Infrastructure.而Channel是Communication的最關鍵部分,而Behavior則是充分體現WCF擴展靈活性的一個點,如果將上面的Endpoint與Channel是樹干,那么Behavior就是樹枝。樹干組成了參天大樹,而樹枝則是對樹干的點綴。如果想成為一個健壯的大樹,樹干必不可少,而樹葉可多可少,可有可無,但樹葉能影響整個大樹的外觀特征。在WCF中自定義了三種Behavior,他們分別是:
IEndpointBehavior
IServiceBehavior
IOperationBehavior
三種Behavior作用對象分別是:Endpoint,Service,Operation.下面看下IEndpointBehavior的定義
public interface IEndpointBehavior { // Methods void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection
bindingParameters); void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime); void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher); void Validate(ServiceEndpoint endpoint); }
本文中注重討論ApplyClientBehavior和ApplyDispatchBehavior,其中ApplyClientBehavior是用于應用客戶端的行為,而ApplyDispatchBehavior用于服務端行為。在ApplyClientBehavior方法中的參數ClientRuntime是擴展客戶端的最重要的類,他是WCF框架提供給開發人員插入擴展客戶端處理消息功能的插入點。ClientRuntime類中有一個MessageInspectors屬性成員,它是客戶端消息檢查器的集合,WCF為客戶端消息檢查器提供了標準接口:IClientMessageInspector,它的定義是:
public interface IClientMessageInspector { // Methods void AfterReceiveReply(ref Message reply, object correlationState); object BeforeSendRequest(ref Message request, IClientChannel channel); }
在消息交互過程中,客戶端和服務端交互的過程如下圖所示:
從上圖中我們可以看出,消息在客戶端有兩種:1)在發送消息之前 2) 接收到消息之后 這兩個分別對應
IClientMessageInspector的兩個接口方法BeforeSendRequest AfterReceiveReply。
在ApplyDispatchBehavior的方法中的參數EndpointDispatcher中有一個屬性:DispatchRuntime和
ClientRuntime相對應,它也有一個MessageInspectors屬性,它是服務端消息檢查器的集合,WCF為服務端消息檢查器
提供了一個標準接口:IDispatchMessageInspector,他的定義是:
public interface IDispatchMessageInspector { // Methods object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext
instanceContext); void BeforeSendReply(ref Message reply, object correlationState); }
它的兩個方法對應這上圖中服務中的兩種消息,一種是接收請求后,另外一種是發送響應前。
通過實現IClientMessageInspector IDispatchMessageInspector 這兩個接口,就能實現客戶端和服務端的消息攔截
器,再通過實現自定義的Behavior,然后將自定義的Behavior添加到相應的行為限制對象上,如Endpoint,Service,
Operation上就能實現對消息的攔截。做了個demo,想查看詳細代碼的可以下載。
這里只給出最后的運行效果圖:
服務端:
客戶端:
采用這種方法的優點是:
1) 能適用于各種場合,比如使用諸如 HTTPS 的安全傳輸時。
缺點是實現比較復雜,且不能跟蹤傳輸級別的消息
4. 跟蹤診斷法
WCF本身也提供了管理診斷功能,由于種種原因,我們可能在設計時可能沒有想到記錄消息的需求,而在實際運維的時候卻出
現這樣的需求,因為有些問題issue的解決需要查看消息內容才能更容易的診斷。WCF也提供了缺省的功能用于滿足上述需求
默認情況系,WCF不記錄Message,但可以通過配置config,能實現消息記錄,主要是通過
System.ServiceModel.MessageLogging。下面的代碼既可以增加消息記錄功能
<system.diagnostics> <sources> <source name="System.ServiceModel.MessageLogging"> <listeners> <add name="messages" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\logs\messages.svclog" /> </listeners> </source> </sources> </system.diagnostics> <system.serviceModel> <diagnostics> <messageLogging logEntireMessage="true" logMalformedMessages="false" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" maxMessagesToLog="3000" maxSizeOfMessageToLog="2000"/> </diagnostics> </system.serviceModel>
簡要的介紹一下上面的代碼,System.Diagnostics.XmlWriterTraceListener是.net表轉的跟蹤偵聽器,使用它,必須
通過指定initializeData來設置記錄的消息保存的文件地址。
在WCF中消息記錄是分級別的,基本劃分為:”服務“級別,”傳輸“級別,”格式不正確“級別。有關這三個級別,msdn
有詳細的描述,我就不再贅述。
通過此種方法,還可以通過添加消息篩選器,實現對部分的消息內容進行記錄,下面的代碼
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="420"> <filters> <add nodeQuota="10" xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> /soap:Envelope/soap:Header </add> </filters> </messageLogging>
這段代碼便是指定了只記錄消息標頭,這些個內容,msdn上都有,不多說了。
也做了一個診斷跟蹤的示例,執行后在c盤下能找到一個messages.txt的文件。內容是:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent%22><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system%22><EventID>0</EventID><Type>3</Type><SubType Name="Information">0</SubType><Level>8</Level><TimeCreated SystemTime="2008-10-25T14:46:58.1093176Z" /><Source Name="System.ServiceModel.MessageLogging" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="Jillzhang.Wcf.MessageInspectors.Trace.Host.vshost" ProcessID="4556" ThreadID="11" /><Channel/><Computer>WIN-QMIXGNBHWPE</Computer></System><ApplicationData><TraceData><DataItem><MessageLogTraceRecord Time="2008-10-25T22:46:58.1043176+08:00" Source="ServiceLevelReceiveRequest" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace%22><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope%22 xmlns:a="http://www.w3.org/2005/08/addressing%22><s:Header><a:Action s:mustUnderstand="1">http://tempuri.org/ICalculator/Add</a:Action><a:MessageID>urn:uuid:1ef15f49-6e38-46d3-b906-d8ed78564c89</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink%22>uIDPo8masvhLEkZBvyYJpVFd168AAAAAgVozn8DAXkaGix0+tb393XpBqSmzHQxOuVyNwKQn8egACQAA</VsDebuggerCausalityData><a:To s:mustUnderstand="1">net.tcp://127.0.0.1:8023/Calculator</a:To></s:Header><s:Body><Add xmlns="http://tempuri.org/%22><a>1</a><b>2</b></Add></s:Body></s:Envelope></MessageLogTraceRecord></DataItem></TraceData></ApplicationData></E2ETraceEvent><E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent%22><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system%22><EventID>0</EventID><Type>3</Type><SubType Name="Information">0</SubType><Level>8</Level><TimeCreated SystemTime="2008-10-25T14:46:58.1293176Z" /><Source Name="System.ServiceModel.MessageLogging" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="Jillzhang.Wcf.MessageInspectors.Trace.Host.vshost" ProcessID="4556" ThreadID="11" /><Channel/><Computer>WIN-QMIXGNBHWPE</Computer></System><ApplicationData><TraceData><DataItem><MessageLogTraceRecord Time="2008-10-25T22:46:58.1293176+08:00" Source="ServiceLevelSendReply" Type="System.ServiceModel.Channels.BodyWriterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace%22><s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing%22 xmlns:s="http://www.w3.org/2003/05/soap-envelope%22><s:Header><a:Action s:mustUnderstand="1">http://tempuri.org/ICalculator/AddResponse</a:Action></s:Header><s:Body><AddResponse xmlns="http://tempuri.org/%22><AddResult>3</AddResult></AddResponse></s:Body></s:Envelope></MessageLogTraceRecord></DataItem></TraceData></ApplicationData></E2ETraceEvent>
診斷跟蹤的方式非常靈活,且獲取的消息也非常詳細,非常適用于生產環境。同時支持自定義診斷跟蹤器。推薦使用
完整的dmeo示例:https://files.cnblogs.com/jillzhang/Jillzhang.Wcf.MessageInspector2.rar
出處:http://jillzhang.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

上文中談到了WCF截獲消息有四種方式1) 路由法 2) 自定義綁定法 3)實現接口法 4) 跟蹤診斷法,上篇文章總結WCF中截獲消息的幾種方式詳細的闡述了前面兩種,本文著重闡述后面兩種實現方式
浙公網安備 33010602011771號