WebApi Formatter that is using ReadAsAsync and WriteToStreamAsync - Json gets truncated while xml works fine
<p>I am working with <code>C#</code>, <code>WebAPI 2</code> and getting a weird behavior.</p>

<p>I have service that calls Controller and content can be sent sometimes as Json and others as XML mechanism that is used to make a call looks following:</p>

<pre><code>using (var client = new HttpClient())
{
    var pricingControllerUrl = CreateEndpoint(apiUrl);
    using (var response = (int)request.Metadata.InputType &gt;= 3 ?  client.PostAsJsonAsync(pricingControllerUrl, request) : client.PostAsXmlWithSerializerAsync(pricingControllerUrl, request))
    {
        if (response.Result.IsSuccessStatusCode)
        {
            var session = response.Result.Content.ReadAsAsync&lt;Session&gt;(new List&lt;MediaTypeFormatter&gt;() { new XmlMediaTypeFormatter { UseXmlSerializer = true }, new JsonMediaTypeFormatter() }).Result;
            return session;
        }
    }
}

public static class HttpExtensions
{
    public static Task&lt;HttpResponseMessage&gt; PostAsXmlWithSerializerAsync&lt;T&gt;(this HttpClient client, string requestUri, T value)
    {
        return client.PostAsync(new Uri(requestUri), value,
                      new XmlMediaTypeFormatter { UseXmlSerializer = true }
                      );
    }
}
</code></pre>

<p>On the receiving end (controller),</p>

<pre><code>public async Task&lt;IHttpActionResult&gt; PostSession([FromBody] Session session)
    {
    //do the calculations
    return Content(HttpStatusCode.OK, sessionResponse, new ReducedSessionFormatter(), this.Request.Content.Headers.ContentType);
    }
</code></pre>

<p>response has to be reduced by removing some information just before it gets dispatched, formatter below is used to facilitate this:</p>

<pre><code>public class ReducedSessionFormatter : MediaTypeFormatter
{
    public ReducedSessionFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/json"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
    }

    public ReducedSessionFormatter(MediaTypeFormatter formatter) : base(formatter)
    {
    }

    public override bool CanReadType(Type type)
    {
        return false;
    }

    public override bool CanWriteType(Type type)
    {
        return type.IsAssignableFrom(typeof (Session));
    }

    protected XDocument ReduceXml(XDocument doc)
    {

        //removing stuff from xml
        return doc;
    }

    protected JObject ReduceJson(JObject serializedJson)
    {
        //removing stuff from json
        return serializedJson;
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        if (content.Headers.ContentType.MediaType.Contains("xml"))
        {
            var doc = SerializeToXmlDocument(type, value).ToXDocument();
            doc = ReduceXml(doc);

            var settings = new XmlWriterSettings {Encoding = new UTF8Encoding(false)};
            using (XmlWriter w = XmlWriter.Create(writeStream, settings))
            {
                doc.Save(w);
            }
        }
        else
        {
            var json = new JavaScriptSerializer().Serialize(value);
            var serializedJson = (JObject)JsonConvert.DeserializeObject(json);
            var serializedJsonString = ReduceJson(serializedJson).ToString(Newtonsoft.Json.Formatting.None);
            var writer = new StreamWriter(writeStream);
            writer.Write(serializedJsonString);
        }

        var tcs = new TaskCompletionSource&lt;object&gt;();
        tcs.SetResult(null);
        return tcs.Task;
    }

    public XmlDocument SerializeToXmlDocument(Type type, object value)
    {
        var serializer = new XmlSerializer(type);

        XmlDocument xmlDocument = null;

        using (var memoryStream = new MemoryStream())
        {
            serializer.Serialize(memoryStream, value);
            memoryStream.Position = 0;
            using (var xtr = XmlReader.Create(memoryStream, new XmlReaderSettings {IgnoreWhitespace = true}))
            {
                xmlDocument = new XmlDocument();
                xmlDocument.Load(xtr);
            }
        }

        return xmlDocument;
    }
}

public static class XmlExtensions
{
    public static XDocument ToXDocument(this XmlDocument xmlDocument)
    {
        using (var nodeReader = new XmlNodeReader(xmlDocument))
        {
            nodeReader.MoveToContent();
            return XDocument.Load(nodeReader);
        }
    }
}
public static class JsonExtensions
{
    public static bool IsNullOrEmpty(this JToken token)
    {
        return (token == null) ||
               (token.Type == JTokenType.Array &amp;&amp; !token.HasValues) ||
               (token.Type == JTokenType.Object &amp;&amp; !token.HasValues) ||
               (token.Type == JTokenType.String &amp;&amp; token.ToString() == String.Empty) ||
               (token.Type == JTokenType.Null);
    }
}
</code></pre>

<p>When aggregated in formatter both xml and json are valid and fine and if data is sent back without using formatter everything works</p>

<p><strong>Weird stuff:</strong> when I am using formatter and send back Json it gets truncated independent from length of it. Even very tiny objects (less than 10k length) get cut off always at same place for same object but at different length for different objects, and only for json and work just fine for xml...</p>

<p>it also fails if json is not being toStringed like:</p>

<pre><code>            var writer = new StreamWriter(writeStream);
            writer.Write(ReduceJson(serializedJson));
</code></pre>

<p>I have added <a href="https://github.com/liufa/Temp/blob/master/WebApplication2.7z" rel="nofollow">minimal solution to show the issue</a></p>

<p><strong>What is going on here? Why using formatter truncates response content for Json but not XML?</strong></p>