Hoping I get better result than this question IAsyncEnumerable JSON streaming is not streaming on azure web app running on IIS
I have the exact same problem. I have a code with IAsyncEnumerable with ASP.NET, and on javascript I am consume it as stream. It is working on Kestrel, but when I deploy it to Azure App Service on Windows, it is not working
My code is as follows:
On Controller:
[HttpPost, Route("runLongProcess")]
[TextJsonFormatter]
public async IAsyncEnumerable<string> RunLongProcess(int id)
{
await foreach (var item in longProcessTask.RunLongProcess(id))
yield return item;
}
and the task code
public async IAsyncEnumerable<string> RunLongProcess(int id)
{
var pipeline = parentPipeline ?? GetPipeline();
var resultToProcess = await GetAllResult(id);
foreach (var item in resultToProcess)
{
string processResult = await ProcessItem(item);
yield return processResult;
}
}
The attribute on the controller is to force to use System.Text.Json serializer, and it is as follows:
public class TextJsonFormatterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is ObjectResult objectResult)
{
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
objectResult.Formatters.RemoveType<NewtonsoftJsonOutputFormatter>();
objectResult.Formatters.Add(new SystemTextJsonOutputFormatter(options));
}
else
{
base.OnActionExecuted(context);
}
}
}
The code working on Kestrel local development, but on Azure App Service on Windows. It process the first item and return it correctly, but then it takes long time and return will all remaining items processed at once.
Add HttpContext.Features.Get<IHttpResponseBodyFeature>().DisableBuffering();
in your code, and it will work properly.
And I also update the answer in that link you mentioned, it also contains my test code.
[HttpPost, Route("runLongProcess")]
[TextJsonFormatter]
public async IAsyncEnumerable<string> RunLongProcess(int id)
{
HttpContext.Features.Get<IHttpResponseBodyFeature>().DisableBuffering();
await foreach (var item in longProcessTask.RunLongProcess(id))
yield return item;
}