Skip to content

Commit e1f7d40

Browse files
committed
Refactor the code to be generic
1 parent c4401c5 commit e1f7d40

File tree

5 files changed

+91
-58
lines changed

5 files changed

+91
-58
lines changed

NorthwindCRUD/Controllers/ProductsController.cs

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@ public class ProductsController : ControllerBase
1717
private readonly CategoryService categoryService;
1818
private readonly OrderService orderService;
1919
private readonly SupplierService supplierService;
20+
private readonly PagingService pagingService;
2021
private readonly IMapper mapper;
2122
private readonly ILogger<ProductsController> logger;
2223

23-
public ProductsController(ProductService productService, CategoryService categoryService, OrderService orderService, SupplierService supplierService, IMapper mapper, ILogger<ProductsController> logger)
24+
public ProductsController(ProductService productService, CategoryService categoryService, OrderService orderService, SupplierService supplierService, PagingService pagingService, IMapper mapper, ILogger<ProductsController> logger)
2425
{
2526
this.productService = productService;
2627
this.categoryService = categoryService;
2728
this.orderService = orderService;
2829
this.supplierService = supplierService;
30+
this.pagingService = pagingService;
2931
this.mapper = mapper;
3032
this.logger = logger;
3133
}
@@ -51,57 +53,31 @@ public ActionResult<ProductDto[]> GetAll()
5153
/// <param name="skip">Previously called pageNumber. The number of the page to fetch. If this parameter is not provided, all products are fetched.</param>
5254
/// <param name="top">Previously called pageSize. The size of the page to fetch. If this parameter is not provided, all products are fetched.</param>
5355
/// <param name="orderBy">The fields to order by, in the format "field1 asc, field2 desc". If not provided, defaults to no specific order.</param>
54-
/// <returns>A PagedProductsDto object containing the fetched products and the total record count.</returns>
56+
/// <returns>A PagedResultDto object containing the fetched T and the total record count.</returns>
5557
[HttpGet("GetAllPagedProducts")]
56-
public ActionResult<PagedProductsDto> GetAllProducts(int? skip, int? top, string? orderBy)
58+
public ActionResult<PagedResultDto<ProductDto>> GetAllProducts(int? skip, int? top, string? orderBy)
5759
{
5860
try
5961
{
6062
// Retrieve all products
6163
var products = this.productService.GetAll();
62-
var totalRecords = products.Length;
6364

64-
// Default skip and top if not provided
65-
int skipRecordsAmount = skip ?? 0;
66-
int currentSize = top ?? totalRecords;
65+
// Get paged data
66+
var pagedResult = pagingService.GetPagedData(products, skip, top, orderBy);
6767

68-
// Apply ordering if specified
69-
if (!string.IsNullOrEmpty(orderBy))
70-
{
71-
var orderByParts = orderBy.Split(' ');
72-
var field = orderByParts[0];
73-
var order = orderByParts.Length > 1 ? orderByParts[1] : "ASC";
74-
75-
// Get the property info of the field to order by
76-
var propertyInfo = products.First().GetType().GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
77-
78-
// Use dynamic LINQ to sort based on field and order
79-
products = order.ToUpper(CultureInfo.InvariantCulture) == "DESC"
80-
? products.OrderByDescending(e => propertyInfo?.GetValue(e, null)).ToArray()
81-
: products.OrderBy(e => propertyInfo?.GetValue(e, null)).ToArray();
82-
}
83-
84-
// Apply pagination
85-
var pagedProducts = products
86-
.Skip(skipRecordsAmount)
87-
.Take(currentSize)
88-
.ToArray();
89-
90-
// Calculate total pages
91-
int totalPages = (int)Math.Ceiling(totalRecords / (double)currentSize);
68+
// Map the results to ProductDto
69+
var productDtos = this.mapper.Map<ProductDto[]>(pagedResult.Items);
9270

93-
// Create and return the product collection
94-
var productCollection = new PagedProductsDto
71+
var result = new PagedResultDto<ProductDto>
9572
{
96-
// Check if both pageNumber and pageSize are null, if so, return all products
97-
Products = this.mapper.Map<ProductDb[], ProductDto[]>(pagedProducts),
98-
TotalRecordsCount = totalRecords,
99-
PageSize = currentSize,
100-
PageNumber = (skipRecordsAmount / currentSize) + 1,
101-
TotalPages = totalPages,
73+
Items = productDtos,
74+
TotalRecordsCount = pagedResult.TotalRecordsCount,
75+
PageSize = pagedResult.PageSize,
76+
PageNumber = pagedResult.PageNumber,
77+
TotalPages = pagedResult.TotalPages,
10278
};
10379

104-
return Ok(productCollection);
80+
return Ok(result);
10581
}
10682
catch (Exception error)
10783
{
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace NorthwindCRUD.Models.Dtos
2+
{
3+
public class PagedResultDto<T>
4+
{
5+
public T[] Items { get; set; }
6+
7+
public int TotalRecordsCount { get; set; }
8+
9+
public int PageSize { get; set; }
10+
11+
public int PageNumber { get; set; }
12+
13+
public int TotalPages { get; set; }
14+
}
15+
}

NorthwindCRUD/Models/Dtos/ProductDtoCollection.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

NorthwindCRUD/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public static void Main(string[] args)
142142
builder.Services.AddTransient<SupplierService>();
143143
builder.Services.AddTransient<TerritoryService>();
144144
builder.Services.AddTransient<SalesService>();
145+
builder.Services.AddTransient<PagingService>();
145146

146147
var app = builder.Build();
147148

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Globalization;
2+
using System.Reflection;
3+
using NorthwindCRUD.Models.Dtos;
4+
5+
namespace NorthwindCRUD.Services
6+
{
7+
public interface IPagingService
8+
{
9+
PagedResultDto<T> GetPagedData<T>(IEnumerable<T> data, int? skip, int? top, string? orderBy);
10+
}
11+
12+
public class PagingService : IPagingService
13+
{
14+
public PagedResultDto<T> GetPagedData<T>(IEnumerable<T> data, int? skip, int? top, string? orderBy)
15+
{
16+
var dataArray = data.ToArray();
17+
var totalRecords = dataArray.Length;
18+
19+
// Default skip and top if not provided
20+
int skipRecordsAmount = skip ?? 0;
21+
int currentSize = top ?? totalRecords;
22+
23+
// Apply ordering if specified
24+
if (!string.IsNullOrEmpty(orderBy))
25+
{
26+
var orderByParts = orderBy.Split(' ');
27+
var field = orderByParts[0];
28+
var order = orderByParts.Length > 1 ? orderByParts[1] : "ASC";
29+
30+
var propertyInfo = typeof(T).GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
31+
32+
if (propertyInfo != null)
33+
{
34+
dataArray = order.ToUpper(CultureInfo.InvariantCulture) == "DESC"
35+
? dataArray.OrderByDescending(e => propertyInfo.GetValue(e, null)).ToArray()
36+
: dataArray.OrderBy(e => propertyInfo.GetValue(e, null)).ToArray();
37+
}
38+
}
39+
40+
// Apply pagination
41+
var pagedData = dataArray
42+
.Skip(skipRecordsAmount)
43+
.Take(currentSize)
44+
.ToArray();
45+
46+
// Calculate total pages
47+
int totalPages = (int)Math.Ceiling(totalRecords / (double)currentSize);
48+
49+
return new PagedResultDto<T>
50+
{
51+
Items = pagedData,
52+
TotalRecordsCount = totalRecords,
53+
PageSize = currentSize,
54+
PageNumber = (skipRecordsAmount / currentSize) + 1,
55+
TotalPages = totalPages,
56+
};
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)