From 4b5462e889d995b62b38f56d8621b5b654025f11 Mon Sep 17 00:00:00 2001 From: cuqmbr Date: Wed, 12 Oct 2022 12:42:08 +0300 Subject: [PATCH] feat: add sorting to countries controller --- Server/Helpers/ISortHelper.cs | 6 +++ Server/Helpers/SortHelper.cs | 46 +++++++++++++++++++ Server/Program.cs | 4 ++ Server/Server.csproj | 1 + Server/Services/CountryManagementService.cs | 27 +++++++++-- .../CountryParameters.cs | 9 +++- .../QueryStringParameters.cs | 1 + 7 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 Server/Helpers/ISortHelper.cs create mode 100644 Server/Helpers/SortHelper.cs diff --git a/Server/Helpers/ISortHelper.cs b/Server/Helpers/ISortHelper.cs new file mode 100644 index 0000000..71edabd --- /dev/null +++ b/Server/Helpers/ISortHelper.cs @@ -0,0 +1,6 @@ +namespace Server.Helpers; + +public interface ISortHelper +{ + IQueryable ApplySort(IQueryable entities, string? orderByQueryString); +} \ No newline at end of file diff --git a/Server/Helpers/SortHelper.cs b/Server/Helpers/SortHelper.cs new file mode 100644 index 0000000..79dad5d --- /dev/null +++ b/Server/Helpers/SortHelper.cs @@ -0,0 +1,46 @@ +using System.Linq.Dynamic.Core; +using System.Reflection; +using System.Text; + +namespace Server.Helpers; + +public class SortHelper : ISortHelper +{ + public IQueryable ApplySort(IQueryable entities, string? orderByQueryString) + { + if (!entities.Any() || String.IsNullOrWhiteSpace(orderByQueryString)) + { + return entities; + } + + var orderParams = orderByQueryString.Trim().Split(","); + var propertyInfos = + typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); + var orderQueryBuilder = new StringBuilder(); + + foreach (var param in orderParams) + { + if (string.IsNullOrWhiteSpace(param)) + { + continue; + } + + var propertyFromQueryName = param[0] == '-' || param[0] == '+' ? param.Substring(1) : param; + var objectProperty = propertyInfos.FirstOrDefault(pi => + pi.Name.Equals(propertyFromQueryName, StringComparison.InvariantCultureIgnoreCase)); + + if (objectProperty == null) + { + continue; + } + + var sortingOrder = param[0] == '-' ? "descending" : "ascending"; + + orderQueryBuilder.Append($"{objectProperty.Name} {sortingOrder}, "); + } + + var orderQuery = orderQueryBuilder.ToString().TrimEnd(',', ' '); + + return entities.OrderBy(orderQuery); + } +} \ No newline at end of file diff --git a/Server/Program.cs b/Server/Program.cs index f72a731..55e1cb0 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Server.Configurations; using Server.Data; +using Server.Helpers; using Server.Models; using Server.Services; @@ -82,8 +83,11 @@ builder.Services.AddAuthorization(); builder.Services.AddAutoMapper(typeof(MapperInitializer)); builder.Services.AddScoped(); + builder.Services.AddScoped(); +builder.Services.AddScoped, SortHelper>(); + // Adding DB Context with PostgreSQL var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => diff --git a/Server/Server.csproj b/Server/Server.csproj index f68f53f..581a306 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -27,6 +27,7 @@ + diff --git a/Server/Services/CountryManagementService.cs b/Server/Services/CountryManagementService.cs index e16c8ca..50c5dd7 100644 --- a/Server/Services/CountryManagementService.cs +++ b/Server/Services/CountryManagementService.cs @@ -1,7 +1,9 @@ +using System.Linq.Dynamic.Core; using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; using Server.Data; +using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; using SharedModels.QueryStringParameters; @@ -12,12 +14,14 @@ public class CountryManagementService : ICountryManagementService { private readonly ApplicationDbContext _dbContext; private readonly IMapper _mapper; + private readonly ISortHelper _countrySortHelper; public CountryManagementService(ApplicationDbContext dbContext, - IMapper mapper) + IMapper mapper, ISortHelper countrySortHelper) { _dbContext = dbContext; _mapper = mapper; + _countrySortHelper = countrySortHelper; } public async Task<(bool isSucceed, string message, CountryDto country)> AddCountry(CreateCountryDto createCountryDto) @@ -36,14 +40,27 @@ public class CountryManagementService : ICountryManagementService var dbCountries = _dbContext.Countries.AsQueryable(); SearchByAllCountryFields(ref dbCountries, parameters.Search); - SearchByCountryCode(ref dbCountries, parameters.CountryCode); - SearchByCountryName(ref dbCountries, parameters.CountryName); + SearchByCountryCode(ref dbCountries, parameters.Code); + SearchByCountryName(ref dbCountries, parameters.Name); + + try + { + dbCountries = _countrySortHelper.ApplySort(dbCountries, parameters.Sort); + + // By calling Any() we will check if LINQ to Entities Query will be + // executed. If not it will throw an InvalidOperationException exception + var isExecuted = dbCountries.Any(); + } + catch (Exception e) + { + return (false, "Invalid sorting string", null, null)!; + } var pagingMetadata = ApplyPaging(ref dbCountries, parameters.PageNumber, parameters.PageSize); - var countryDtos = dbCountries.ToList() - .ConvertAll(c => _mapper.Map(c)); + var countryDtos = + dbCountries.ProjectTo(_mapper.ConfigurationProvider); return (true, "", countryDtos, pagingMetadata); diff --git a/SharedModels/QueryStringParameters/CountryParameters.cs b/SharedModels/QueryStringParameters/CountryParameters.cs index e4227b7..291be52 100644 --- a/SharedModels/QueryStringParameters/CountryParameters.cs +++ b/SharedModels/QueryStringParameters/CountryParameters.cs @@ -2,6 +2,11 @@ namespace SharedModels.QueryStringParameters; public class CountryParameters : QueryStringParameters { - public string? CountryCode { get; set; } - public string? CountryName { get; set; } + public CountryParameters() + { + Sort = "id"; + } + + public string? Code { get; set; } + public string? Name { get; set; } } \ No newline at end of file diff --git a/SharedModels/QueryStringParameters/QueryStringParameters.cs b/SharedModels/QueryStringParameters/QueryStringParameters.cs index 5623baa..65ebd22 100644 --- a/SharedModels/QueryStringParameters/QueryStringParameters.cs +++ b/SharedModels/QueryStringParameters/QueryStringParameters.cs @@ -13,4 +13,5 @@ public class QueryStringParameters } public string? Search { get; set; } + public string? Sort { get; set; } } \ No newline at end of file