Issue with Dynamic Filtering After Upgrading to Radzen 6.0.x

HI, After upgrading to Radzen 6.0.6, I encountered an issue when executing queries with dynamic filtering. Previously, the following code worked correctly: items = items.Where(query.Filter, query.FilterParameters);

However, after updating, I get the following error:
System.InvalidOperationException: Invalid Where selector

Here my code: protected override async Task OnInitializedAsync()
{
...
var filters = new List();
var filterParameters = new List();
int parmIdx = 0;

if (var1 != 0)
{
    filters.Add($"Var1 == @{parmIdx}");
    filterParameters.Add(var1);
    parmIdx++;
}

if (var2 != 0L)
{
    filters.Add($"Var1 == @{parmIdx}");
    filterParameters.Add(var2);
    parmIdx++;
}

string filterString = string.Join(" && ", filters);

var query = new Radzen.Query
{
    Filter = filterString,
    FilterParameters = filterParameters.Cast<object>().ToArray(),
    OrderBy = "Var1 asc, Var2 asc",
    Expand = "Table1, Table2"
};

.myEntity = await ServerDbService.GetMyEntity(query);

}

I tried several solutions, such as:

  • Replacing eq with == in the filter string
  • Casting FilterParameters to object[]
  • Debugging the generated query

But the error persists.

Could you please confirm if there was a breaking change in Radzen 6.0.6 regarding dynamic filtering? If so, what would be the recommended way to adjust our queries to work with the new version?

Thanks in advance for your help!
Fra

Hi,

I also got massive issues after upgrading to 6.0; I had to revert to 5. The problem is also that the error message above does not really help. There is no real way to debug what the problem with the query is. Just try&error which is not an option for more complex queries (most of them were generated initially with Radzen Studio btw).

Is there any way to find out more why the queries are not working? I also got the impression that the use if C# inside query with expressions like .Contains() or .ToString() cause massive problems....

Would be great to understand what has actually changed.

The change is triggered by the System.Dynamic.Linq.Core library vulnerability. We do not want to rely on vulnerable dependency. The string expression used for Where() and Select() methods were not valid C# in some cases but pseudo syntax applicable for System.Dynamic.Linq.Core library only - our Where() and Select() methods by strings will accept only valid C# strings since we are using Microsoft Roslyn to parse it runtime.

Ok, understood. However, it would be a huge help if the exception could contain more detailed information what in the parsed string exactly is the problem. This generinc error makes it very hard if not impossible to find the actual issue with a given query.

We will provide this in our upcoming update now!

1 Like

Thanks for adding this. Now I get a more detailed error:

System.InvalidOperationException: Invalid Where selector: 'i => i.IsActive == true && (Contact.Company.Contains("mira") || Contact.Firstname.Contains("mira") || Contact.Lastname.Contains("mira") || Contact.Email.Contains("mira") || Contact.Town.Contains("mira") || Contact.Comment.Contains("mira") || Comment.Contains("mira") || AccountNotice.Contains("mira") || SpecialNote.Contains("mira") || AdditionalAccountContacts.Where(c => (c.IsActive == true) && (
  c.Contact.Email.Contains("mira") ||
  c.Contact.Company.Contains("mira") ||
  c.Contact.Firstname.Contains("mira") ||
  c.Contact.Lastname.Contains("mira") ||
  c.Contact.Town.Contains("mira") ||
  c.Contact.Comment.Contains("mira")
 )).Any())'. Exception: Unsupported identifier: Contact

This is my query:

