Надеюсь, я получу лучший результат, чем этот вопрос Потоковая передача IAsyncEnumerable JSON не выполняется в веб-приложении Azure, работающем в IIS
У меня точно такая же проблема. У меня есть код с IAsyncEnumerable с ASP.NET, и в javascript я использую его как поток. Он работает на Kestrel, но когда я развертываю его в Службе приложений Azure в Windows, он не работает.
Мой код выглядит следующим образом:
На контроллере:
[HttpPost, Route("runLongProcess")]
[TextJsonFormatter]
public async IAsyncEnumerable<string> RunLongProcess(int id)
{
await foreach (var item in longProcessTask.RunLongProcess(id))
yield return item;
}
и код задачи
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;
}
}
Атрибут контроллера предназначен для принудительного использования сериализатора System.Text.Json и выглядит следующим образом:
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);
}
}
}
Код работает над локальной разработкой Kestrel, но в Службе приложений Azure в Windows. Он обрабатывает первый элемент и возвращает его правильно, но затем это занимает много времени, и все оставшиеся элементы возвращаются сразу.
Добавьте HttpContext.Features.Get<IHttpResponseBodyFeature>().DisableBuffering();
в свой код, и он будет работать правильно.
И я также обновляю ответ в упомянутой вами ссылке, он также содержит мой тестовый код.
[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;
}