Skip to content

Commit 2981caf

Browse files
committed
introduce Is method on attributes for performing case insensitive comparisons
1 parent 61e2915 commit 2981caf

File tree

6 files changed

+61
-41
lines changed

6 files changed

+61
-41
lines changed

src/JsonApiDotNetCore/Internal/ContextGraph.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public class ContextGraph : IContextGraph
99
private List<ContextEntity> _entities;
1010

1111
public ContextGraph() { }
12-
13-
public ContextGraph(List<ContextEntity> entities, bool usesDbContext)
12+
13+
public ContextGraph(List<ContextEntity> entities, bool usesDbContext)
1414
{
1515
_entities = entities;
1616
UsesDbContext = usesDbContext;
@@ -42,9 +42,9 @@ public string GetRelationshipName<TParent>(string relationshipName)
4242
{
4343
var entityType = typeof(TParent);
4444
return _entities
45-
.SingleOrDefault(e => e.EntityType == entityType)
45+
.SingleOrDefault(e => e.EntityType == entityType)
4646
?.Relationships
47-
.SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase))
47+
.SingleOrDefault(r => r.Is(relationshipName))
4848
?.InternalRelationshipName;
4949
}
5050
}

src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ public AttrFilterQuery(
1717

1818
var attribute = GetAttribute(filterQuery.Attribute);
1919

20-
if(attribute == null)
20+
if (attribute == null)
2121
throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
2222

23-
if(attribute.IsFilterable == false)
23+
if (attribute.IsFilterable == false)
2424
throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
2525

2626
FilteredAttribute = attribute;
@@ -32,9 +32,7 @@ public AttrFilterQuery(
3232
public string PropertyValue { get; }
3333
public FilterOperations FilterOperation { get; }
3434

35-
private AttrAttribute GetAttribute(string attribute) =>
36-
_jsonApiContext.RequestEntity.Attributes.FirstOrDefault(
37-
attr => string.Equals(attr.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase)
38-
);
35+
private AttrAttribute GetAttribute(string attribute) =>
36+
_jsonApiContext.RequestEntity.Attributes.FirstOrDefault(attr => attr.Is(attribute));
3937
}
4038
}

src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ public RelatedAttrFilterQuery(
2222
throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}.");
2323

2424
var attribute = GetAttribute(relationship, relationshipArray[1]);
25-
26-
if(attribute == null)
25+
26+
if (attribute == null)
2727
throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
2828

29-
if(attribute.IsFilterable == false)
29+
if (attribute.IsFilterable == false)
3030
throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
3131

3232
FilteredRelationship = relationship;
@@ -41,16 +41,13 @@ public RelatedAttrFilterQuery(
4141
public RelationshipAttribute FilteredRelationship { get; }
4242

4343
private RelationshipAttribute GetRelationship(string propertyName)
44-
{
45-
return _jsonApiContext.RequestEntity.Relationships
46-
.FirstOrDefault(r => string.Equals(r.PublicRelationshipName, propertyName, StringComparison.OrdinalIgnoreCase));
47-
}
44+
=> _jsonApiContext.RequestEntity.Relationships.FirstOrDefault(r => r.Is(propertyName));
4845

4946
private AttrAttribute GetAttribute(RelationshipAttribute relationship, string attribute)
5047
{
5148
var relatedContextExntity = _jsonApiContext.ContextGraph.GetContextEntity(relationship.Type);
5249
return relatedContextExntity.Attributes
53-
.FirstOrDefault(a => string.Equals(a.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase));
50+
.FirstOrDefault(a => a.Is(attribute));
5451
}
5552
}
5653
}

src/JsonApiDotNetCore/Models/AttrAttribute.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,11 @@ public void SetValue(object entity, object newValue)
4747
propertyInfo.SetValue(entity, convertedValue);
4848
}
4949
}
50+
51+
/// <summary>
52+
/// Whether or not the provided exposed name is equivalent to the one defined in on the model
53+
/// </summary>
54+
public virtual bool Is(string publicRelationshipName)
55+
=> string.Equals(publicRelationshipName, PublicAttributeName, StringComparison.OrdinalIgnoreCase);
5056
}
5157
}

src/JsonApiDotNetCore/Models/RelationshipAttribute.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22

33
namespace JsonApiDotNetCore.Models
44
{
@@ -33,5 +33,11 @@ public override bool Equals(object obj)
3333
}
3434
return IsHasMany == attr.IsHasMany && PublicRelationshipName.Equals(attr.PublicRelationshipName);
3535
}
36+
37+
/// <summary>
38+
/// Whether or not the provided exposed name is equivalent to the one defined in on the model
39+
/// </summary>
40+
public virtual bool Is(string publicRelationshipName)
41+
=> string.Equals(publicRelationshipName, PublicRelationshipName, StringComparison.OrdinalIgnoreCase);
3642
}
3743
}

src/JsonApiDotNetCore/Services/QueryParser.cs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
using JsonApiDotNetCore.Models;
99
using Microsoft.AspNetCore.Http;
1010

