title: ASP.NET Web API Logging Inbound Request Content
body: <p>I’m trying to log out Web API Request Content – i.e. the json string.  I implemented an ITraceWriter class (<a href="http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api" rel="nofollow noreferrer">example</a>) and configured it so that Web API calls it in the pipeline.  But if I read the request.Content or copy into to a stream to read it is not available for the method resulting in a null model.  <a href="https://stackoverflow.com/questions/13021089/why-is-the-body-of-a-web-api-request-read-once">This post</a> talks about that issue a little.  Anyone have experience logging out inbound Web API request content and know what the best approach is?</p>
  
  <p>Thanks</p>
  
  <p><strong>Update A</strong></p>
  
  <p>I created a simple sample Web API project to rule out anything in my project and I still see that the model will be null because of logging.  I simply test a few times in a row by posting via Fidder and see my model comes in null.  With breakpoints in place, it might work which is why I think there is a sync/timing issue.  Any thoughts on how to get this to work?</p>
  
  <p>Header:</p>
  
  <pre><code>User-Agent: Fiddler
  Host: localhost:56824
  Content-Type: application/json
  Content-Length: 22
  </code></pre>
  
  <p>Body:</p>
  
  <pre><code>{
  "A":1,"B":"test"
  }
  </code></pre>
  
  <p>Here's the code:</p>
  
  <p>Controller:</p>
  
  <pre><code>public class ValuesController : ApiController
  {
      [HttpPost]
      public void Post(ValuesModel model)
      {
          if (model == null)
          {
              Debug.WriteLine("model was null!");
          }
          else
          {
              Debug.WriteLine("model was NOT null!");
          }
      }
  }
  </code></pre>
  
  <p>Model:</p>
  
  <pre><code>public class ValuesModel
  {
      public int A { get; set; }
      public string B { get; set; }
  }
  </code></pre>
  
  <p>Logger:</p>
  
  <pre><code>public class APITraceLogger : DelegatingHandler
      {
          protected override System.Threading.Tasks.Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
          {
              if (request.Content != null)
              {
                  // This can cause model to be null
                  request.Content.ReadAsStringAsync().ContinueWith(s =&gt;
                  {
                      string requestText = s.Result;
                      Debug.WriteLine(requestText);
                  });
  
                  // and so can this
                  //request.Content.ReadAsByteArrayAsync()
                  //    .ContinueWith((task) =&gt;
                  //    {
                  //        string requestText = System.Text.UTF8Encoding.UTF8.GetString(task.Result);
                  //        Debug.WriteLine(requestText);
                  //    });
              }
              // Execute the request, this does not block
              var response = base.SendAsync(request, cancellationToken);
  
              // TODO:
              // Once the response is processed asynchronously, log the response data
              // to the database
  
  
              return response;
          }
  
  
      }
  </code></pre>
  
  <p>Wiring up logger in WebApiConfig class:</p>
  
  <pre><code>config.MessageHandlers.Add(new APITraceLogger());
  </code></pre>
  
  <p><strong>Update B</strong></p>
  
  <p>It seems like it is now working if I change the logger to the following code adding the await, async and returning the result.  Seems like something I'm not understanding in the async code or truly a timing issue or something.</p>
  
  <pre><code>public class APITraceLogger : DelegatingHandler
  {
      protected async override System.Threading.Tasks.Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
      {
          if (request.Content != null)
          {
  
              // This does seem to work - is it because it is synchronous?  Is this a potential problem?
              var requestText = await request.Content.ReadAsStringAsync();
              Debug.WriteLine(requestText);
          }
          // Execute the request, this does not block
          var response = base.SendAsync(request, cancellationToken);
  
          // TODO:
          // Once the response is processed asynchronously, log the response data
          // to the database
  
  
          return response.Result;
      }
  
  
  }
  </code></pre>