Skip to content

Commit

Permalink
Fix for bad ordering with $skiptoken enabled and `$orderby=... desc…
Browse files Browse the repository at this point in the history
…` when declaring an Edm model with lowercased or aliased properties (#1054)

Co-authored-by: Serge Aradj <[email protected]>
  • Loading branch information
orty and Serge Aradj authored Sep 25, 2023
1 parent fce1c61 commit 3e52f81
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private static IQueryable ApplyToCore(IQueryable query, ODataQuerySettings query
if (orderByNodes != null)
{
directionMap =
orderByNodes.OfType<OrderByPropertyNode>().ToDictionary(node => node.Property.Name, node => node.Direction);
orderByNodes.OfType<OrderByPropertyNode>().ToDictionary(node => context.Model.GetClrPropertyName(node.Property), node => node.Direction);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

namespace Microsoft.AspNetCore.OData.Tests.Query
{
using Microsoft.AspNetCore.Http;
using System.Reflection;
using System.Runtime.Serialization;

public class DefaultSkipTokenHandlerTests
Expand Down Expand Up @@ -315,6 +317,33 @@ public void ApplyToOfTDefaultSkipTokenHandler_Applies_WithAlias_ToQueryable()
"SkipCustomerId-2");
}

[Fact]
public void ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_ToQueryable()
{
ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_ToQueryable_Implementation(
_model,
"Name",
"Name-'Alex',Id-3");
}

[Fact]
public void ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_WithLowerCamelCase_ToQueryable()
{
ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_ToQueryable_Implementation(
_modelLowerCamelCased,
"name",
"name-'Alex',Id-3");
}

[Fact]
public void ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_WithAlias_ToQueryable()
{
ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_ToQueryable_Implementation(
_modelAliased,
"FirstAndLastName",
"FirstAndLastName-'Alex',SkipCustomerId-3");
}

private ODataSerializerContext GetSerializerContext(IEdmModel model, bool enableSkipToken = false)
{
IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers");
Expand Down Expand Up @@ -597,6 +626,53 @@ private static void ApplyToOfTDefaultSkipTokenHandler_Applies_ToQueryable_Implem
skipTokenCustomer.Name);
}

private static void ApplyToOfTDefaultSkipTokenHandler_Applies_WithOrderByDesc_ToQueryable_Implementation(
IEdmModel edmModel,
string orderByPropertyName,
string skipTokenQueryOptionRawValue)
{
// Arrange
ODataQuerySettings settings = new ODataQuerySettings {HandleNullPropagation = HandleNullPropagationOption.False};
ODataQueryContext context = new ODataQueryContext(
edmModel,
typeof(SkipCustomer));

HttpRequest request = RequestFactory.Create(
HttpMethods.Get,
$"http://server/service/Customers/?$orderby={orderByPropertyName} desc&$skiptoken={skipTokenQueryOptionRawValue}");

// Act
ODataQueryOptions oDataQueryOptions = new ODataQueryOptions(context, request);

SkipTokenQueryOption skipTokenQuery = new SkipTokenQueryOption(
skipTokenQueryOptionRawValue,
context);
DefaultSkipTokenHandler handler = new DefaultSkipTokenHandler();
IQueryable<SkipCustomer> customers = new List<SkipCustomer>
{
new SkipCustomer {Id = 2, Name = "Aaron"},
new SkipCustomer {Id = 1, Name = "Andy"},
new SkipCustomer {Id = 3, Name = "Alex"}
}.AsQueryable();

// Act
SkipCustomer[] results = handler.ApplyTo(
customers,
skipTokenQuery,
settings,
oDataQueryOptions)
.ToArray();

// Assert
SkipCustomer skipTokenCustomer = Assert.Single(results);
Assert.Equal(
2,
skipTokenCustomer.Id);
Assert.Equal(
"Aaron",
skipTokenCustomer.Name);
}

[DataContract]
public class SkipCustomer
{
Expand Down

0 comments on commit 3e52f81

Please sign in to comment.