OData / AspNetCoreOData

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

ODataException: When writing a JSON response... when an OData function returns an entity #102

Open magneticcore opened 3 years ago

magneticcore commented 3 years ago

Describe the bug

Calling an OData controller function returning an entity raises an ODataException:

When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataResourceWriter method or the ODataResourceSerializationInfo must be set on the ODataResource or ODataResourceSet that is being written. at Microsoft.OData.ODataResourceTypeContext.ValidateAndReturn[T](T value)

Assemblies affected

Microsoft.AspNetCore.OData v8.0.0-beta Microsoft.EntityFrameworkCore v5.0.3

Reproduce steps

Take the attached Visual Studio 2019 project "WebApplicationCoreOdata4-entity" and run it. In the launched browser, type for url: https://localhost:44353/api/books/GetBookByPressId(PressId=2)

Expected result

The response of odata contening the entity, ie book which PressId field is equal to 2.

Actual result

An ODataException is raised:

Microsoft.OData.ODataException: When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataResourceWriter method or the ODataResourceSerializationInfo must be set on the ODataResource or ODataResourceSet that is being written. at Microsoft.OData.ODataResourceTypeContext.ValidateAndReturn[T](T value) at Microsoft.OData.ODataResourceTypeContext.get_NavigationSourceName() at Microsoft.OData.ODataContextUrlInfo.Create(ODataResourceTypeContext typeContext, ODataVersion version, Boolean isSingle, ODataUri odataUri) at Microsoft.OData.JsonLight.ODataJsonLightResourceSerializer.<>cDisplayClass11_0.b0() at Microsoft.OData.JsonLight.ODataJsonLightSerializer.WriteContextUriProperty(ODataPayloadKind payloadKind, Func`1 contextUrlInfoGen, ODataContextUrlInfo parentContextUrlInfo, String propertyName) at Microsoft.OData.JsonLight.ODataJsonLightResourceSerializer.WriteResourceContextUri(ODataResourceTypeContext typeContext, ODataContextUrlInfo parentContextUrlInfo) at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource(ODataResource resource) at Microsoft.OData.ODataWriterCore.<>cDisplayClass121_0.b0() at Microsoft.OData.ODataWriterCore.InterceptException(Action action) at Microsoft.OData.ODataWriterCore.WriteStartResourceImplementation(ODataResource resource) at Microsoft.OData.ODataWriterCore.<>c__DisplayClass49_0.b__0() at Microsoft.OData.TaskUtils.GetTaskForSynchronousOperation(Action synchronousOperation) --- End of stack trace from previous location --- at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteResourceAsync(Object graph, ODataWriter writer, ODataSerializerContext writeContext, IEdmTypeReference expectedType) at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInlineAsync(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectAsync(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, ODataSerializerProvider serializerProvider)

Additional detail

None

Attachments

WebApplicationCoreOdata4-entity.zip

xuzhg commented 3 years ago

@magneticcore If you try the nightly, it should work:

That's related the function returned entity set

image

marcopelegrini commented 1 year ago

@xuzhg I'm getting this issue when using property navigation:

/odata/Apps/1542629c-01b3-4a6d-8f76-1938b779e48d/AppRating

Any tips?

image
xuzhg commented 1 year ago

@xuzhg I'm getting this issue when using property navigation:

/odata/Apps/1542629c-01b3-4a6d-8f76-1938b779e48d/AppRating

Any tips?

image

Do you have the navigation property binding for the navigation property "AppRating"? If it's non-contained navigation property?

Can you share your repro?

marcopelegrini commented 1 year ago

@xuzhg I can't, but I just replicated the same issue using this sample: https://github.com/OData/AspNetCoreOData/tree/main/sample/ODataRoutingSample

I've added a method for GetDetail in the ProductsController:

        [EnableQuery]
        [HttpGet]
        public IActionResult GetDetail(int key)
        {
            var product = _context.Products.FirstOrDefault(p => p.Id == key);
            if (product == null)
            {
                return NotFound($"Not found product with id = {key}");
            }

            return Ok(product.Detail);
        }

When I try https://localhost:5000/Products/1/Detail I get the same error:

Microsoft.OData.ODataException: When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataResourceWriter method or the ODataResourceSerializationInfo must be set on the ODataResource or ODataResourceSet that is being written.
xuzhg commented 1 year ago

@marcopelegrini Add a new line code after: https://github.com/OData/AspNetCoreOData/blob/main/sample/ODataRoutingSample/Models/EdmModelBuilder.cs#L18

as: builder.EntitySet("Details");

Let me know whether it can work or not?

marcopelegrini commented 1 year ago

@xuzhg, that works. Now, if ProductDetail was a complex type (no Id)... is there a way to make it work?

xuzhg commented 1 year ago

@marcopelegrini Without 'Id', it should work without any other changes. Or you can explicitly config ProductDetail as complex by calling 'builder.ComplexType();'. Thanks.