Can I get the dynamic linq string query from Data Filter

Looking at your codebase I see agreat extension method to apply the DataFilter to an IQueryable. Internally it converts the DataFilter settings to a dynamic linq string and then uses dynamic linq to apply it to the Iqueyable. I'd like to have a method that returns that filter string back to me so I can store it and use the DataFilter as a means to define the queries that I can execute later on.

My next question is whether you can initialize a DataFilter from a dynamic linq query string. This is probably more difficult to implement because it probably requires you to write a complex parser.

public static IQueryable Where(this IQueryable source, RadzenDataFilter dataFilter)
{
Func<CompositeFilterDescriptor, bool> canFilter = (c) => dataFilter.properties.Where(col => col.Property == c.Property).FirstOrDefault()?.FilterPropertyType != null &&
(!(c.FilterValue == null || c.FilterValue as string == string.Empty)
|| c.FilterOperator == FilterOperator.IsNotNull || c.FilterOperator == FilterOperator.IsNull
|| c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty)
&& c.Property != null;

if (dataFilter.Filters.Concat(dataFilter.Filters.SelectManyRecursive(i => i.Filters ?? Enumerable.Empty<CompositeFilterDescriptor>())).Where(canFilter).Any())
{
    var index = 0;
    var filterExpressions = new List<string>();
    var filterValues = new List<object[]>();

    foreach (var filter in dataFilter.Filters)
    {
        AddWhereExpression(canFilter, filter, ref filterExpressions, ref filterValues, ref index, dataFilter);
    }
     //I refactored this line out from the below line in your source code.  I need this value back... 
     //Is there a way to do this without modifying your source?
    string filterExpression = string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions);

    return filterExpressions.Any() ?
        source.Where(filterExpression, filterValues.SelectMany(i => i.ToArray()).ToArray())
        : source;
}

return source;

}

Both are not possible at the moment however we accept pull requests!

Ok - thank you. I don't want to waste anybody's time, but if I were to add one extension method to your QueryableExtension.cs file like the following, what are the chances you would accept the pull request:

    /// <summary>
    /// Returns the dynamic linq filter from the filters in the DataFilter
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataFilter">The DataFilter from which to derive the filter string.</param>
    /// <returns>The Dynamic LINQ filter string that represents the DataFilter</returns>
    public static (string, IEnumerable<object>) GetFilter<T>(this RadzenDataFilter<T> dataFilter)
    {
        Func<CompositeFilterDescriptor, bool> canFilter = (c) => dataFilter.properties.Where(col => col.Property == c.Property).FirstOrDefault()?.FilterPropertyType != null &&
           (!(c.FilterValue == null || c.FilterValue as string == string.Empty)
            || c.FilterOperator == FilterOperator.IsNotNull || c.FilterOperator == FilterOperator.IsNull
            || c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty)
           && c.Property != null;

        if (dataFilter.Filters.Concat(dataFilter.Filters.SelectManyRecursive(i => i.Filters ?? Enumerable.Empty<CompositeFilterDescriptor>())).Where(canFilter).Any())
        {
            var index = 0;
            var filterExpressions = new List<string>();
            var filterValues = new List<object[]>();

            foreach (var filter in dataFilter.Filters)
            {
                AddWhereExpression(canFilter, filter, ref filterExpressions, ref filterValues, ref index, dataFilter);
            }

            string filterExpression = string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions);
            var paramList = filterValues.SelectMany(i => i.ToArray()).ToArray();

            (string filterExpression, IEnumerable<object> paramList) result = (filterExpression, paramList);

            return result;
        }

        return ("", Enumerable.Empty<object>());
    }
1 Like

If it doesn’t break anything and adds value, the pull request will be merged similarly to all other pull requests we already accepted.

I'd find an extension method like this very useful if you're still interested in submitting a pull request for it, it would definitely provide a lot more flexibility with how the component can be applied.

1 Like

When looking at how DataGrid and DataFilter create their filters, I got some strange differences: DataGrid seems to create the filter arguments based on the type of list it is showing: if it's Odata-like, it creates OData filters, otherwise Linq-like filters.
DataFilter does nothing of the sort, you are supposed to create the filter string yourself. There is one extension method for doing so: ToODataFilterString - which does exactly that.
The net result of this can however be that if you want to combine both, you end up with a filter that uses Linq syntax coming out of the LoadDataArgs (from the grid), and filter args that are OData-like, from the filter.

Obviously a backend system (be it OData or Linq) won't be able to make any sense of that.

So, indeed it would be helpful to have some facility to either get Linq-filter syntax out of a DataFilter filters (new extension method?), or be able to have some more fine-grained control over what a DataGrid creates as filter syntax.
This latter may be possible already (just ensure your data list is "OData"-assignable), but then the provided controller example code on how to use filters data seems not correct - at least I only got it to work on filters that are "linq"-compliant. The moment I send OData filters it fails - in particular on text filters that use "contains".

Suggestions are welcome!

See Feature Request: RadzenDataFilter: Add support for Linq-like filtering Β· Issue #1553 Β· radzenhq/radzen-blazor Β· GitHub

Hey @rudolfdeschipper,

We accept pull requests!

Hi,
Great, thanks. I tried to do create one but got an Access Denied on the repo - how to do? Also creating a remote branch failed.
(yes, I admit, I'm not very familiar with Pull Requests :-/ )

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests

Done - I think, see PR #1556.