From 2055c2f89ac82050c722901c5a3fc9175a2f3a12 Mon Sep 17 00:00:00 2001 From: Ishit Parikh Date: Tue, 19 Oct 2021 15:53:28 +0530 Subject: [PATCH 1/3] Added a boolean param in Filter to support case-insensitive filter for strings and operators - StartsWith, EndsWith, Contains and Doesnotcontain --- src/Filter.cs | 8 ++-- src/QueryableExtensions.cs | 20 ++++----- .../Data/MockContext.cs | 41 +++++++++++-------- .../Kendo.DynamicLinqCore.Tests/FilterTest.cs | 32 ++++++++++++++- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/Filter.cs b/src/Filter.cs index a711ba1..0f54294 100644 --- a/src/Filter.cs +++ b/src/Filter.cs @@ -111,11 +111,11 @@ private void Collect(IList filters) /// Converts the filter expression to a predicate suitable for Dynamic Linq e.g. "Field1 = @1 and Field2.Contains(@2)" /// /// A list of flattened filters. - public string ToExpression(Type type, IList filters) + public string ToExpression(Type type, IList filters, bool isCaseSensitive) { if (Filters?.Any() == true) { - return "(" + String.Join(" " + Logic + " ", Filters.Select(filter => filter.ToExpression(type,filters)).ToArray()) + ")"; + return "(" + String.Join(" " + Logic + " ", Filters.Select(filter => filter.ToExpression(type,filters,isCaseSensitive)).ToArray()) + ")"; } var currentPropertyType = GetLastPropertyType(type, Field); @@ -144,7 +144,7 @@ public string ToExpression(Type type, IList filters) if (Operator == "doesnotcontain") { - return String.Format("{0} != null && !{0}.{1}(@{2})", Field, comparison, index); + return String.Format(isCaseSensitive ? "{0} != null && !{0}.{1}(@{2})" : "{0} != null && !{0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } if (Operator == "isnull" || Operator == "isnotnull") @@ -164,7 +164,7 @@ public string ToExpression(Type type, IList filters) if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains") { - return String.Format("{0} != null && {0}.{1}(@{2})", Field, comparison, index); + return String.Format(isCaseSensitive ? "{0} != null && {0}.{1}(@{2})" : "{0} != null && {0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } return String.Format("{0} {1} @{2}", Field, comparison, index); diff --git a/src/QueryableExtensions.cs b/src/QueryableExtensions.cs index f927a48..85ef9da 100644 --- a/src/QueryableExtensions.cs +++ b/src/QueryableExtensions.cs @@ -20,9 +20,9 @@ public static class QueryableExtensions /// Specifies the current sort order. /// Specifies the current filter. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, bool isCaseSensitive = false) { - return queryable.ToDataSourceResult(take, skip, sort, filter, null, null); + return queryable.ToDataSourceResult(take, skip, sort, filter, null, null, isCaseSensitive); } /// @@ -32,9 +32,9 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// The IQueryable which should be processed. /// The DataSourceRequest object containing take, skip, sort, filter, aggregates, and groups data. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, DataSourceRequest request) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, DataSourceRequest request, bool isCaseSensitive = false) { - return queryable.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter, request.Aggregate, request.Group); + return queryable.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter, request.Aggregate, request.Group, isCaseSensitive); } /// @@ -49,12 +49,12 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// Specifies the current aggregates. /// Specifies the current groups. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates, IEnumerable group) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates, IEnumerable group, bool isCaseSensitive = false) { var errors = new List(); // Filter the data first - queryable = Filters(queryable, filter, errors); + queryable = Filters(queryable, filter, errors, isCaseSensitive); // Calculate the total number of records (needed for paging) var total = queryable.Count(); @@ -124,12 +124,12 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// Specifies the current aggregates. /// Specifies the current groups. /// A DataSourceResult object populated from the processed IQueryable. - public static Task ToDataSourceResultAsync(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates = null, IEnumerable group = null) + public static Task ToDataSourceResultAsync(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates = null, IEnumerable group = null, bool isCaseSensitive = false) { - return Task.Run(() => queryable.ToDataSourceResult(take, skip, sort, filter, aggregates, group)); + return Task.Run(() => queryable.ToDataSourceResult(take, skip, sort, filter, aggregates, group, isCaseSensitive)); } - private static IQueryable Filters(IQueryable queryable, Filter filter, List errors) + private static IQueryable Filters(IQueryable queryable, Filter filter, List errors, bool isCaseSensitive) { if (filter?.Logic != null) { @@ -144,7 +144,7 @@ private static IQueryable Filters(IQueryable queryable, Filter filter, string predicate; try { - predicate = filter.ToExpression(typeof(T), filters); + predicate = filter.ToExpression(typeof(T), filters, isCaseSensitive); } catch(Exception ex) { diff --git a/test/Kendo.DynamicLinqCore.Tests/Data/MockContext.cs b/test/Kendo.DynamicLinqCore.Tests/Data/MockContext.cs index d3092db..e456069 100644 --- a/test/Kendo.DynamicLinqCore.Tests/Data/MockContext.cs +++ b/test/Kendo.DynamicLinqCore.Tests/Data/MockContext.cs @@ -15,7 +15,7 @@ public class MockContext : DbContext public static MockContext GetDefaultInMemoryDbContext() { - if(_defaultDbContext != null) return _defaultDbContext; + if (_defaultDbContext != null) return _defaultDbContext; var serviceProvider = new ServiceCollection().AddDbContext(options => options.UseLazyLoadingProxies().UseInMemoryDatabase("Kendo")).BuildServiceProvider(); @@ -34,7 +34,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { // Add employee data modelBuilder.Entity().HasData( - new Employee { + new Employee + { Number = 1, Name = "Monie", Identification = Guid.Parse("ff5f9bb3-f805-4f52-a5f9-fbd0493d5b8f"), @@ -42,10 +43,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Weight = 48.5, Salary = 1000, Gender = Gender.F, - Birthday = new DateTime(2000,5,5), + Birthday = new DateTime(2000, 5, 5), CompanyId = Guid.Parse("c2cbfe28-f82a-4904-8075-bf98729d434f") }, - new Employee { + new Employee + { Number = 2, Identification = Guid.Parse("a3ee172c-fdf3-4390-9bb1-d5a70ccfbb3b"), Name = "CoCo", @@ -53,20 +55,22 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Salary = 2500, Weight = 69.2, Gender = Gender.M, - Birthday = new DateTime(1986,10,10), + Birthday = new DateTime(1986, 10, 9, 16, 0, 0), CompanyId = Guid.Parse("c2cbfe28-f82a-4904-8075-bf98729d434f") }, - new Employee { + new Employee + { Number = 3, Identification = Guid.Parse("aad8a5ec-9b5a-4c5f-9d3b-d7a39df6392f"), Name = "Kirin", Introduce = "I'm Kirin", Weight = 73.8, Gender = Gender.M, - Birthday = new DateTime(1984,7,8), + Birthday = new DateTime(1984, 7, 8), CompanyId = Guid.Parse("5dd641dd-2ba4-4dfd-9572-81325ecd8940") }, - new Employee { + new Employee + { Number = 4, Identification = Guid.Parse("a4e918a9-46f9-4a13-8f37-e8771bf7dc5c"), Name = "Rock", @@ -74,10 +78,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Salary = 1750, Weight = 82.1, Gender = Gender.M, - Birthday = new DateTime(1976,11,6), + Birthday = new DateTime(1976, 11, 5, 16, 0, 0), CompanyId = Guid.Parse("80a6570c-ca98-4661-adde-e4d5a8637ee5") }, - new Employee { + new Employee + { Number = 5, Identification = Guid.Parse("3e5f4514-1a3f-402a-8e97-a2fa95ccb91b"), Name = "Pikachu", @@ -85,10 +90,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Salary = 6600, Weight = 52.9, Gender = Gender.P, - Birthday = new DateTime(2005,3,16), + Birthday = new DateTime(2005, 3, 16), CompanyId = Guid.Parse("80a6570c-ca98-4661-adde-e4d5a8637ee5") }, - new Employee { + new Employee + { Number = 6, Identification = Guid.Parse("0814bceb-3481-49c6-8dfb-0a398f2b55f3"), Name = "Zed", @@ -96,22 +102,25 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Salary = 3000, Weight = 71.6, Gender = Gender.M, - Birthday = new DateTime(2003,1,22), + Birthday = new DateTime(2003, 1, 22), CompanyId = Guid.Parse("80a6570c-ca98-4661-adde-e4d5a8637ee5") } ); // Add company data modelBuilder.Entity().HasData( - new Company { + new Company + { Id = Guid.Parse("c2cbfe28-f82a-4904-8075-bf98729d434f"), Name = "Microsoft" }, - new Company { + new Company + { Id = Guid.Parse("5dd641dd-2ba4-4dfd-9572-81325ecd8940"), Name = "Google" }, - new Company { + new Company + { Id = Guid.Parse("80a6570c-ca98-4661-adde-e4d5a8637ee5"), Name = "Apple" } diff --git a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs index 5f7c64c..a7b2802 100644 --- a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs +++ b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs @@ -35,7 +35,7 @@ public void InputParameter_SubPropertyContains_CheckResultCount() Value = "Microsoft", Operator = "contains", Logic = "and" - }); + }, true); Assert.AreEqual(2, result.Total); @@ -50,6 +50,36 @@ public void InputParameter_SubPropertyContains_CheckResultCount() } }, Logic = "and" + }, true); + + Assert.AreEqual(2, result2.Total); + } + + [Test] + public void InputParameter_SubPropertyContains_Case_Insensitive_CheckResultCount() + { + var result = _dbContext.Employee.Include(x => x.Company).AsQueryable().ToDataSourceResult(10, 0, null, new Filter + { + Field = "Company.Name", + Value = "microsoft", + Operator = "contains", + Logic = "and" + }); + + Assert.AreEqual(2, result.Total); + + var result2 = _dbContext.Employee.AsQueryable().ToDataSourceResult(10, 0, null, new Filter + { + Filters = new[] + { + new Filter + { + Field ="Company.Name", + Operator = "contains", + Value = "microsoft" + } + }, + Logic = "and" }); Assert.AreEqual(2, result2.Total); From 39b7ab9ff37220061a494238af53e015b719e883 Mon Sep 17 00:00:00 2001 From: Ishit Parikh Date: Tue, 19 Oct 2021 18:06:26 +0530 Subject: [PATCH 2/3] Support for the ignoreCase like property same as Kendo UI angular --- src/Filter.cs | 14 ++++-- src/QueryableExtensions.cs | 20 ++++---- .../Kendo.DynamicLinqCore.Tests/FilterTest.cs | 48 ++++++++++--------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/Filter.cs b/src/Filter.cs index 0f54294..c16da40 100644 --- a/src/Filter.cs +++ b/src/Filter.cs @@ -37,6 +37,12 @@ public class Filter [DataMember(Name = "logic")] public string Logic { get; set; } + /// + /// Gets or sets the filtering logic. Can be set to "or" or "and". Set to null unless Filters is set. + /// + [DataMember(Name = "ignoreCase")] + public bool ignoreCase { get; set; } + /// /// Gets or sets the child filter expressions. Set to null if there are no child expressions. /// @@ -111,11 +117,11 @@ private void Collect(IList filters) /// Converts the filter expression to a predicate suitable for Dynamic Linq e.g. "Field1 = @1 and Field2.Contains(@2)" /// /// A list of flattened filters. - public string ToExpression(Type type, IList filters, bool isCaseSensitive) + public string ToExpression(Type type, IList filters) { if (Filters?.Any() == true) { - return "(" + String.Join(" " + Logic + " ", Filters.Select(filter => filter.ToExpression(type,filters,isCaseSensitive)).ToArray()) + ")"; + return "(" + String.Join(" " + Logic + " ", Filters.Select(filter => filter.ToExpression(type,filters)).ToArray()) + ")"; } var currentPropertyType = GetLastPropertyType(type, Field); @@ -144,7 +150,7 @@ public string ToExpression(Type type, IList filters, bool isCaseSensitiv if (Operator == "doesnotcontain") { - return String.Format(isCaseSensitive ? "{0} != null && !{0}.{1}(@{2})" : "{0} != null && !{0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); + return String.Format(!ignoreCase ? "{0} != null && !{0}.{1}(@{2})" : "{0} != null && !{0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } if (Operator == "isnull" || Operator == "isnotnull") @@ -164,7 +170,7 @@ public string ToExpression(Type type, IList filters, bool isCaseSensitiv if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains") { - return String.Format(isCaseSensitive ? "{0} != null && {0}.{1}(@{2})" : "{0} != null && {0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); + return String.Format(!ignoreCase ? "{0} != null && {0}.{1}(@{2})" : "{0} != null && {0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } return String.Format("{0} {1} @{2}", Field, comparison, index); diff --git a/src/QueryableExtensions.cs b/src/QueryableExtensions.cs index 85ef9da..f927a48 100644 --- a/src/QueryableExtensions.cs +++ b/src/QueryableExtensions.cs @@ -20,9 +20,9 @@ public static class QueryableExtensions /// Specifies the current sort order. /// Specifies the current filter. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, bool isCaseSensitive = false) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter) { - return queryable.ToDataSourceResult(take, skip, sort, filter, null, null, isCaseSensitive); + return queryable.ToDataSourceResult(take, skip, sort, filter, null, null); } /// @@ -32,9 +32,9 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// The IQueryable which should be processed. /// The DataSourceRequest object containing take, skip, sort, filter, aggregates, and groups data. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, DataSourceRequest request, bool isCaseSensitive = false) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, DataSourceRequest request) { - return queryable.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter, request.Aggregate, request.Group, isCaseSensitive); + return queryable.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter, request.Aggregate, request.Group); } /// @@ -49,12 +49,12 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// Specifies the current aggregates. /// Specifies the current groups. /// A DataSourceResult object populated from the processed IQueryable. - public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates, IEnumerable group, bool isCaseSensitive = false) + public static DataSourceResult ToDataSourceResult(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates, IEnumerable group) { var errors = new List(); // Filter the data first - queryable = Filters(queryable, filter, errors, isCaseSensitive); + queryable = Filters(queryable, filter, errors); // Calculate the total number of records (needed for paging) var total = queryable.Count(); @@ -124,12 +124,12 @@ public static DataSourceResult ToDataSourceResult(this IQueryable queryabl /// Specifies the current aggregates. /// Specifies the current groups. /// A DataSourceResult object populated from the processed IQueryable. - public static Task ToDataSourceResultAsync(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates = null, IEnumerable group = null, bool isCaseSensitive = false) + public static Task ToDataSourceResultAsync(this IQueryable queryable, int take, int skip, IEnumerable sort, Filter filter, IEnumerable aggregates = null, IEnumerable group = null) { - return Task.Run(() => queryable.ToDataSourceResult(take, skip, sort, filter, aggregates, group, isCaseSensitive)); + return Task.Run(() => queryable.ToDataSourceResult(take, skip, sort, filter, aggregates, group)); } - private static IQueryable Filters(IQueryable queryable, Filter filter, List errors, bool isCaseSensitive) + private static IQueryable Filters(IQueryable queryable, Filter filter, List errors) { if (filter?.Logic != null) { @@ -144,7 +144,7 @@ private static IQueryable Filters(IQueryable queryable, Filter filter, string predicate; try { - predicate = filter.ToExpression(typeof(T), filters, isCaseSensitive); + predicate = filter.ToExpression(typeof(T), filters); } catch(Exception ex) { diff --git a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs index a7b2802..4009063 100644 --- a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs +++ b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs @@ -17,9 +17,9 @@ public class FilterTest { private MockContext _dbContext; - #if NETCOREAPP3_1 +#if NETCOREAPP3_1 private JsonSerializerOptions jsonSerializerOptions = CustomJsonSerializerOptions.DefaultOptions; - #endif +#endif [SetUp] public void Setup() @@ -30,17 +30,19 @@ public void Setup() [Test] public void InputParameter_SubPropertyContains_CheckResultCount() { - var result = _dbContext.Employee.Include(x=>x.Company).AsQueryable().ToDataSourceResult(10, 0, null, new Filter { - Field ="Company.Name", + var result = _dbContext.Employee.Include(x => x.Company).AsQueryable().ToDataSourceResult(10, 0, null, new Filter + { + Field = "Company.Name", Value = "Microsoft", Operator = "contains", Logic = "and" - }, true); + }); Assert.AreEqual(2, result.Total); - var result2 = _dbContext.Employee.AsQueryable().ToDataSourceResult(10, 0, null, new Filter { - Filters = new [] + var result2 = _dbContext.Employee.AsQueryable().ToDataSourceResult(10, 0, null, new Filter + { + Filters = new[] { new Filter { @@ -50,7 +52,7 @@ public void InputParameter_SubPropertyContains_CheckResultCount() } }, Logic = "and" - }, true); + }); Assert.AreEqual(2, result2.Total); } @@ -63,7 +65,8 @@ public void InputParameter_SubPropertyContains_Case_Insensitive_CheckResultCount Field = "Company.Name", Value = "microsoft", Operator = "contains", - Logic = "and" + Logic = "and", + ignoreCase = true, }); Assert.AreEqual(2, result.Total); @@ -76,7 +79,8 @@ public void InputParameter_SubPropertyContains_Case_Insensitive_CheckResultCount { Field ="Company.Name", Operator = "contains", - Value = "microsoft" + Value = "microsoft", + ignoreCase = true, } }, Logic = "and" @@ -90,11 +94,11 @@ public void InputDataSourceRequest_DecimalGreaterAndLess_CheckResultCount() { // source string = {"take":20,"skip":0,"filter":{"logic":"and","filters":[{"field":"Salary","operator":"gt","value":999.00},{"field":"Salary","operator":"lt","value":6000.00}]}} - #if NETCOREAPP3_1 +#if NETCOREAPP3_1 var request = JsonSerializer.Deserialize("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gt\",\"value\":999.00},{\"field\":\"Salary\",\"operator\":\"lt\",\"value\":6000.00}]}}", jsonSerializerOptions); - #else - var request = JsonConvert.DeserializeObject("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gt\",\"value\":999.00},{\"field\":\"Salary\",\"operator\":\"lt\",\"value\":6000.00}]}}"); - #endif +#else + var request = JsonConvert.DeserializeObject("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gt\",\"value\":999.00},{\"field\":\"Salary\",\"operator\":\"lt\",\"value\":6000.00}]}}"); +#endif var result = _dbContext.Employee.AsQueryable().ToDataSourceResult(request); Assert.AreEqual(4, result.Total); @@ -105,11 +109,11 @@ public void InputDataSourceRequest_DoubleGreaterAndLessEqual_CheckResultCount() { // source string = {"take":20,"skip":0,"filter":{"logic":"and","filters":[{"field":"Weight","operator":"gt","value":48},{"field":"Weight","operator":"lt","value":69.2}]}} - #if NETCOREAPP3_1 +#if NETCOREAPP3_1 var request = JsonSerializer.Deserialize("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Weight\",\"operator\":\"gt\",\"value\":48},{\"field\":\"Weight\",\"operator\":\"lte\",\"value\":69.2}]}}", jsonSerializerOptions); - #else - var request = JsonConvert.DeserializeObject("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Weight\",\"operator\":\"gt\",\"value\":48},{\"field\":\"Weight\",\"operator\":\"lte\",\"value\":69.2}]}}"); - #endif +#else + var request = JsonConvert.DeserializeObject("{\"take\":20,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"field\":\"Weight\",\"operator\":\"gt\",\"value\":48},{\"field\":\"Weight\",\"operator\":\"lte\",\"value\":69.2}]}}"); +#endif var result = _dbContext.Employee.AsQueryable().ToDataSourceResult(request); Assert.AreEqual(3, result.Total); @@ -120,11 +124,11 @@ public void InputDataSourceRequest_ManyConditions_CheckResultCount() { // source string = {\"take\":10,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"logic\":\"or\",\"filters\":[{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1986-10-09T16:00:00.000Z\"},{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1976-11-05T16:00:00.000Z\"}]},{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gte\",\"value\":1000},{\"field\":\"Salary\",\"operator\":\"lte\",\"value\":6000}]}]}} - #if NETCOREAPP3_1 +#if NETCOREAPP3_1 var request = JsonSerializer.Deserialize("{\"take\":10,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"logic\":\"or\",\"filters\":[{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1986-10-09T16:00:00.000Z\"},{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1976-11-05T16:00:00.000Z\"}]},{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gte\",\"value\":1000},{\"field\":\"Salary\",\"operator\":\"lte\",\"value\":6000}]}]}}", jsonSerializerOptions); - #else - var request = JsonConvert.DeserializeObject("{\"take\":10,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"logic\":\"or\",\"filters\":[{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1986-10-09T16:00:00.000Z\"},{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1976-11-05T16:00:00.000Z\"}]},{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gte\",\"value\":1000},{\"field\":\"Salary\",\"operator\":\"lte\",\"value\":6000}]}]}}"); - #endif +#else + var request = JsonConvert.DeserializeObject("{\"take\":10,\"skip\":0,\"filter\":{\"logic\":\"and\",\"filters\":[{\"logic\":\"or\",\"filters\":[{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1986-10-09T16:00:00.000Z\"},{\"field\":\"Birthday\",\"operator\":\"eq\",\"value\":\"1976-11-05T16:00:00.000Z\"}]},{\"logic\":\"and\",\"filters\":[{\"field\":\"Salary\",\"operator\":\"gte\",\"value\":1000},{\"field\":\"Salary\",\"operator\":\"lte\",\"value\":6000}]}]}}"); +#endif var result = _dbContext.Employee.AsQueryable().ToDataSourceResult(request); Assert.AreEqual(2, result.Total); From 7a7dc261ae605bd391dca3a36bdbc62418758b13 Mon Sep 17 00:00:00 2001 From: Ishit Parikh Date: Wed, 20 Oct 2021 16:52:31 +0530 Subject: [PATCH 3/3] Changed property name from camelcase to pascalcase --- src/Filter.cs | 6 +++--- test/Kendo.DynamicLinqCore.Tests/FilterTest.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Filter.cs b/src/Filter.cs index c16da40..8d3bc7f 100644 --- a/src/Filter.cs +++ b/src/Filter.cs @@ -41,7 +41,7 @@ public class Filter /// Gets or sets the filtering logic. Can be set to "or" or "and". Set to null unless Filters is set. /// [DataMember(Name = "ignoreCase")] - public bool ignoreCase { get; set; } + public bool IgnoreCase { get; set; } /// /// Gets or sets the child filter expressions. Set to null if there are no child expressions. @@ -150,7 +150,7 @@ public string ToExpression(Type type, IList filters) if (Operator == "doesnotcontain") { - return String.Format(!ignoreCase ? "{0} != null && !{0}.{1}(@{2})" : "{0} != null && !{0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); + return String.Format(!IgnoreCase ? "{0} != null && !{0}.{1}(@{2})" : "{0} != null && !{0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } if (Operator == "isnull" || Operator == "isnotnull") @@ -170,7 +170,7 @@ public string ToExpression(Type type, IList filters) if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains") { - return String.Format(!ignoreCase ? "{0} != null && {0}.{1}(@{2})" : "{0} != null && {0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); + return String.Format(!IgnoreCase ? "{0} != null && {0}.{1}(@{2})" : "{0} != null && {0}.ToLower().{1}(@{2}.ToLower())", Field, comparison, index); } return String.Format("{0} {1} @{2}", Field, comparison, index); diff --git a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs index 4009063..ffd8db5 100644 --- a/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs +++ b/test/Kendo.DynamicLinqCore.Tests/FilterTest.cs @@ -66,7 +66,7 @@ public void InputParameter_SubPropertyContains_Case_Insensitive_CheckResultCount Value = "microsoft", Operator = "contains", Logic = "and", - ignoreCase = true, + IgnoreCase = true, }); Assert.AreEqual(2, result.Total); @@ -80,7 +80,7 @@ public void InputParameter_SubPropertyContains_Case_Insensitive_CheckResultCount Field ="Company.Name", Operator = "contains", Value = "microsoft", - ignoreCase = true, + IgnoreCase = true, } }, Logic = "and"