Skip to content

Commit c131839

Browse files
committed
feat(#130): disable query params
1 parent 59fc512 commit c131839

File tree

10 files changed

+263
-36
lines changed

10 files changed

+263
-36
lines changed

src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public CustomJsonApiController(
5454
IResourceService<T, TId> resourceService,
5555
ILoggerFactory loggerFactory)
5656
{
57-
_jsonApiContext = jsonApiContext.ApplyContext<T>();
57+
_jsonApiContext = jsonApiContext.ApplyContext<T>(this);
5858
_resourceService = resourceService;
5959
_logger = loggerFactory.CreateLogger<JsonApiDotNetCore.Controllers.JsonApiController<T, TId>>();
6060
}
@@ -63,7 +63,7 @@ public CustomJsonApiController(
6363
IJsonApiContext jsonApiContext,
6464
IResourceService<T, TId> resourceService)
6565
{
66-
_jsonApiContext = jsonApiContext.ApplyContext<T>();
66+
_jsonApiContext = jsonApiContext.ApplyContext<T>(this);
6767
_resourceService = resourceService;
6868
}
6969

src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ public class ContextGraphBuilder : IContextGraphBuilder
1212
{
1313
private List<ContextEntity> _entities;
1414
private bool _usesDbContext;
15-
public Link DocumentLinks { get; set; } = Link.All;
15+
public Link DocumentLinks { get; set; } = Link.All;
1616

1717
public ContextGraphBuilder()
1818
{
1919
_entities = new List<ContextEntity>();
20-
}
20+
}
2121

2222
public IContextGraph Build()
2323
{
@@ -47,7 +47,7 @@ private Link GetLinkFlags(Type entityType)
4747
var attribute = (LinksAttribute)entityType.GetTypeInfo().GetCustomAttribute(typeof(LinksAttribute));
4848
if (attribute != null)
4949
return attribute.Links;
50-
50+
5151
return DocumentLinks;
5252
}
5353

@@ -126,7 +126,7 @@ public void AddDbContext<T>() where T : DbContext
126126
private string GetResourceName(PropertyInfo property)
127127
{
128128
var resourceAttribute = property.GetCustomAttribute(typeof(ResourceAttribute));
129-
if(resourceAttribute == null)
129+
if (resourceAttribute == null)
130130
return property.Name.Dasherize();
131131

132132
return ((ResourceAttribute)resourceAttribute).ResourceName;

src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected BaseJsonApiController(
2626
IJsonApiContext jsonApiContext,
2727
IResourceService<T, TId> resourceService)
2828
{
29-
_jsonApiContext = jsonApiContext.ApplyContext<T>();
29+
_jsonApiContext = jsonApiContext.ApplyContext<T>(this);
3030
_getAll = resourceService;
3131
_getById = resourceService;
3232
_getRelationship = resourceService;
@@ -42,7 +42,7 @@ protected BaseJsonApiController(
4242
IResourceQueryService<T, TId> queryService = null,
4343
IResourceCmdService<T, TId> cmdService = null)
4444
{
45-
_jsonApiContext = jsonApiContext.ApplyContext<T>();
45+
_jsonApiContext = jsonApiContext.ApplyContext<T>(this);
4646
_getAll = queryService;
4747
_getById = queryService;
4848
_getRelationship = queryService;
@@ -64,7 +64,7 @@ protected BaseJsonApiController(
6464
IUpdateRelationshipService<T, TId> updateRelationships = null,
6565
IDeleteService<T, TId> delete = null)
6666
{
67-
_jsonApiContext = jsonApiContext.ApplyContext<T>();
67+
_jsonApiContext = jsonApiContext.ApplyContext<T>(this);
6868
_getAll = getAll;
6969
_getById = getById;
7070
_getRelationship = getRelationship;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace JsonApiDotNetCore.Controllers
4+
{
5+
public class DisableQueryAttribute : Attribute
6+
{
7+
public DisableQueryAttribute(QueryParams queryParams)
8+
{
9+
QueryParams = queryParams;
10+
}
11+
12+
public QueryParams QueryParams { get; set; }
13+
}
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace JsonApiDotNetCore.Controllers
4+
{
5+
public enum QueryParams
6+
{
7+
Filter = 1 << 0,
8+
Sort = 1 << 1,
9+
Include = 1 << 2,
10+
Page = 1 << 3,
11+
Fields = 1 << 4,
12+
All = ~(-1 << 5),
13+
None = 1 << 6,
14+
}
15+
}

src/JsonApiDotNetCore/Internal/ContextEntity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ public class ContextEntity
1010
public Type EntityType { get; set; }
1111
public List<AttrAttribute> Attributes { get; set; }
1212
public List<RelationshipAttribute> Relationships { get; set; }
13-
public Link Links { get; set; }
13+
public Link Links { get; set; } = Link.All;
1414
}
1515
}

src/JsonApiDotNetCore/Internal/Query/QuerySet.cs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using JsonApiDotNetCore.Services;
66
using Microsoft.AspNetCore.Http;
77
using JsonApiDotNetCore.Models;
8+
using JsonApiDotNetCore.Controllers;
89

910
namespace JsonApiDotNetCore.Internal.Query
1011
{
@@ -13,53 +14,57 @@ public class QuerySet
1314
private readonly IJsonApiContext _jsonApiContext;
1415

1516
public QuerySet(
16-
IJsonApiContext jsonApiContext,
17+
IJsonApiContext jsonApiContext,
1718
IQueryCollection query)
1819
{
1920
_jsonApiContext = jsonApiContext;
20-
PageQuery = new PageQuery();
21-
Filters = new List<FilterQuery>();
22-
Fields = new List<string>();
2321
BuildQuerySet(query);
2422
}
2523

26-
public List<FilterQuery> Filters { get; set; }
27-
public PageQuery PageQuery { get; set; }
28-
public List<SortQuery> SortParameters { get; set; }
29-
public List<string> IncludedRelationships { get; set; }
30-
public List<string> Fields { get; set; }
24+
public List<FilterQuery> Filters { get; set; } = new List<FilterQuery>();
25+
public PageQuery PageQuery { get; set; } = new PageQuery();
26+
public List<SortQuery> SortParameters { get; set; } = new List<SortQuery>();
27+
public List<string> IncludedRelationships { get; set; } = new List<string>();
28+
public List<string> Fields { get; set; } = new List<string>();
3129

3230
private void BuildQuerySet(IQueryCollection query)
3331
{
32+
var disabledQueries = _jsonApiContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
33+
3434
foreach (var pair in query)
3535
{
3636
if (pair.Key.StartsWith("filter"))
3737
{
38-
Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
38+
if (disabledQueries.HasFlag(QueryParams.Filter) == false)
39+
Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
3940
continue;
4041
}
4142

4243
if (pair.Key.StartsWith("sort"))
4344
{
44-
SortParameters = ParseSortParameters(pair.Value);
45+
if (disabledQueries.HasFlag(QueryParams.Sort) == false)
46+
SortParameters = ParseSortParameters(pair.Value);
4547
continue;
4648
}
4749

4850
if (pair.Key.StartsWith("include"))
4951
{
50-
IncludedRelationships = ParseIncludedRelationships(pair.Value);
52+
if (disabledQueries.HasFlag(QueryParams.Include) == false)
53+
IncludedRelationships = ParseIncludedRelationships(pair.Value);
5154
continue;
5255
}
5356

5457
if (pair.Key.StartsWith("page"))
5558
{
56-
PageQuery = ParsePageQuery(pair.Key, pair.Value);
59+
if (disabledQueries.HasFlag(QueryParams.Page) == false)
60+
PageQuery = ParsePageQuery(pair.Key, pair.Value);
5761
continue;
5862
}
5963

6064
if (pair.Key.StartsWith("fields"))
6165
{
62-
Fields = ParseFieldsQuery(pair.Key, pair.Value);
66+
if (disabledQueries.HasFlag(QueryParams.Fields) == false)
67+
Fields = ParseFieldsQuery(pair.Key, pair.Value);
6368
continue;
6469
}
6570

@@ -74,9 +79,9 @@ private List<FilterQuery> ParseFilterQuery(string key, string value)
7479
var queries = new List<FilterQuery>();
7580

7681
var propertyName = key.Split('[', ']')[1].ToProperCase();
77-
82+
7883
var values = value.Split(',');
79-
foreach(var val in values)
84+
foreach (var val in values)
8085
{
8186
(var operation, var filterValue) = ParseFilterOperation(val);
8287
queries.Add(new FilterQuery(propertyName, filterValue, operation));
@@ -87,14 +92,14 @@ private List<FilterQuery> ParseFilterQuery(string key, string value)
8792

8893
private (string operation, string value) ParseFilterOperation(string value)
8994
{
90-
if(value.Length < 3)
95+
if (value.Length < 3)
9196
return (string.Empty, value);
92-
97+
9398
var operation = value.Split(':');
9499

95-
if(operation.Length == 1)
100+
if (operation.Length == 1)
96101
return (string.Empty, value);
97-
102+
98103
// remove prefix from value
99104
var prefix = operation[0];
100105
value = operation[1];
@@ -109,7 +114,7 @@ private PageQuery ParsePageQuery(string key, string value)
109114
PageQuery = PageQuery ?? new PageQuery();
110115

111116
var propertyName = key.Split('[', ']')[1];
112-
117+
113118
if (propertyName == "size")
114119
PageQuery.PageSize = Convert.ToInt32(value);
115120
else if (propertyName == "number")
@@ -142,7 +147,7 @@ private List<SortQuery> ParseSortParameters(string value)
142147

143148
private List<string> ParseIncludedRelationships(string value)
144149
{
145-
if(value.Contains("."))
150+
if (value.Contains("."))
146151
throw new JsonApiException(400, "Deeply nested relationships are not supported");
147152

148153
return value
@@ -157,11 +162,11 @@ private List<string> ParseFieldsQuery(string key, string value)
157162

158163
var includedFields = new List<string> { "Id" };
159164

160-
if(typeName != _jsonApiContext.RequestEntity.EntityName)
165+
if (typeName != _jsonApiContext.RequestEntity.EntityName)
161166
return includedFields;
162167

163168
var fields = value.Split(',');
164-
foreach(var field in fields)
169+
foreach (var field in fields)
165170
{
166171
var internalAttrName = _jsonApiContext.RequestEntity
167172
.Attributes

src/JsonApiDotNetCore/Services/IJsonApiContext.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
using System;
12
using System.Collections.Generic;
3+
using System.Reflection;
24
using JsonApiDotNetCore.Builders;
35
using JsonApiDotNetCore.Configuration;
46
using JsonApiDotNetCore.Data;
@@ -12,7 +14,7 @@ namespace JsonApiDotNetCore.Services
1214
public interface IJsonApiContext
1315
{
1416
JsonApiOptions Options { get; set; }
15-
IJsonApiContext ApplyContext<T>();
17+
IJsonApiContext ApplyContext<T>(object controller);
1618
IContextGraph ContextGraph { get; set; }
1719
ContextEntity RequestEntity { get; set; }
1820
string BasePath { get; set; }
@@ -25,6 +27,8 @@ public interface IJsonApiContext
2527
IGenericProcessorFactory GenericProcessorFactory { get; set; }
2628
Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
2729
Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
30+
Type ControllerType { get; set; }
31+
TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
2832
IDbContextResolver GetDbContextResolver();
2933
}
3034
}

src/JsonApiDotNetCore/Services/JsonApiContext.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Reflection;
45
using JsonApiDotNetCore.Builders;
56
using JsonApiDotNetCore.Configuration;
67
using JsonApiDotNetCore.Data;
@@ -46,9 +47,15 @@ public JsonApiContext(
4647
public IGenericProcessorFactory GenericProcessorFactory { get; set; }
4748
public Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; } = new Dictionary<AttrAttribute, object>();
4849
public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
50+
public Type ControllerType { get; set; }
4951

50-
public IJsonApiContext ApplyContext<T>()
52+
public IJsonApiContext ApplyContext<T>(object controller)
5153
{
54+
if (controller == null)
55+
throw new JsonApiException(500, $"Cannot ApplyContext from null controller for type {typeof(T)}");
56+
57+
ControllerType = controller.GetType();
58+
5259
var context = _httpContextAccessor.HttpContext;
5360
var path = context.Request.Path.Value.Split('/');
5461

@@ -83,5 +90,11 @@ private PageManager GetPageManager()
8390
PageSize = query.PageSize > 0 ? query.PageSize : Options.DefaultPageSize
8491
};
8592
}
93+
94+
public TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute
95+
{
96+
var attribute = ControllerType.GetTypeInfo().GetCustomAttribute(typeof(TAttribute));
97+
return attribute == null ? null : (TAttribute)attribute;
98+
}
8699
}
87100
}

0 commit comments

Comments
 (0)