title: Why is the body of a Web API request read once?
body: <p>My goal is to authenticate Web API requests using a AuthorizationFilter or DelegatingHandler. I want to look for the client id and authentication token in a few places, including the request body. At first it seemed like this would be easy, I could do something like this</p>
  
  <pre><code>var task = _message.Content.ReadAsAsync&lt;Credentials&gt;();
  
  task.Wait();
  
  if (task.Result != null)
  {
      // check if credentials are valid
  }
  </code></pre>
  
  <p>The problem is that the HttpContent can only be read once. If I do this in a Handler or a Filter then the content isn't available for me in my action method. I found a few answers here on StackOverflow, like this one: <a href="https://stackoverflow.com/questions/12494067/read-httpcontent-in-mvc-webapi-controller?rq=1">Read HttpContent in WebApi controller</a> that explain that it is intentionally this way, but they don't say WHY. This seems like a pretty severe limitation that blocks me from using any of the cool Web API content parsing code in Filters or Handlers.</p>
  
  <p>Is it a technical limitation? Is it trying to keep me from doing a VERY BAD THING(tm) that I'm not seeing? </p>
  
  <p>POSTMORTEM:</p>
  
  <p>I took a look at the source like Filip suggested. ReadAsStreamAsync returns the internal stream and there's nothing stopping you from calling Seek <strong>if the stream supports it</strong>. In my tests if I called ReadAsAsync then did this:</p>
  
  <pre><code>message.Content.ReadAsStreamAsync().ContinueWith(t =&gt; t.Result.Seek(0, SeekOrigin.Begin)).Wait();
  </code></pre>
  
  <p>The automatic model binding process would work fine when it hit my action method. I didn't use this though, I opted for something more direct:</p>
  
  <pre><code>var buffer = new MemoryStream(_message.Content.ReadAsByteArrayAsync().WaitFor());
  var formatters = _message.GetConfiguration().Formatters;
  var reader = formatters.FindReader(typeof(Credentials), _message.Content.Headers.ContentType);
  var credentials = reader.ReadFromStreamAsync(typeof(Credentials), buffer, _message.Content, null).WaitFor() as Credentials;
  </code></pre>
  
  <p>With an extension method (I'm in .NET 4.0 with no await keyword)</p>
  
  <pre><code>public static class TaskExtensions
  {
      public static T WaitFor&lt;T&gt;(this Task&lt;T&gt; task)
      {
          task.Wait();
          if (task.IsCanceled) { throw new ApplicationException(); }
          if (task.IsFaulted) { throw task.Exception; }
          return task.Result;
      }
  }
  </code></pre>
  
  <p>One last catch, HttpContent has a hard-coded max buffer size:</p>
  
  <pre><code>internal const int DefaultMaxBufferSize = 65536;
  </code></pre>
  
  <p>So if your content is going to be bigger than that you'll need to manually call LoadIntoBufferAsync with a larger size before you try to call ReadAsByteArrayAsync.</p>