Open awbacker opened 1 year ago
Is this perhaps somewhat intended, as part of a streaming response?
We have an EF data context which is used across multiple platforms; desktop, api, webapi. This context intercepts the EF query expressions for many purposes; one of which is to ensure that the current user has read permission for all the entity sets they are attempting to access. Should this fail, an appropriate “access denied” exception is thrown.
By virtue of IQueryable, AspNetCore OData (8.2.5) begins writing to the response body before the entities have been materialized. If an exception occurs while materializing the entities, the response is abandoned - but with a 200 OK status. Any exception handlers also fail because the response has already started and cannot be changed.
Other exceptions may be thrown during the materialization of entities (e.g. database / network issues), so this isn’t great behaviour.
For now, we’ve worked around the issue by overriding the default implementation of WriteObjectAsync in ODataResourceSetSerializer, ensuring entities are materialized into concrete lists before the base method is called. Doing so ensures that any exception occurs before AspNetCore OData has started to respond, at the possible cost of some performance:
public override async Task WriteObjectAsync(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
{
// Microsoft.AspNetCore.OData (8.2.5) starts the HttpResponse
// before materializing EF entities.
// Any errors during materialization will not get returned because the
// response has already started and cannot be changed.
// This results in a 200 OK and a truncated response.
// So... let's materialize EF entities early.
// Any exception will now be thrown before the response has started.
if (graph is IAsyncEnumerable<object> asyncEnumerable)
graph = await asyncEnumerable.ToListAsync();
else if (graph is IEnumerable enumerable)
graph = enumerable.Cast<object>().ToList();
await base.WriteObjectAsync(graph, type, messageWriter, writeContext);
}
Definitely the same issue as https://github.com/OData/WebApi/issues/2704.
I have a simple controller with a
Get
method, which reads from the database. TheEntityFramework
model had a bug (column was null). When reading, an exception was raised:This causes the OData library to:
Data Model
Request/Response
Expected behavior