locked
ASP.NET Web API Controller output is always buffered RRS feed

  • Question

  • User-2115162787 posted

    How to send output without buffering? I defined my API controller this way:

    public class DefaultController : ApiController
    {
        [HttpGet]
        [Route]
        public HttpResponseMessage Get()
        {
            var response = Request.CreateResponse();
            response.Content = new PushStreamContent(
                (output, content, context) =>
                {
                    using (var writer = new StreamWriter(output))
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            writer.WriteLine("Eh?");
                            writer.Flush();
                            Thread.Sleep(2000);
                        }
                    }
                },
                "text/plain");
    
            return response;
        }
    }

    Output appears in the browser all at once, so it looks like it waits start sending it till completion. I defined this attribute:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    class NoBufferAttribute : Attribute, IControllerConfiguration
    {
        public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
        {
            controllerSettings.Services.Replace(
                typeof(IHostBufferPolicySelector),
                new BufferPolicy());
        }
    
        class BufferPolicy : IHostBufferPolicySelector
        {
            public bool UseBufferedInputStream(object hostContext)
            {
                return false;
            }
    
            public bool UseBufferedOutputStream(HttpResponseMessage response)
            {
                return false;
            }
        }
    }

    And applied it to controller:

        [NoBuffer]
        public class DefaultController : ApiController
        {
              ...
        }

    It did not help. All the output appears in the browser the same time.

    Friday, July 17, 2015 11:15 PM

Answers

  • User-2115162787 posted

    It looks like problem is about flushing. I changed code to the following:

            var response = Request.CreateResponse();
            response.Content = new PushStreamContent(
                (output, content, context) =>
                {
                    using (var writer = new StreamWriter(output))
                    {
                        var s = Stopwatch.StartNew();
                        while (s.Elapsed < TimeSpan.FromSeconds(10))
                        {
                            writer.WriteLine(s.Elapsed);
                            writer.Flush();
                        }
                    }
                },
                "text/plain");

    Now I can see output in progress. Disabling gzip encoding does not help to see content in smaller chunks.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 18, 2015 7:36 AM

All replies

  • User1759999623 posted

    Are you confusing the asynchronous nature of Web API methods as buffering?  I would believe that the response must be completed before it can be sent back to the client.

    Saturday, July 18, 2015 2:56 AM
  • User-2115162787 posted

    It is mentioned here that "I use PushStreamContent with my REST API (ASP.NET Web API) and works great. The HttpClient can request a ressource and gets the HTTP-Response before the complete request is handled by the server (the server still writes to the push-stream)."

    It just does not work for me the same way in a fresh new test project which does not contain anything except quoted code.

    Saturday, July 18, 2015 6:59 AM
  • User-2115162787 posted

    It looks like problem is about flushing. I changed code to the following:

            var response = Request.CreateResponse();
            response.Content = new PushStreamContent(
                (output, content, context) =>
                {
                    using (var writer = new StreamWriter(output))
                    {
                        var s = Stopwatch.StartNew();
                        while (s.Elapsed < TimeSpan.FromSeconds(10))
                        {
                            writer.WriteLine(s.Elapsed);
                            writer.Flush();
                        }
                    }
                },
                "text/plain");

    Now I can see output in progress. Disabling gzip encoding does not help to see content in smaller chunks.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 18, 2015 7:36 AM