Maybe the same origin: LoadDataArgs.Filter is an empty string with current version even if LoadDataArgs.Filters contains an integer filter. (Was not in version 8.4.2)
You can check your own example Blazor DataGrid Component - OData Service | Free UI Components by Radzen when enabling the filter on the EmployeeID column
Thanks for that. It’s fixed it in my test case case - I’m not getting a blank string.
However, the way I’m calling it my application is now getting me a new exception.
System.InvalidOperationException: No generic method 'Contains' on type 'System.Linq.Enumerable' 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 Radzen.QueryableExtension.GetExpression[T](ParameterExpression parameter, FilterDescriptor filter, FilterCaseSensitivity filterCaseSensitivity, Type type)
at Radzen.QueryableExtension.AddWhereExpression[T](ParameterExpression parameter, CompositeFilterDescriptor filter, List`1& filterExpressions, FilterCaseSensitivity filterCaseSensitivity)
at Radzen.QueryableExtension.ToFilterString[T](IEnumerable`1 filters, LogicalFilterOperator logicalFilterOperator, FilterCaseSensitivity filterCaseSensitivity)
I’ll try and make a reproducible case now, as it maybe an issue with serializing out RadzenDataFilter.Filters
Okay I think it’s just how I’m serilizing/deserilizing the filters. I redid it with the built-in System.Text.Json rather than legacy Newtonsoft and get a different exception.
@page "/dataFilterBug"
@using System.Text.Json
@using System.Text.Json.Serialization
<RadzenButton Text="IEnumerable Only Filter" Click="EnumerableFilter" />
<RadzenButton Text="Text Only Filter" Click="TextFilter" />
<RadzenButton Text="Mixed Filter" Click="MixedFilter" />
<RadzenButton Text="Serilization Round Trip" Click="Serilize" />
<RadzenDataFilter @ref="dataFilter" TItem="Demo" ViewChanged="@(()=>StateHasChanged())" >
<Properties>
<RadzenDataFilterProperty Type="@typeof(string)" Property="@nameof(Demo.Title)" />
<RadzenDataFilterProperty
Type="@typeof(IEnumerable<int>)"
Property="@nameof(Demo.DemoValue)"
FilterOperator="FilterOperator.Contains"
FilterOperators="@(new [] { FilterOperator.Contains, FilterOperator.DoesNotContain})">
<FilterTemplate Context="field">
<RadzenDropDown @bind-Value="@(field.FilterValue)"
Style="width:100%;"
Data="@(new List<int> { 1, 2, 3, 4, 5 })"
AllowClear="true"
Multiple="true" />
</FilterTemplate>
</RadzenDataFilterProperty>
</Properties>
</RadzenDataFilter>
@if (dataFilter != null)
{
<p>Filter String: @dataFilter.ToFilterString()</p>
<p>OData String: @dataFilter.ToODataFilterString()</p>
}
@code {
public class JsonTypeConverter : JsonConverter<Type>
{
public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string? typeName = reader.GetString();
return typeName == null ? null : Type.GetType(typeName);
}
public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)
{
// Use AssemblyQualifiedName to ensure the type can be reloaded later
writer.WriteStringValue(value.AssemblyQualifiedName);
}
}
RadzenDataFilter<Demo> dataFilter;
async Task Serilize()
{
var options = new JsonSerializerOptions
{
Converters = { new JsonTypeConverter() },
WriteIndented = true
};
await dataFilter.ClearFilters();
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = nameof(Demo.DemoValue),
FilterValue = new int[] { 2 },
FilterOperator = FilterOperator.Contains
});
// Serilize the filters out
var json = JsonSerializer.Serialize(dataFilter.Filters, options);
// and bring them back in.
var filters = JsonSerializer.Deserialize<IEnumerable<CompositeFilterDescriptor>>(json, options);
dataFilter.ClearFilters();
dataFilter.Filters = filters;
StateHasChanged();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
await EnumerableFilter();
}
}
async Task EnumerableFilter()
{
await dataFilter.ClearFilters();
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = nameof(Demo.DemoValue),
FilterValue = new int[] { 2 },
FilterOperator = FilterOperator.Contains
});
StateHasChanged();
}
async Task TextFilter()
{
await dataFilter.ClearFilters();
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = nameof(Demo.Title),
FilterValue = "t",
FilterOperator = FilterOperator.Contains
});
StateHasChanged();
}
async Task MixedFilter()
{
await dataFilter.ClearFilters();
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = nameof(Demo.DemoValue),
FilterValue = new int[] { 2 },
FilterOperator = FilterOperator.Contains
});
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = nameof(Demo.Title),
FilterValue = "t",
FilterOperator = FilterOperator.Contains
});
StateHasChanged();
}
public class Demo
{
public string Title { get; set; }
public int DemoValue { get; set; }
}
}
System.ArgumentException
HResult=0x80070057
Message=Argument types do not match
Source=System.Linq.Expressions
StackTrace:
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.AddWhereExpression[T](ParameterExpression parameter, CompositeFilterDescriptor filter, List`1& filterExpressions, FilterCaseSensitivity filterCaseSensitivity)
at Radzen.QueryableExtension.ToFilterString[T](RadzenDataFilter`1 dataFilter)
at Demo.DataFilterBug.BuildRenderTree(RenderTreeBuilder __builder) in
Not sure how this is related to our extension methods - you cannot serialize/deserialize arrays using default/simple converters.This is what you will get for FilterValue which is definetely not something supported by our filtering: