Skip to content

Instantly share code, notes, and snippets.

@mrshridhara
Created July 7, 2014 13:44
Show Gist options
  • Save mrshridhara/0f6a4ed1277dbc467f75 to your computer and use it in GitHub Desktop.
Save mrshridhara/0f6a4ed1277dbc467f75 to your computer and use it in GitHub Desktop.
DelegatingHandler to log request and response of a Web API call.
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// </summary>
public class MessageLoggingHandler : DelegatingHandler
{
/// <summary>
/// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
/// </summary>
/// <param name="request">The HTTP request message to send to the server.</param>
/// <param name="cancellationToken">A cancellation token to cancel operation.</param>
/// <returns>
/// Returns <see cref="T:System.Threading.Tasks.Task`1"/>. The task object representing the asynchronous operation.
/// </returns>
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Record the start time.
var startTime = DateTime.Now;
// Execute the request, this does not block.
var response = base.SendAsync(request, cancellationToken);
// Once the response is processed asynchronously, log the data.
response.ContinueWith(responseMessage => LogData(startTime, DateTime.Now, request, responseMessage.Result, responseMessage.Exception));
return response;
}
private static void LogData(DateTime startTime, DateTime endTime, HttpRequestMessage request, HttpResponseMessage response, Exception exception)
{
// Is this Web API call?
if (request.RequestUri.AbsoluteUri.Contains("/api/") == false)
{
// Return without doing anything.
return;
}
var loggingInfo = new LoggingInfo { StartTime = startTime, EndTime = endTime, Url = request.RequestUri.AbsoluteUri };
request
.Content
.ReadAsByteArrayAsync()
.ContinueWith(requestContentTask => { loggingInfo.Request = Encoding.UTF8.GetString(requestContentTask.Result); })
.ContinueWith
(
requestContentTask =>
{
if (exception == null)
{
response
.Content
.ReadAsByteArrayAsync()
.ContinueWith(responseContentTask => { loggingInfo.Response = Encoding.UTF8.GetString(responseContentTask.Result); })
.ContinueWith(responseContentTask => LogData(loggingInfo));
}
else
{
loggingInfo.Exception = exception;
LogData(loggingInfo);
}
}
);
}
private static void LogData(LoggingInfo loggingInfo)
{
// Log data to appropriate storage.
}
/// <summary>
/// </summary>
public class LoggingInfo
{
/// <summary>
/// Gets or sets the request.
/// </summary>
/// <value>
/// The request.
/// </value>
public string Request { get; set; }
/// <summary>
/// Gets or sets the response.
/// </summary>
/// <value>
/// The response.
/// </value>
public string Response { get; set; }
/// <summary>
/// Gets or sets the end time.
/// </summary>
/// <value>
/// The end time.
/// </value>
public DateTime EndTime { get; set; }
/// <summary>
/// Gets or sets the start time.
/// </summary>
/// <value>
/// The start time.
/// </value>
public DateTime StartTime { get; set; }
/// <summary>
/// Gets or sets the exception.
/// </summary>
/// <value>
/// The exception.
/// </value>
public Exception Exception { get; set; }
/// <summary>
/// Gets or sets the URL.
/// </summary>
/// <value>
/// The URL.
/// </value>
public string Url { get; set; }
}
}
@Zabaa
Copy link

Zabaa commented Aug 29, 2017

Hi, thanks for cool gist. But I've got this exception in my example ReadAsByteArrayAsync()' threw an exception of type 'System.ObjectDisposedException' in 46 line. Do you now why request.Content is disposed at that moment ?

@Zabaa
Copy link

Zabaa commented Aug 29, 2017

And when I create GET method request.Content is null so it should be checked :)

@serefbilge
Copy link

serefbilge commented Sep 2, 2021

 Wait() should be called after ContinueWith methods, otherwise error comes out. Please check the page: https://stackoverflow.com/questions/26087935/why-do-i-have-to-wait-for-the-continuation

                 request
		        .Content
		        .ReadAsByteArrayAsync()
		        .ContinueWith(requestContentTask => { loggingInfo.Request = Encoding.UTF8.GetString(requestContentTask.Result); })
		        .ContinueWith
		        (
			        requestContentTask =>
			        {
				        if (exception == null)
				        {
					        response
						        .Content
						        .ReadAsByteArrayAsync()
						        .ContinueWith(responseContentTask => { loggingInfo.Response = Encoding.UTF8.GetString(responseContentTask.Result); })
						        .ContinueWith(responseContentTask => LogData(loggingInfo)).Wait();                                                           
				        }
				        else
				        {
					        loggingInfo.Exception = exception;
					        LogData(loggingInfo);
				        }
			        }
		        ).Wait();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment