Почему я не могу дважды прочитать входной поток запроса Http? - программирование

Почему я не могу дважды прочитать входной поток запроса Http?

Я вставлял некоторый код отладки, чтобы проверить некоторые вещи, а затем код отладки не вел себя так, как ожидалось. Пример ниже - упрощенный код, чтобы продемонстрировать мой вопрос.

Это в .NET 4 и с использованием WebApi, я пытаюсь распечатать тело http-запроса в коде отладки. Для этого я ищу поток ввода и прочитаю поток. Он работает отлично в первый раз, но если я попытаюсь прочитать его снова, я получаю пустую строку.

Почему я не могу запросить назад и прочитать InputStream во второй раз? В приведенном ниже примере body2 всегда пуст. Во втором наборе CanSeek по-прежнему верен, а второй вызов ReadToEnd() возвращает пустую строку, перезаписывающую значение по умолчанию.

using System.IO;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;

public class TestController : ApiController
{

    public class TestOutuput
    {
        public string firstRead;
        public string secondRead;
    }

    public HttpResponseMessage Post()
    {
        string body1 = "default for one";
        string body2 = "default for two";
        if (HttpContext.Current.Request.InputStream.CanSeek)
        {
            HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
        }
        using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
        {
            body1 = reader.ReadToEnd();
        }

        if (HttpContext.Current.Request.InputStream.CanSeek)
        {
            HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
        }
        using (var reader2 = new StreamReader(HttpContext.Current.Request.InputStream))
        {
            // this is always empty, even after seek back to origin
            body2 = reader2.ReadToEnd();
        }

        TestOutuput testOutput = new TestOutuput() { firstRead = body1, secondRead = body2 };
        HttpResponseMessage response = new HttpResponseMessage();
        return Request.CreateResponse<TestOutuput>(HttpStatusCode.OK, testOutput);
    }
}
4b9b3361

Ответ 1

StreamReader вызывает Dispose в заданном потоке при его размещении. Чтобы оставить поток открытым, используйте соответствующий конструктор для StreamReader. Или еще лучше, просто скопируйте его в буфер. Из MSDN:

При чтении из потока более эффективно использовать буфер, который имеет тот же размер, что и внутренний буфер потока.

См. этот вопрос, например.

Ответ 2

HttpContext.Current.Request.InputStream.Position=0;

Как только вы прочтете, позиция переходит к последнему значению, оттуда он пытается прочитать второй раз. Поэтому, прежде чем читать, установите положение в ноль.

Надеюсь, что это поможет.