Reputation: 31
$orderby
fails on a derived type property
Assemblies affected
System.Web.OData 5.9.1.0 Microsoft.OData.Core 6.15.0.0
Reproduce steps
*Model:
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Manager : Person
{
public string ManagerProperty { get; set; }
}
public class Supervisor : Person
{
public string SupervisorProperty { get; set; }
}
If I query now to order on a derived Members property I get an error
Query:
http://someserver/odata/persons?$isof=('Namespace.Manager')&$orderby=Namespace.Manager/ManagerProperty
Error Details:
"message":"The method or operation is not implemented.","type":"System.NotImplementedException","stacktrace":" at Microsoft.OData.Core.UriParser.Visitors.QueryNodeVisitor`1.Visit(SingleEntityCastNode nodeIn)\r\n at System.Web.OData.Query.Validators.OrderByQueryValidator.OrderByModelLimitationsValidator.TryValidate(OrderByClause orderByClause, Boolean explicitPropertiesDefined)\r\n at System.Web.OData.Query.Validators.OrderByQueryValidator.Validate(OrderByQueryOption orderByOption, ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.OrderByQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
•
Expected result
It should order the results by specified property
Actual result
*"message":"The method or operation is not implemented.","type":"System.NotImplementedException","stacktrace":" at Microsoft.OData.Core.UriParser.Visitors.QueryNodeVisitor`1.Visit(SingleEntityCastNode nodeIn)\r\n at System.Web.OData.Query.Validators.OrderByQueryValidator.OrderByModelLimitationsValidator.TryValidate(OrderByClause orderByClause, Boolean explicitPropertiesDefined)\r\n at System.Web.OData.Query.Validators.OrderByQueryValidator.Validate(OrderByQueryOption orderByOption, ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.OrderByQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
*
Breaks in following method in OrderByQueryValidator
public override SingleValueNode Visit(SingleValuePropertyAccessNode nodeIn)
{
if (EdmLibHelpers.IsNotSortable(nodeIn.Property, _model))
{
return nodeIn;
}
if (nodeIn.Source != null)
{
return nodeIn.Source.Accept(this);
}
return null;
}
I then added following condition which fixed the issue but I am sure if that's the correct solution hence, can someone please advise
public override SingleValueNode Visit(SingleValuePropertyAccessNode nodeIn)
{
if (EdmLibHelpers.IsNotSortable(nodeIn.Property, _model))
{
return nodeIn;
}
if (nodeIn.Source != null)
{
if(((SingleEntityCastNode)nodeIn.Source).EntityTypeReference != ((SingleEntityCastNode)nodeIn.Source).Source.EntityTypeReference)
{
return ((SingleEntityCastNode)nodeIn.Source).Source.Accept(this);
}
return nodeIn.Source.Accept(this);
}
return null;
}
Upvotes: 2
Views: 526
Reputation: 11
it's better to go directly to override Visit method of SingleEntityCastNode parameter, with this you avoid errors of other node types:
public override SingleValueNode Visit(SingleValuePropertyAccessNode nodeIn)
{
if (EdmLibHelpers_IsNotSortable(nodeIn.Property, _model))
{
return nodeIn;
}
if (nodeIn.Source != null)
{
return nodeIn.Source.Accept(this);
}
return null;
}
public override SingleValueNode Visit(SingleEntityCastNode nodeIn)
{
if (nodeIn.EntityTypeReference != nodeIn.Source.EntityTypeReference)
{
return nodeIn.Source.Accept(this);
}
return base.Visit(nodeIn);
}
Also see https://github.com/OData/WebApi/issues/861
Upvotes: 1