Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
670 views
in Technique[技术] by (71.8m points)

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

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);
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...