Почему я не могу дважды прочитать входной поток запроса 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);
}
}
Ответы
Ответ 1
StreamReader
вызывает Dispose
в заданном потоке при его размещении. Чтобы оставить поток открытым, используйте соответствующий конструктор для StreamReader
.
Или еще лучше, просто скопируйте его в буфер. Из MSDN:
При чтении из потока более эффективно использовать буфер, который имеет тот же размер, что и внутренний буфер потока.
См. этот вопрос, например.
Ответ 2
HttpContext.Current.Request.InputStream.Position=0;
Как только вы прочтете, позиция переходит к последнему значению, оттуда он пытается прочитать второй раз.
Поэтому, прежде чем читать, установите положение в ноль.
Надеюсь, что это поможет.