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.
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;
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>());
}
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.
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".
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 :-/ )