-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Q: OpenAPI for streamed JSON request body & asking about IAsyncEnumerable<T> input support #62391
-
Hi ASP.NET Core team,
Scenario:
I need to accept very large JSON arrays. To avoid buffering the whole payload I read HttpRequest.Body directly and stream‐deserialize with JsonSerializer.DeserializeAsyncEnumerable<Data>().
That (hopefully) keeps memory usage low, but because the action has no [FromBody] parameter, the OpenAPI shows an empty request body.
[HttpPost] [EndpointSummary("...")] [EndpointDescription("...")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] [ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(string))] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(string))] public async Task<ActionResult<int>> Post(CancellationToken cancellationToken) { var processedCount = 0; var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; try { // The array can be a VERY LARGE array. await foreach (var data in JsonSerializer.DeserializeAsyncEnumerable<Data>(Request.Body, jsonOptions, cancellationToken)) { if (data == null) { continue; } // send data to SQS / background worker here processedCount++; } return processedCount; } catch { return BadRequest("Invalid request body"); } }
Questions
-
How do I decorate the action so that OpenAPI documentation shows "array of Data in the request body" even though I’m reading
Request.Bodymyself? (Is there an side-effect free attribute that you recommend? As far as my understanding if I use[FromBody]it will buffer and deserialize the content of the JSON into memory) -
Is manual streaming still the right approach, or can MVC now bind directly to IAsyncEnumerable?
public async Task<ActionResult<int>> Post([FromBody] IAsyncEnumerable<Data> items, CancellationToken ct)
If this is (or will soon be) supported?
- Any gotchas when using the manual Request.Body approach?
Related issues:
- Make SystemTextJsonInputFormatter IAsyncEnumerable aware #43489
- Support binding request body as Stream in Controller Actions #41540
- https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/6.0/iasyncenumerable-not-buffered-by-mvc (but for output, not input)
Any guidance or pointers to docs would be greatly appreciated.
Thanks for your time and for all the great work on ASP.NET Core!
Beta Was this translation helpful? Give feedback.
All reactions
How do I decorate the action so that OpenAPI documentation shows "array of Data in the request body"
If you are using .NET 9 and the built-in OpenAPI document generation, you could use an operation transformer to add the request body on that operation. The operation transformer will run for all operations and you'll have to filter to just the one you want to update.
Is manual streaming still the right approach, or can MVC now bind directly to IAsyncEnumerable?
I think manual streaming is still the right (only?) approach.
Any gotchas when using the manual Request.Body approach?
Just the one you've already encountered -- you need to fix the OpenAPI metadata to get an accurate API desc...
Replies: 1 comment
-
How do I decorate the action so that OpenAPI documentation shows "array of Data in the request body"
If you are using .NET 9 and the built-in OpenAPI document generation, you could use an operation transformer to add the request body on that operation. The operation transformer will run for all operations and you'll have to filter to just the one you want to update.
Is manual streaming still the right approach, or can MVC now bind directly to IAsyncEnumerable?
I think manual streaming is still the right (only?) approach.
Any gotchas when using the manual Request.Body approach?
Just the one you've already encountered -- you need to fix the OpenAPI metadata to get an accurate API description.
Beta Was this translation helpful? Give feedback.