Component: RadFilter ( RadFilterExpressionConverter , RadFilterExpressionSerializer )
Affected: 2026.2.708 and later, where the JSON serializer replaced the Newtonsoft one
Description:
RadFilterExpressionConverter.IsValidFieldName ( RadFilterExpressionConverter.cs:180 ) allows only letters, digits, _ and . . Any other FieldName is silently replaced with null during LoadSettings() . SaveSettings() does not validate, so a bracket-qualified name saves but can't be loaded.
Steps to reproduce
1. Create a RadFilter with a RadFilterTextFieldEditor where FieldName = "[dataBooking].[TotalPaid]" .
2. Add a RadFilterLessThanFilterExpression<string> on that field with the value "1000" .
3. Call SaveSettings() . The JSON contains "FieldName":"[dataBooking].[TotalPaid]" .
4. On a new RadFilter with the same editor, call LoadSettings(saved) .
Sample console application code snippet to reproduce the issue:
using System;
using System.Collections;
using Telerik.Web.UI;
namespace RadFilterBracketFieldNameRepro
{
class Program
{
private const string BracketedFieldName = "[dataBooking].[TotalPaid]";
static void Main()
{
Console.WriteLine("Telerik.Web.UI version: " + typeof(RadFilter).Assembly.GetName().Version);
Console.WriteLine("FieldName under test: " + BracketedFieldName);
Console.WriteLine();
// 1) Build a filter with one expression against a bracket-qualified field name.
// This format is not unusual -- it's what you get for any field name that needs
// to be schema/table-qualified. Telerik's own RadFilterSqlExpressionEvaluator
// produces the same "[table].[column]" shape when generating SQL.
RadFilter source = new RadFilter();
source.FieldEditors.Add(new RadFilterTextFieldEditor { FieldName = BracketedFieldName });
RadFilterLessThanFilterExpression<string> expression = new RadFilterLessThanFilterExpression<string>(BracketedFieldName);
((IRadFilterValueExpression)expression).SetValues(new ArrayList { "1000" });
source.RootGroup.AddExpression(expression);
// 2) Persist it the normal way.
string savedState = source.SaveSettings();
Console.WriteLine("SaveSettings() output (base64):");
Console.WriteLine(savedState);
Console.WriteLine();
Console.WriteLine("Decoded JSON:");
Console.WriteLine(System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(savedState)));
Console.WriteLine();
// 3) Simulate the next request restoring that saved state into a fresh RadFilter,
// exactly like a report/page reload would.
RadFilter restored = new RadFilter();
restored.FieldEditors.Add(new RadFilterTextFieldEditor { FieldName = BracketedFieldName });
try
{
restored.LoadSettings(savedState);
RadFilterLessThanFilterExpression<string> restoredExpression = (RadFilterLessThanFilterExpression<string>)restored.RootGroup.Expressions[0];
Console.WriteLine("FieldName after LoadSettings(): '" + restoredExpression.FieldName + "'");
Console.WriteLine(restoredExpression.FieldName == BracketedFieldName
? "OK -- FieldName round-tripped correctly."
: "BUG REPRODUCED -- FieldName was lost during LoadSettings().");
}
catch (Exception ex)
{
Console.WriteLine("BUG REPRODUCED -- LoadSettings() threw:");
Console.WriteLine(ex);
}
Console.WriteLine();
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
}
Expected: The expression is restored with its original FieldName.
Actual:
System.ArgumentException: Parameter cannot be null or empty. Parameter name: fieldName RadFilterDataFieldEditorCollection.FindEditorForFieldName RadFilterSingleExpressionItem.SetupFunctionInterface RadFilter.CreateFilterItems / CreateChildControls RadFilter.RecreateControl RadFilter.LoadSettings