Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I read Http Request Input stream twice?

Tags:

I was putting in some debugging code to test some things, and then the debug code didn't behave as expected. The example below is a simplified code to demonstrate my question.

This is in .NET 4 and using WebApi, I'm trying to print out the body of the http request in the debug code. To do this I seek the Input stream back and read the stream. It works fine the first time, but if I try to read it again, I get an empty string.

Why can't I seek back and read the InputStream a second time? In the example below, body2 is always empty. In the second set, CanSeek is still true and the the second call to ReadToEnd() returns an empty string overwriting the default.

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);     } } 
like image 553
Michael Levy Avatar asked Feb 23 '14 17:02

Michael Levy


People also ask

Can I read InputStream twice?

Depending on where the InputStream is coming from, you might not be able to reset it. You can check if mark() and reset() are supported using markSupported() . If it is, you can call reset() on the InputStream to return to the beginning. If not, you need to read the InputStream from the source again.

Can we open output stream twice in Java?

No. Java streams, once consumed, can not be reused by default.

How do I copy input stream?

If all you want to do is read the same information more than once, and the input data is small enough to fit into memory, you can copy the data from your InputStream to a ByteArrayOutputStream. Then you can obtain the associated array of bytes and open as many "cloned" ByteArrayInputStreams as you like.

How do I reset my input stream?

The java. io. InputStream. reset() method repositions this stream to the position at the time the mark method was last called on this input stream.


Video Answer


2 Answers

StreamReader calls Dispose on given stream when disposed. To leave the stream open use the appropriate constructor for the StreamReader. Or better yet, just copy it to a buffer. From MSDN:

When reading from a Stream, it is more efficient to use a buffer that is the same size as the internal buffer of the stream.

See this question for example.

like image 109
Patko Avatar answered Sep 22 '22 13:09

Patko


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

Once you read the position goes to last value, from there its trying to read second time. So before you read, set the position to zero.

Hope it helps.

like image 44
ANG Avatar answered Sep 22 '22 13:09

ANG