Just released our new major version of Radzen.Blazor 6.0.0 without reference to System.Linq.Dynamic.Core NuGet package

Now on Radzen version 6.0.15.

I am having issues with bind-Settings

I simplified my solution to try an isolate the issue but am unable to. I'm not exactly sure how to review the code in the Radzen DataGrid responsible for applying the settings.

  1. Changed Datagrid to a single column.
  2. Applied a filter to the single column.
  3. Saved the settings (Included below).
  4. Reloaded the page applying the saved settings via bind-Settings="@Settings"

The error I am receiving is:

fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
Unhandled exception in circuit 'AhMhnpTCpZuUA8tKXRS_lJQW_5nCBZqAy7ygMAEiIG0'.
System.AggregateException: One or more errors occurred. (No generic method 'Contains' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. )
---> System.InvalidOperationException: No generic method 'Contains' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.
at System.Linq.Expressions.Expression.FindMethod(Type type, String methodName, Type typeArgs, Expression args, BindingFlags flags)
at System.Linq.Expressions.Expression.Call(Type type, String methodName, Type typeArguments, Expression arguments)
at Radzen.QueryableExtension.GetExpression[T](ParameterExpression parameter, FilterDescriptor filter, FilterCaseSensitivity filterCaseSensitivity, Type type)
at Radzen.QueryableExtension.Where[T](IQueryable1 source, IEnumerable1 filters, LogicalFilterOperator logicalFilterOperator, FilterCaseSensitivity filterCaseSensitivity)
at Radzen.QueryableExtension.Where[T](IQueryable1 source, IEnumerable1 columns)
at Radzen.Blazor.RadzenDataGrid1.get_View() at Radzen.Blazor.RadzenDataGrid1.LoadSettingsInternal(DataGridSettings settings)
at Radzen.Blazor.RadzenDataGrid`1.OnAfterRenderAsync(Boolean firstRender)
--- End of inner exception stack trace ---
An error occurred in OnAfterRenderAsync: A task was canceled.

The simplified settings being applied:

{
"Columns": [
{
"UniqueID": null,
"Property": "DataAreaId",
"Visible": true,
"Width": null,
"OrderIndex": null,
"SortOrder": null,
"SortIndex": null,
"FilterValue": ["nduk"],
"FilterOperator": 6,
"SecondFilterValue": null,
"SecondFilterOperator": 0,
"LogicalFilterOperator": 0,
"CustomFilterExpression": null
}
],
"Groups": ,
"CurrentPage": 0,
"PageSize": 10
}

Most probably this property is not of type string.

@enchev

This issue occurs regardless of the type, and with any field previously included in the datagrid. Reverting back to 5.9.9 fixes the issue. Do you have an example where bind-setting works post Radzen 6.x update? What is the proposed solution if it’s nothing something related to this update?

Yes, we have this demo which works normally:

There is a chance that there are saved filters with Dynamic LINQ syntax which is not valid c# in some cases - i.e. will use and, or single = for comparison, etc.

@enchev,

If I am saving the setting generated by the DataGrid component I'm not sure I see the solve on my end, as I'm just storing and retrieving out of the box functionality. I did dig a little deeper, and if I remove the following:

FilterMode="FilterMode.CheckBoxList" AllowCheckBoxListVirtualization="false"

then it works. So, it seems the issue is how the settings are being applied when FilterMode.CheckBoxList is being used.

Thanks for the details! We will try to replicate your case locally and we will release update later today if necessary.

UPDATE: Saved DataGrid filter with CheckBoxList filter type will raise except… · radzenhq/radzen-blazor@73c2d27 · GitHub

One of the causes for concern with System.Linq.Dynamic.Core was the possibility for SQL Injection. We were able to work around this by using a ParsingConfig object with UseParameterizedNamesInDynamicQuery = true. Then this would get passed into the query:

var config = new ParsingConfig()
{
    UseParameterizedNamesInDynamicQuery = true
};

var query = _context.Set<T>().AsQueryable();

if (!string.IsNullOrEmpty(where))
{
    query = query.Where(config, where);
}
if (!string.IsNullOrEmpty(orderby))
{
    query = query.OrderBy(config, orderby);
}
if (skip.HasValue)
{
    query = query.Skip(skip.Value);
}
if (take.HasValue)
{
    query = query.Take(take.Value);
}

return await query.ToListAsync();

However, it looks like the 6.0 version of the grid doesn't support this option. If I re-write the code without the ParsingConfig and thus without passing it to the query, it looks like a lot of the resultant SQL is inlined rather than using parameters.

While I haven't been able to successfully break it yet and get SQL Server to execute code passed in through the filters, I would feel better if the resultant SQL used parameters to make it more injection resistant. In the mean-time, I've added a prefilter than removes all special characters from the filters. This keeps any bad actors from getting to SQL, but also limits legitimate queries that might include these characters, like a "\" in a domain name or "@" in an email address.

Are there any plans to implement this parameterization option, or is there already an implementation that I'm not aware of?

I really love your product, and the grid especially. I'm very thankful for all your hard work!

Matt

We removed dependency to this library completely in favor of our own parsing code - as far as we know our code is not vulnerable.

Thank you, @enchev.

I understand that this dependency has been removed. And like you said, so far, I have not been able to produce an injection vulnerability. However, I am by no means a malicious party and I'm probably not trying every trick in the book. General best practices when it comes to executing SQL from .net or any other language is to use parameters wherever possible rather than compiling strings and passing them to the database. I'm curious if your implementation will support this down the road or if we'll need to keep depending on System.Linq.Dynamic.Core for this.

Note that I have been able to continue to use System.Linq.Dynamic.Core along with the latest version of Radzen, so it's not really a problem for now I suppose, other than that I'd prefer to only have to maintain updates for one package rather than 2. Also I would think it would eliminate any backwards compatibility issues down the road if I was only relying on your package.

Just a question/suggestion for consideration. Thank you.

We have this class as backwards compatibility:

We don’t plan anything else at the moment, feel free to submit a pull request with something you think it will be useful.