AccountList = await MyContext.GetAccounts(new Query() { Filter = $@"i => i.IsActive == @0 && (Contact.Company.Contains(""{SearchTerm}"") || Contact.Firstname.Contains(""{SearchTerm}"") || Contact.Lastname.Contains(""{SearchTerm}"") || Contact.Email.Contains(""{SearchTerm}"") || Contact.Town.Contains(""{SearchTerm}"") || Contact.Comment.Contains(""{SearchTerm}"") || Comment.Contains(""{SearchTerm}"") || AccountNotice.Contains(""{SearchTerm}"") || SpecialNote.Contains(""{SearchTerm}"") || AdditionalAccountContacts.Where(c => (c.IsActive == true) && (
 c.Contact.Email.Contains(""{SearchTerm}"") ||
 c.Contact.Company.Contains(""{SearchTerm}"") ||
 c.Contact.Firstname.Contains(""{SearchTerm}"") ||
 c.Contact.Lastname.Contains(""{SearchTerm}"") ||
 c.Contact.Town.Contains(""{SearchTerm}"") ||
 c.Contact.Comment.Contains(""{SearchTerm}"")
)).Any())", FilterParameters = [true], OrderBy = $"DateCreated desc", Expand = "Licenses.Product,AdditionalAccountContacts,LinkedAccount,LinkedAccount.Contact" });

To me it looks like the new expression evaluation cannot handle the where() statement any more with the sub query.

We never knew that this is possible in the first place. You ca replace this Where() with Any().

Hi @JustJoe,

The expression is indeed invalid. It is missing i. in front of Contact.. Please try changing:

Contact.Company.Contains

to

i.Contact.Company.Contains

Hi @korchev ,

you got the right point. After prefixing the names with "i." it works as expected. I really need to go through all the expressions in my app since these have been initially been created using Radzen Studio. But with the new, more detailed exception and the syntax changes for the filter expressions in mind, it should be possible to get everything fixed.

Thanks a lot!

Radzen Studio and Radzen Blazor Studio never generates nested Where() expressions as far we know.

Right. This was related to the missing prefix.

However, I found another issue:

This expression does not work:

Filter = $@"i => i.IsActive == @0 && (i.Comment == null || (!i.Comment.Contains(@1)))"

I needed to change it to:

Filter = $@"i => i.IsActive == @0 && (i.Comment == null || (i.Comment.Contains(@1) == false))"

Due to "Exception: Unsupported syntax: PrefixUnaryExpressionSyntax". Will this be supported again or do I have to change the syntax?

This will be fixed immediately!

1 Like

Hi,
public class PalletProductRemainInfo
{

    public virtual int? YYY { get; set; }
    public virtual string? DESCRIPTION1 { get; set; }
    public virtual string? STOCK_CODE { get; set; }
    public virtual decimal? Remain { get; set; }
    public virtual decimal? RemainT_QUANTITY { get; set; }
    public virtual byte[]? ProductImageSmall { get; set; }
    public virtual string?  UNIT1 { get; set; }
    public virtual string?  UNIT2 { get; set; }
    public virtual string?  LIFE { get; set; }
    public virtual decimal? UNITRATE1 { get; set; }
    public virtual decimal? UNITRATE2 { get; set; }

    public virtual decimal? TotalPalletCount
    {
        get
        {
            if (RemainT_QUANTITY.HasValue && UNITRATE1.HasValue && UNITRATE2.HasValue &&
                UNITRATE1.Value != 0 && UNITRATE2.Value != 0)
            {
                return RemainT_QUANTITY.Value / (UNITRATE2.Value * UNITRATE1.Value);
            }
            return 0; // Return 0 if any value is null or zero
        }
    }

}
 using (var session = _nHibernateHelper.OpenSession())
 {
     var query = session.Query<PalletDetail>()
         .Where(p => p.PYYY != null) // Filter out null PYYY references
         .Fetch(p => p.PYYY); // Eager load PYYY to prevent N+1 queries

     var filteredSums = query
         .GroupBy(p => new
         {
             p.PYYY.DESCRIPTION1,
             p.PYYY.YYY,
             p.PYYY.STOCK_CODE,
             p.PYYY.ProductImageSmall,
             p.PYYY.UNIT1,
             p.PYYY.UNIT2,
             p.PYYY.UNITRATE1,
             p.PYYY.UNITRATE2,
             Life = p.PYYY.LIFE != null ? p.PYYY.LIFE.Trim() : string.Empty,
         })
         .Select(g => new PalletProductRemainInfo
         {
             ProductImageSmall = g.Key.ProductImageSmall,
             DESCRIPTION1 = g.Key.DESCRIPTION1,
             LIFE = g.Key.Life,
             YYY = g.Key.YYY,
             UNIT1 = g.Key.UNIT1,
             UNIT2 = g.Key.UNIT2,
             UNITRATE1 = g.Key.UNITRATE1,
             UNITRATE2 = g.Key.UNITRATE2,
             STOCK_CODE = g.Key.STOCK_CODE,
             Remain = g.Sum(p => p.RemainQUANTITY ?? 0),
             RemainT_QUANTITY = g.Sum(p => p.RemainT_QUANTITY ?? 0)
         });

     if (filter.FilterBy != null)
     {
         filteredSums = filteredSums.Where(filter.FilterBy);
     }

     if (filter.OrderBy != null)
     {
         filteredSums = filteredSums.OrderBy(filter.OrderBy);
     }

     var list = filteredSums.ToList();
     return (list, list.Count);
 }
	Exception caught: 'System.NotSupportedException' in BlazorEcommerce.ServerTest.dll ("MemberInit") Exception caught: 'System.NotSupportedException' in BlazorEcommerce.ServerTest.dll ("MemberInit") Hyperlink: Activate Historical Debugging giving error on var list = filteredSums.ToList();

