このブログ投稿DelegatingHandler
の詳細を使用して、リクエスト ログを作成しました。
リクエストまたはレスポンスの本文を読みたくない (この作業を 2 倍にするのは、潜在的に大量の Web サービスではばかげているように思われる)。やりたいことは、各リクエストに一意の ID を割り当て、URI とヘッダーをログに記録することだけです。別のヘッダーの応答に要求 ID を書き込み、応答 (成功/失敗) と発生した例外をログに記録します。
protected override System.Threading.Tasks.Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request,
System.Threading.CancellationToken cancellationToken)
{
DateTime receivedUTC = DateTime.UtcNow;
//I use the Request properties to persist a Request's ID
var requestID = request.GetRequestUID();
if (requestID == null)
requestID = request.SetRequestUID();
//grab the base response task
var baseResult = base.SendAsync(request, cancellationToken);
return baseResult.ContinueWith(innerTask =>
{
var tcs = new TaskCompletionSource<HttpResponseMessage>();
//note I've got rid of SynchronizationContext code out of this
//to keep it shorter
//construct the log packet
LogData toLog = new LogData()
{
ReceivedUTC = receivedUTC,
Request = request,
RequestID = requestID,
};
//get the response
try
{
tcs.SetResult(innerTask.Result);
//NOTE - If this request actually fails response serialization,
// Then the above result will actually look fine, because
// The error hasn't occurred yet!
toLog.Response = innerTask.Result;
//this adds a header
AddRequestIDToResponse(toLog.Response, requestID);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
toLog.Ex = ex;
}
//fire the logging call asynchronously (code elided, just some DB work)
Task.Factory.StartNew(() => Log(toLog));
return tcs.Task;
}).Unwrap();
}
ObjectContent
これは、アクションメソッドから返されたものが応答にシリアル化される 間に例外が発生した場合を除いて、ほぼすべての要求に対して完全に正常に機能します。
これが発生した場合、上記のコードは既に実行されており、上記の try/catch ブロックに表示される応答メッセージは、最終的にシリアル化に失敗するオブジェクトを含む200
通常のメッセージとして表示されます。ObjectContent
応答本文へのシリアル化がまだ行われていないため、これは理にかなっています。
コンテンツのフォーマットが行われた後に表示される応答メッセージが、クライアントが受け取る実際のObjectContent
メッセージであることを確認するには、このコードをどのように変更すればよいでしょうか? 別の拡張ポイントを見る必要がありますか?