MVC no almacena en búfer los tipos IAsyncEnumerable al usar System.Text.Json

En ASP.NET Core 5, MVC agregó compatibilidad con la aplicación de formato de salida a los tipos IAsyncEnumerable<T> al almacenar en búfer la secuencia en memoria y aplicar formato a la colección almacenada en búfer. En ASP.NET Core 6, al aplicar formato mediante System.Text.Json, MVC ya no almacena en búfer las instancias de IAsyncEnumerable<T>. En su lugar, MVC se basa en la compatibilidad que System.Text.Json agregó para estos tipos.

En la mayoría de los casos, la aplicación no observa la ausencia de almacenamiento en búfer, pero puede que algunos escenarios dependan involuntariamente de la semántica de almacenamiento en búfer para serializar correctamente. Por ejemplo, si se devuelve una instancia de IAsyncEnumerable<T> que está respaldada por una consulta de Entity Framework en un tipo con propiedades cargadas de forma diferida, es posible que se produzca una ejecución simultánea de las consultas, lo que podría no ser compatible con el proveedor.

Este cambio no afecta a la aplicación de formato de salida mediante Newtonsoft.Json o con formateadores basados en XML.

Versión introducida

ASP.NET Core 6.0

Comportamiento anterior

Las instancias de IAsyncEnumerable<T> que se devuelven a partir de una acción de MVC como un valor al que se va a aplicar formato mediante ObjectResult o JsonResult se almacenan en búfer antes de serializarse como una colección sincrónica.

Comportamiento nuevo

Al aplicar formato mediante System.Text.Json, MVC ya no almacena en búfer las instancias de IAsyncEnumerable<T>.

Motivo del cambio

System.Text.Json ha agregado compatibilidad con el streaming de tipos IAsyncEnumerable<T>. Esto permite una superficie de memoria menor durante la serialización.

Si la aplicación requiere almacenamiento en búfer, considere la posibilidad de almacenar manualmente en búfer el objeto IAsyncEnumerable<T>:

// Before
public IActionResult Get()
{
    return Ok(dbContext.Blogs);
}

// After
public async Task<IActionResult> Get()
{
    return Ok(await dbContext.Blogs.ToListAsync());
}