@Muhammet_Ozdag didn't get much of your post - you can format your code at least and provide more details.

Thank you for ansver. Radzendatagrid Loaddata Query working at 5.9.9. but after version 6.0.. Exception caught: 'System.NotSupportedException' in BlazorEcommerce.ServerTest.dll ("MemberInit") Hyperlink: Activate Historical Debugging giving error on var list = filteredSums.ToList();

Note: I am using NHIBERNATE

We don’t know what that error means.You can continue to use either 5.x or Dynamic LINQ.

Thank you @enchev I will try.

I stumbled upon another issue may be is related to the new version 6 (it was working in 5.x):

I have a grid and this is one of the columns:

<RadzenDataGridColumn TItem="MyData.Models.MyData.Account" FilterProperty="Contact.Company" GroupProperty="Contact.Company" Groupable="false" Property="ContactId" SortProperty="Contact.Company" Title="Name">
    <Template Context="MyDataModelsMyDataAccount">
        <RadzenLabel style="font-weight: bold" Text="@($"{(MyDataModelsMyDataAccount.Contact?.Company)}")">
        </RadzenLabel>
        <RadzenLabel Text="@($"{(", " + MyDataModelsMyDataAccount.Contact?.Firstname)}")">
        </RadzenLabel>
        <RadzenLabel Text="@($"{(" " + MyDataModelsMyDataAccount.Contact?.Lastname)}")">
        </RadzenLabel>
        <RadzenBadge style="background-color: #cb6992; margin-left: 5px" Text="Inactive!" Visible="@(MyDataModelsMyDataAccount.IsActive == false)">
        </RadzenBadge>
    </Template>
</RadzenDataGridColumn>

When I filter using the "contains" option for a given string, I get this exception:

System.ArgumentException: Argument types do not match
   at System.Linq.Expressions.Expression.Constant(Object value, Type type)
   at Radzen.QueryableExtension.GetExpression[T](ParameterExpression parameter, FilterDescriptor filter, FilterCaseSensitivity filterCaseSensitivity, Type type)
   at Radzen.QueryableExtension.Where[T](IQueryable`1 source, IEnumerable`1 filters, LogicalFilterOperator logicalFilterOperator, FilterCaseSensitivity filterCaseSensitivity)
   at Radzen.QueryableExtension.Where[T](IQueryable`1 source, IEnumerable`1 columns)
   at Radzen.Blazor.RadzenDataGrid`1.get_View()
   at Radzen.PagedDataBoundComponent`1.get_PagedView()
   at Radzen.Blazor.RadzenDataGrid`1.DrawGroupOrDataRows(RenderTreeBuilder builder, IList`1 visibleColumns)
   at Radzen.Blazor.RadzenDataGrid`1.<>c__DisplayClass22_0.<DrawRows>b__0(RenderTreeBuilder builder)

I think the problem here is that FilterProperty is "Contact.Company", so a sub-property.

if (filter.OrderBy != null)
{
filteredSums = filteredSums.OrderBy("DESCRIPTION1 Asc");
} If orderBy is not null giving error else working properly.