完全な要求と応答の本文を含むサービス参照に送信されるすべての送信要求をログに記録しようとしています。私は、behaviorExtensionsを使って解決策があると思っていましたが、展開した後、拡張が複数の要求間で共有されていることが明らかになりました。IEndpointBehaviorライフサイクル/ロギングサービスの呼び出し
はここに私の現在のコードです:私は、ログに記録するポイントに到達したとき、私は行動を抽出し、その後
public class LoggingBehaviorExtender : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(LoggingRequestExtender);
protected override object CreateBehavior() { return new LoggingRequestExtender(); }
}
public class LoggingRequestExtender : IClientMessageInspector, IEndpointBehavior
{
public string Request { get; private set; }
public string Response { get; private set; }
#region IClientMessageInspector
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
Request = request.ToString();
Response = null;
return null;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Response = reply.ToString();
}
#endregion
#region IEndpointBehavior
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
#endregion
}
... LoggingRequestExtenderにデバッグログを追加
var lre = client.Endpoint.Behaviors.OfType<LoggingRequestExtender>().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;
は、私はそれを見つけました複数の要求に対して一度しかインスタンス化されませんでした。
この動作クラスがスレッドごとに新しくインスタンス化されることを確認する方法はありますか?あるいは、サービスコールを行うときに、完全なリクエスト/レスポンスボディを得るためのより良い方法がありますか?
編集/部分の答え:
これを書いて以来、私は、GUIDを使用して、要求と応答を接続できるようにBeforeSendRequestによって返された値がcorrelationStateとしてAfterReceiveReplyに渡されることを発見した:
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
var guid = Guid.NewGuid();
WebServiceLog.LogCallStart(guid, channel.RemoteAddress.ToString(), request.ToString());
return guid;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Guid guid = (Guid)correlationState;
WebServiceLog.LogCallEnd(guid, reply.ToString());
}
このアプローチには2つの欠陥があります。これは、ログインサートを必要とし、1つのインサートではなく更新することです。
例外が発生した場合(タイムアウトなど)、AfterRecieveSupplyには一度も当たっていないので、ログには何が起こったのか分からない。私は、サービス要求のログに例外ログを結びつけることは何もない私は別に...
try
{
response = client.SomeFunction(request);
}
catch (Exception ex)
{
AppLog.Error("Some function failed", ex);
}
を例外をログに記録することができます...しかし、私はBeforeSendRequest/AfterReceiveReplyの外でGUIDをアクセスする方法を見ることができません。