Skip to content

Commit 2b31741

Browse files
committed
Extend the OrderBy capabilities with comma separated support for then by
1 parent 13d89ec commit 2b31741

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

NorthwindCRUD/Controllers/ProductsController.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ public ActionResult<ProductDto[]> GetAll()
5050
/// <summary>
5151
/// Fetches all products or a page of products based on the provided parameters.
5252
/// </summary>
53-
/// <param name="skip">Previously called pageNumber. The number of the page to fetch. If this parameter is not provided, all products are fetched.</param>
54-
/// <param name="top">Previously called pageSize. The size of the page to fetch. If this parameter is not provided, all products are fetched.</param>
55-
/// <param name="orderBy">The fields to order by, in the format "field1 asc, field2 desc". If not provided, defaults to no specific order.</param>
53+
/// <param name="skip">The number of records to skip before starting to fetch the products. If this parameter is not provided, fetching starts from the beginning.</param>
54+
/// <param name="top">The maximum number of products to fetch. If this parameter is not provided, all products are fetched.</param>
55+
/// <param name="orderBy">A comma-separated list of fields to order the products by, along with the sort direction (e.g., "field1 asc, field2 desc").</param>
5656
/// <returns>A PagedResultDto object containing the fetched T and the total record count.</returns>
57-
[HttpGet("GetAllPagedProducts")]
57+
[HttpGet("GetPagedProducts")]
5858
public ActionResult<PagedResultDto<ProductDto>> GetAllProducts(int? skip, int? top, string? orderBy)
5959
{
6060
try

NorthwindCRUD/Services/PagingService.cs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Globalization;
2+
using System.Linq.Expressions;
23
using System.Reflection;
34
using AutoMapper;
45
using Microsoft.AspNetCore.Mvc.RazorPages;
@@ -32,18 +33,7 @@ public PagedResultDto<TDto> GetPagedData<TEntity, TDto>(IEnumerable<TEntity> dat
3233
// Apply ordering if specified
3334
if (!string.IsNullOrEmpty(orderBy))
3435
{
35-
var orderByParts = orderBy.Split(' ');
36-
var field = orderByParts[0];
37-
var order = orderByParts.Length > 1 ? orderByParts[1] : "ASC";
38-
39-
var propertyInfo = typeof(TEntity).GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
40-
41-
if (propertyInfo != null)
42-
{
43-
dataArray = order.ToUpper(CultureInfo.InvariantCulture) == "DESC"
44-
? dataArray.OrderByDescending(e => propertyInfo.GetValue(e, null)).ToArray()
45-
: dataArray.OrderBy(e => propertyInfo.GetValue(e, null)).ToArray();
46-
}
36+
dataArray = ApplyOrdering(dataArray.AsQueryable(), orderBy).ToArray();
4737
}
4838

4939
// Apply pagination
@@ -67,5 +57,46 @@ public PagedResultDto<TDto> GetPagedData<TEntity, TDto>(IEnumerable<TEntity> dat
6757
TotalPages = totalPages,
6858
};
6959
}
60+
61+
private IQueryable<TEntity> ApplyOrdering<TEntity>(IQueryable<TEntity> source, string orderBy)
62+
{
63+
var orderParams = orderBy.Split(',');
64+
65+
IOrderedQueryable<TEntity>? orderedQuery = null;
66+
67+
foreach (var param in orderParams)
68+
{
69+
var trimmedParam = param.Trim();
70+
var orderByParts = trimmedParam.Split(' ');
71+
var field = orderByParts[0];
72+
var order = orderByParts.Length > 1 ? orderByParts[1] : "asc";
73+
74+
var propertyInfo = typeof(TEntity).GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
75+
76+
if (propertyInfo != null)
77+
{
78+
var parameter = Expression.Parameter(typeof(TEntity), "x");
79+
var property = Expression.Property(parameter, propertyInfo);
80+
var lambda = Expression.Lambda(property, parameter);
81+
82+
var methodName = order.ToUpper(CultureInfo.InvariantCulture) == "DESC"
83+
? (orderedQuery == null ? "OrderByDescending" : "ThenByDescending")
84+
: (orderedQuery == null ? "OrderBy" : "ThenBy");
85+
86+
var resultExpression = Expression.Call(
87+
typeof(Queryable),
88+
methodName,
89+
new Type[] { source.ElementType, property.Type },
90+
(orderedQuery ?? source).Expression,
91+
Expression.Quote(lambda));
92+
93+
orderedQuery = (IOrderedQueryable<TEntity>)(orderedQuery == null
94+
? source.Provider.CreateQuery<TEntity>(resultExpression)
95+
: orderedQuery.Provider.CreateQuery<TEntity>(resultExpression));
96+
}
97+
}
98+
99+
return orderedQuery ?? source;
100+
}
70101
}
71102
}

0 commit comments

Comments
 (0)