OData / AspNetCoreOData

ASP.NET Core OData: A server library built upon ODataLib and ASP.NET Core
Other
458 stars 158 forks source link

Use `await using` for async disposal of message writer #1323

Closed habbes closed 1 month ago

habbes commented 1 month ago

This issue https://github.com/OData/AspNetCoreOData/issues/1320 revealed that we call synchronous Dispose() method in one of the code paths in ODataOutputFormatterHelper:

System.InvalidOperationException
An asynchronous operation is already in progress.
   at System.Xml.XmlAsyncCheckWriter.CheckAsync()
   at System.Xml.XmlAsyncCheckWriter.Flush()
   at Microsoft.OData.ODataMetadataOutputContext.Dispose(Boolean disposing)
   at Microsoft.OData.ODataOutputContext.Dispose()
   at Microsoft.OData.ODataMessageWriter.Dispose(Boolean disposing)
   at Microsoft.OData.ODataMessageWriter.Dispose()
   at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider)

This is due to the fact the code path uses

using (ODataMessageWriter messageWriter = ...)
{

}

instead of

await using (ODataMessagewriter messageWriter = ...)
{
}

AspNetCoreOData uses an internal StreamWriter that wraps the output stream, intercepts the synchronous Write(byte[] buffer) method and calls WriteAsync() and blocks on the result. This is a bad pattern and we should remove it now that we have async CSDL schema writer. This pattern is a hack to by the AllowSynchronousIO setting: https://github.com/OData/AspNetCoreOData/blob/main/src/Microsoft.AspNetCore.OData/Formatter/ODataOutputFormatterHelper.cs#L244

See: https://github.com/OData/AspNetCoreOData/issues/997

We should check whether the synchronous geospatial serialization API would be a problem.