Created
July 7, 2014 13:44
-
-
Save mrshridhara/0f6a4ed1277dbc467f75 to your computer and use it in GitHub Desktop.
DelegatingHandler to log request and response of a Web API call.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; } | |
} | |
} |
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
And when I create GET method request.Content is null so it should be checked :)