Skip to content

Commit 0654b42

Browse files
author
Bart Koelman
authored
Fixed: splitting on comma in legacy filter notation (#825)
The original code looked at the first operator and would, unless that operator was 'in' or 'nin', split the query string parameter value on comma. This never worked correctly in composition, because the syntax becomes ambiguous. For example: `?filter[name]=like:a,in:b,c,d` could mean: - like(a), in(b,c,d) - like(a), in(b,c), equals(d) So while this fix addresses the simple case, it still fails on combinations, including mixing with the new notation.
1 parent b32e304 commit 0654b42

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

src/JsonApiDotNetCore/QueryStrings/Internal/FilterQueryStringParameterReader.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,30 @@ public virtual void Read(string parameterName, StringValues parameterValues)
6464
{
6565
_lastParameterName = parameterName;
6666

67-
foreach (string parameterValue in parameterValues)
67+
foreach (string parameterValue in ExtractParameterValues(parameterName, parameterValues))
6868
{
6969
ReadSingleValue(parameterName, parameterValue);
7070
}
7171
}
7272

73+
private IEnumerable<string> ExtractParameterValues(string parameterName, StringValues parameterValues)
74+
{
75+
foreach (string parameterValue in parameterValues)
76+
{
77+
if (_options.EnableLegacyFilterNotation)
78+
{
79+
foreach (string condition in _legacyConverter.ExtractConditions(parameterName, parameterValue))
80+
{
81+
yield return condition;
82+
}
83+
}
84+
else
85+
{
86+
yield return parameterValue;
87+
}
88+
}
89+
}
90+
7391
private void ReadSingleValue(string parameterName, string parameterValue)
7492
{
7593
try

src/JsonApiDotNetCore/QueryStrings/Internal/LegacyFilterNotationConverter.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,23 @@ public sealed class LegacyFilterNotationConverter
2525
["like:"] = Keywords.Contains
2626
};
2727

28+
public IEnumerable<string> ExtractConditions(string parameterName, string parameterValue)
29+
{
30+
if (parameterValue.StartsWith(ExpressionPrefix, StringComparison.Ordinal) ||
31+
parameterValue.StartsWith(InPrefix, StringComparison.Ordinal) ||
32+
parameterValue.StartsWith(NotInPrefix, StringComparison.Ordinal))
33+
{
34+
yield return parameterValue;
35+
}
36+
else
37+
{
38+
foreach (string condition in parameterValue.Split(','))
39+
{
40+
yield return condition;
41+
}
42+
}
43+
}
44+
2845
public (string parameterName, string parameterValue) Convert(string parameterName, string parameterValue)
2946
{
3047
if (parameterName == null) throw new ArgumentNullException(nameof(parameterName));

test/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin
5656

5757
[Theory]
5858
[InlineData("filter[caption]", "Brian O'Quote", "equals(caption,'Brian O''Quote')")]
59-
[InlineData("filter[caption]", "using,comma", "equals(caption,'using,comma')")]
6059
[InlineData("filter[caption]", "am&per-sand", "equals(caption,'am&per-sand')")]
6160
[InlineData("filter[caption]", "2017-08-15T22:43:47.0156350-05:00", "equals(caption,'2017-08-15T22:43:47.0156350-05:00')")]
6261
[InlineData("filter[caption]", "eq:1", "equals(caption,'1')")]
@@ -77,6 +76,9 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin
7776
[InlineData("filter", "expr:equals(author,null)", "equals(author,null)")]
7877
[InlineData("filter", "expr:has(author.articles)", "has(author.articles)")]
7978
[InlineData("filter", "expr:equals(count(author.articles),'1')", "equals(count(author.articles),'1')")]
79+
[InlineData("filter[caption]", "using,comma", "or(equals(caption,'using'),equals(caption,'comma'))")]
80+
[InlineData("filter[caption]", "like:First,Second", "or(contains(caption,'First'),equals(caption,'Second'))")]
81+
[InlineData("filter[caption]", "like:First,like:Second", "or(contains(caption,'First'),contains(caption,'Second'))")]
8082
public void Reader_Read_Succeeds(string parameterName, string parameterValue, string expressionExpected)
8183
{
8284
// Act

0 commit comments

Comments
 (0)