11-
namespace JsonApiDotNetCore.Services {
12-
public interface IQueryParser {
11+
namespace JsonApiDotNetCore.Services
12+
{
13+
public interface IQueryParser
14+
{
1315
QuerySet Parse(IQueryCollection query);
1416
}
1517

16-
public class QueryParser : IQueryParser {
18+
public class QueryParser : IQueryParser
19+
{
1720
private readonly IControllerContext _controllerContext;
1821
private readonly JsonApiOptions _options;
1922

@@ -30,41 +33,49 @@ public class QueryParser : IQueryParser {
3033

3134
public QueryParser(
3235
IControllerContext controllerContext,
33-
JsonApiOptions options) {
36+
JsonApiOptions options)
37+
{
3438
_controllerContext = controllerContext;
3539
_options = options;
3640
}
3741

38-
public virtual QuerySet Parse(IQueryCollection query) {
42+
public virtual QuerySet Parse(IQueryCollection query)
43+
{
3944
var querySet = new QuerySet();
40-
var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>() ? .QueryParams ?? QueryParams.None;
45+
var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
4146

42-
foreach (var pair in query) {
43-
if (pair.Key.StartsWith(FILTER)) {
47+
foreach (var pair in query)
48+
{
49+
if (pair.Key.StartsWith(FILTER))
50+
{
4451
if (disabledQueries.HasFlag(QueryParams.Filter) == false)
4552
querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
4653
continue;
4754
}
4855

49-
if (pair.Key.StartsWith(SORT)) {
56+
if (pair.Key.StartsWith(SORT))
57+
{
5058
if (disabledQueries.HasFlag(QueryParams.Sort) == false)
5159
querySet.SortParameters = ParseSortParameters(pair.Value);
5260
continue;
5361
}
5462

55-
if (pair.Key.StartsWith(INCLUDE)) {
63+
if (pair.Key.StartsWith(INCLUDE))
64+
{
5665
if (disabledQueries.HasFlag(QueryParams.Include) == false)
5766
querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
5867
continue;
5968
}
6069

61-
if (pair.Key.StartsWith(PAGE)) {
70+
if (pair.Key.StartsWith(PAGE))
71+
{
6272
if (disabledQueries.HasFlag(QueryParams.Page) == false)
6373
querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
6474
continue;
6575
}
6676

67-
if (pair.Key.StartsWith(FIELDS)) {
77+
if (pair.Key.StartsWith(FIELDS))
78+
{
6879
if (disabledQueries.HasFlag(QueryParams.Fields) == false)
6980
querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
7081
continue;
@@ -77,23 +88,26 @@ public virtual QuerySet Parse(IQueryCollection query) {
7788
return querySet;
7889
}
7990

80-
protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
91+
protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
92+
{
8193
// expected input = filter[id]=1
8294
// expected input = filter[id]=eq:1
8395
var queries = new List<FilterQuery>();
8496

85-
var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
97+
var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
8698

8799
var values = value.Split(COMMA);
88-
foreach (var val in values) {
100+
foreach (var val in values)
101+
{
89102
(var operation, var filterValue) = ParseFilterOperation(val);
90103
queries.Add(new FilterQuery(propertyName, filterValue, operation));
91104
}
92105

93106
return queries;
94107
}
95108

96-
protected virtual(string operation, string value) ParseFilterOperation(string value) {
109+
protected virtual (string operation, string value) ParseFilterOperation(string value)
110+
{
97111
if (value.Length < 3)
98112
return (string.Empty, value);
99113

@@ -159,7 +173,7 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
159173

160174
var attribute = GetAttribute(propertyName);
161175

162-
if(attribute.IsSortable == false)
176+
if (attribute.IsSortable == false)
163177
throw new JsonApiException(400, $"Sort is not allowed for attribute '{attribute.PublicAttributeName}'.");
164178

165179
sortParameters.Add(new SortQuery(direction, attribute));
@@ -168,7 +182,8 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
168182
return sortParameters;
169183
}
170184

171-
protected virtual List<string> ParseIncludedRelationships(string value) {
185+
protected virtual List<string> ParseIncludedRelationships(string value)
186+
{
172187
const string NESTED_DELIMITER = ".";
173188
if (value.Contains(NESTED_DELIMITER))
174189
throw new JsonApiException(400, "Deeply nested relationships are not supported");
@@ -195,7 +210,7 @@ protected virtual List<string> ParseFieldsQuery(string key, string value)
195210
{
196211
var attr = _controllerContext.RequestEntity
197212
.Attributes
198-
.SingleOrDefault(a => string.Equals(a.PublicAttributeName, field, StringComparison.OrdinalIgnoreCase));
213+
.SingleOrDefault(a => a.Is(field));
199214

200215
if (attr == null) throw new JsonApiException(400, $"'{_controllerContext.RequestEntity.EntityName}' does not contain '{field}'.");
201216

@@ -213,9 +228,7 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
213228
return _controllerContext
214229
.RequestEntity
215230
.Attributes
216-
.Single(attr =>
217-
string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
218-
);
231+
.Single(attr => attr.Is(propertyName));
219232
}
220233
catch (InvalidOperationException e)
221234
{

0 commit comments

Comments
 (0)