Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpRequestMessage.Content is lost when it is read in a logging DelegatingHandler in ASP.Net Web API

When trying to an object in an Action in a Controller it sporadically seems to be null. I discovered that it is due to the ReadAsStringAsync() in the SendAsync() override of the DelegatingHandler. The issue is with the content. When my client sends a content body and it is read in the logger it is never read by the Controller Action Invoker (or may be somewhere in the JsonFormatter). I suspect the subsequent call to Content.ReadAsStringAsync() doesnt throw an exception but also doesnt not return the expected content body (some info is returned stating that the async read is completed).

But my problem remains since I want to read a [FromBody] parameter in an action and it is null when the RaceCondition of Content.ReadStringAsync is won by the DelegatingHandler. When JsonFormatter wins it though, I get the object but that is rare (only at service startup).

Here is my DelegatingHandler code:

public class LogHandler : DelegatingHandler
{

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var apiRequest = new WebApiUsageRequest(request);
        WriteLog(apiRequest);
        request.Content.ReadAsStringAsync().ContinueWith(t =>
        {
            apiRequest.Content = t.Result;
            WriteLog(apiRequest);
        });

        return base.SendAsync(request, cancellationToken).ContinueWith(task =>
        {
            var apiResponse = new WebApiUsageResponse(task.Result);
            apiResponse.Content = task.Result.Content != null ? task.Result.Content.ReadAsStringAsync().Result : null;
            WriteLog(apiResponse);
            return task.Result;
        });
    }
}

Does anyone have a clue to the solution of this issue?

like image 417
Sando Avatar asked Aug 24 '12 03:08

Sando


1 Answers

This is by design. In ASP.NET Web API the body content is treated a forward-only stream that can only be read once.

You might try utilising ASP.NET Web API Tracing but I haven't test it with POST request yet so I'm not sure how/if it is tracing the request body (it is tracing parameters for GET request for sure). You can read more here:

  • Tracing in ASP.NET Web API (Ron Cain)
  • ASP.NET Web API Tracing Preview (Ron Cain)
  • Tracing in ASP.NET Web API (Mike Wasson)
like image 58
tpeczek Avatar answered Oct 14 '22 01:10

tpeczek