The output of the ASP.NET Web API Controller is always buffered.

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 immediately appears in the browser, so it looks as if it starts sending it before 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 the controller:

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

It did not help. All output is displayed in the browser at the same time.

UPDATE

The problem seems to be flushing. I changed the 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 see the result. Disabling gzip encoding does not help to see content in small fragments.

0
source share

Source: https://habr.com/ru/post/1650350/


All Articles