OdataToEntity: `$select` on nullable `$expand` property throws ODataException
When I execute the following query (where an Account
has a nullable/optional DepartmentId
/ Department
:
http://localhost:5000/odata/Accounts?$top=50&$expand=Department($select=Name)
I get the following exception.
Microsoft.OData.ODataException: The property 'Name[Nullable=False]' of type 'Edm.String' has a null value, which is not allowed.
at Microsoft.OData.WriterValidationUtils.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, IEdmModel model)
at Microsoft.OData.WriterValidator.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, Boolean isTopLevel, IEdmModel model)
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteNullProperty(ODataProperty property)
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties(IEdmStructuredType owningType, IEnumerable`1 properties, Boolean isComplexValue, IDuplicatePropertyNameChecker duplicatePropertyNameChecker)
at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource(ODataResource resource)
at Microsoft.OData.ODataWriterCore.InterceptException(Action action)
at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo)
at OdataToEntity.AspNetCore.ODataResult`1.WriteNavigationProperty(ODataWriter writer, Object value, PropertyInfo navigationProperty)
at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo)
at OdataToEntity.AspNetCore.ODataResult`1.SerializeAsync(ODataWriter writer)
at OdataToEntity.AspNetCore.ODataResult`1.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Request finished in 259.252ms 200 application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8
If I adjust the query with either of the following, the query executes successfully
- Do not apply the
$select
on the$expand
http://localhost:5000/odata/Accounts?$top=50&$expand=Department
- Filter null
Department
entitieshttp://localhost:5000/odata/Accounts?$top=50&$expand=Department($select=Name)&$filter=DepartmentId ne null
This led me to believe the combination of $expand
ing a nullable property and $select
was the culprit.
I was able to setup a local database and successfully run your entire test suite, and I attempted to write a failing test to confirm the issue using the existing models
[Theory]
[InlineData(0, false)]
[InlineData(1, false)]
[InlineData(0, true)]
[InlineData(1, true)]
public async Task ExpandNullableNestedSelect(int pageSize, bool navigationNextLink)
{
var parameters = new QueryParameters<Order>()
{
RequestUri = "Orders?$expand=AltCustomers($select=Name)&$orderby=Id",
Expression = t => t.Include(o => o.AltCustomer).OrderBy(o => o.Id),
NavigationNextLink = navigationNextLink,
PageSize = pageSize
};
await Fixture.Execute(parameters).ConfigureAwait(false);
}
but I am unable to execute the test due to a cleanup failure I can’t figure out.
I think there is a similar issue with ICollection
properties, but I haven’t spent as much time trying to dig in and confirm yet.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 30 (30 by maintainers)
Commits related to this issue
- fix #25 $select property from $expand null navigation property in controller — committed to voronov-maxim/OdataToEntity by voronov-maxim 6 years ago
Add support filter and select result