2012-04-20 80 views
10

我有一個使用多種方法的WCF服務。我想記錄來自客戶端的原始請求,而不管它是如何發送的。一種方法接受數據作爲查詢字符串(嚴格的傳統支持),我可以使用日誌:如何在WCF服務中記錄原始請求

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri 

足以在該方案中,但其他方法允許客戶端使用生成的代理類來發送數據作爲XML由svcutil.exe。在這種情況下,我發現我希望在S中的數據:主體:

OperationContext.Current.RequestContext.RequestMessage 

不幸的是,無論我怎麼努力讀之前,我無法創建消息的緩衝副本。這裏有一個例子:

public CascadeResponse SendCustomer(Customer c) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest 
    } 

在SendCustomer的第一線,不過,我得到以下錯誤:

,因爲它已經被閱讀了此消息不支持操作。

這是我創造緩衝副本的重點,當然?我猜測我在這裏做了一些根本性錯誤。

編輯:

好了,所以該方法現在是這樣的:

public CascadeResponse SendCustomer(Message requestMessage) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest   
     Customer c = msg.GetBody<Customer>(); 
     string clientKey = "1111"; // This should be the clientKey string passed to the function along with the customer 
     return SendLead(c, clientKey); 
    } 

我的問題是,我不知道如何讓客戶和ClientKey派作爲獨立的實體。我可以讓clientKey成爲Customer的一個屬性(或者創建一個專門用於傳遞數據的自定義對象,並且包含Customer和ClientKey作爲屬性),但是如果可能的話,我想避免這種情況,因爲這是一個遺留系統的升級,已經以這種方式工作。

我也有麻煩使用svcUtil.exe來創建我的代理類 - 我假設有上述方法簽名意味着我的服務將不再公佈正確的簽名發送請求爲?不確定是否足夠清楚 - 如果我的唯一輸入法接受一個Message對象,我的客戶如何知道發送一個Customer和一個ClientKey?

+0

你爲什麼不能在WCF中使用內置跟蹤功能的任何原因? http://msdn.microsoft.com/en-us/library/ms733025.aspx – DaveRead 2012-04-20 15:40:06

+0

@DaveRead主要是我不知道它 - 這是否允許我將我的日誌保存到數據庫? – Maloric 2012-04-23 10:18:15

+0

不是開箱即用,但您可以創建自己的自定義TraceListener,請參閱此文章的詳細信息:http://msdn.microsoft.com/en-gb/magazine/cc300790.aspx – DaveRead 2012-04-23 12:04:22

回答

19

我發現了一個解決方案,人也可能會覺得有用。創建MessageInspector允許您附加代碼爲「AfterReceiveRequest」和「BeforeSendReply」事件,按以下操作:

public class MessageInspector : IDispatchMessageInspector 
{ 
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); 
     request = buffer.CreateMessage(); 
     LogMessage("Received:\n{0}", buffer.CreateMessage().ToString()); 
     return null; 
    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue); 
     reply = buffer.CreateMessage(); 
     LogMessage("Sending:\n{0}", buffer.CreateMessage().ToString()); 
    } 
} 

有一個full tutorial for setting up message inspectors fo wcf here。在將行爲擴展添加到app.config/web.config時,我會說要小心檢查完全限定的程序集名稱。

希望別人認爲這有用。

2

爲了讓您實現上述需要改變你的方法,如下圖所示:

public CascadeResponse SendCustomer(Message requestMessage) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest   
     Customer c = msg.GetBody<Customer>(); 
    } 

更多有關Using Message Class

+0

謝謝,這讓我走上正軌,但我得到了一堆使用svcutil.exe創建所需的代理類時出錯。 '不能導入WSDL:binding' '不能導入WSDL:binding' ...等等 另外,我不知道如何檢索請求主體的其他對象(我的例子僅包含一個對象,但實際的代碼有一個額外的字符串標識客戶端)。 週一我會再看看,但感謝您的幫助。 – Maloric 2012-04-20 16:58:21

2

我認爲你可以使用...ToString()方法和它所要做的是重寫內部消息:

string soap = OperationContext.Current.RequestContext.RequestMessage.ToString(); 

ToString()方法...裏面;)

0

在VS2015上的WCF服務項目,你可以在網頁右鍵點擊.config來編輯WCF配置。從這裏您可以啓用診斷來獲取記錄的原始消息。

+0

你能否詳細說明這一點,並指定確切的方式和設置?簡單地做出這樣的陳述是不夠的。 – 2017-02-08 21:00:45