diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs index 58d1a33376..26e16b0741 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs @@ -16,15 +16,8 @@ public class JsonApiOptions public bool AllowClientGeneratedIds { get; set; } public IContextGraph ContextGraph { get; set; } public bool RelativeLinks { get; set; } - - /// - /// This flag is experimental and could be perceived as a violation - /// of the v1 spec. However, we have decided that this is a real - /// requirement for users of this library and a gap in the specification. - /// It will likely be removed when the spec is updated to support this - /// requirement. - /// public bool AllowCustomQueryParameters { get; set; } + [Obsolete("JsonContract resolver can now be set on SerializerSettings.")] public IContractResolver JsonContractResolver { @@ -38,8 +31,7 @@ public IContractResolver JsonContractResolver }; internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder(); - public void BuildContextGraph(Action builder) - where TContext : DbContext + public void BuildContextGraph(Action builder) where TContext : DbContext { BuildContextGraph(builder); diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs index 3d2b14704a..afcc11ee8d 100644 --- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs @@ -110,6 +110,8 @@ public static void AddJsonApiInternals( services.AddScoped(); services.AddScoped(typeof(GenericProcessor<>)); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); } public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions jsonApiOptions) diff --git a/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs b/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs index 628e6187a3..88aac1e67b 100644 --- a/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs +++ b/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs @@ -1,193 +1,13 @@ -using System; using System.Collections.Generic; -using System.Linq; -using JsonApiDotNetCore.Extensions; -using JsonApiDotNetCore.Services; -using Microsoft.AspNetCore.Http; -using JsonApiDotNetCore.Models; -using JsonApiDotNetCore.Controllers; namespace JsonApiDotNetCore.Internal.Query { public class QuerySet { - private readonly IJsonApiContext _jsonApiContext; - - public QuerySet( - IJsonApiContext jsonApiContext, - IQueryCollection query) - { - _jsonApiContext = jsonApiContext; - BuildQuerySet(query); - } - public List Filters { get; set; } = new List(); public PageQuery PageQuery { get; set; } = new PageQuery(); public List SortParameters { get; set; } = new List(); public List IncludedRelationships { get; set; } = new List(); public List Fields { get; set; } = new List(); - - private void BuildQuerySet(IQueryCollection query) - { - var disabledQueries = _jsonApiContext.GetControllerAttribute()?.QueryParams ?? QueryParams.None; - - foreach (var pair in query) - { - if (pair.Key.StartsWith("filter")) - { - if (disabledQueries.HasFlag(QueryParams.Filter) == false) - Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value)); - continue; - } - - if (pair.Key.StartsWith("sort")) - { - if (disabledQueries.HasFlag(QueryParams.Sort) == false) - SortParameters = ParseSortParameters(pair.Value); - continue; - } - - if (pair.Key.StartsWith("include")) - { - if (disabledQueries.HasFlag(QueryParams.Include) == false) - IncludedRelationships = ParseIncludedRelationships(pair.Value); - continue; - } - - if (pair.Key.StartsWith("page")) - { - if (disabledQueries.HasFlag(QueryParams.Page) == false) - PageQuery = ParsePageQuery(pair.Key, pair.Value); - continue; - } - - if (pair.Key.StartsWith("fields")) - { - if (disabledQueries.HasFlag(QueryParams.Fields) == false) - Fields = ParseFieldsQuery(pair.Key, pair.Value); - continue; - } - - if (_jsonApiContext.Options.AllowCustomQueryParameters == false) - throw new JsonApiException(400, $"{pair} is not a valid query."); - } - } - - private List ParseFilterQuery(string key, string value) - { - // expected input = filter[id]=1 - // expected input = filter[id]=eq:1 - var queries = new List(); - - var propertyName = key.Split('[', ']')[1].ToProperCase(); - - var values = value.Split(','); - foreach (var val in values) - { - (var operation, var filterValue) = ParseFilterOperation(val); - queries.Add(new FilterQuery(propertyName, filterValue, operation)); - } - - return queries; - } - - private (string operation, string value) ParseFilterOperation(string value) - { - if (value.Length < 3) - return (string.Empty, value); - - var operation = value.Split(':'); - - if (operation.Length == 1) - return (string.Empty, value); - - // remove prefix from value - if (Enum.TryParse(operation[0], out FilterOperations op) == false) - return (string.Empty, value); - - var prefix = operation[0]; - value = string.Join(":", operation.Skip(1)); - - return (prefix, value); - } - - private PageQuery ParsePageQuery(string key, string value) - { - // expected input = page[size]=10 - // page[number]=1 - PageQuery = PageQuery ?? new PageQuery(); - - var propertyName = key.Split('[', ']')[1]; - - if (propertyName == "size") - PageQuery.PageSize = Convert.ToInt32(value); - else if (propertyName == "number") - PageQuery.PageOffset = Convert.ToInt32(value); - - return PageQuery; - } - - // sort=id,name - // sort=-id - private List ParseSortParameters(string value) - { - var sortParameters = new List(); - value.Split(',').ToList().ForEach(p => - { - var direction = SortDirection.Ascending; - if (p[0] == '-') - { - direction = SortDirection.Descending; - p = p.Substring(1); - } - - var attribute = GetAttribute(p.ToProperCase()); - - sortParameters.Add(new SortQuery(direction, attribute)); - }); - - return sortParameters; - } - - private List ParseIncludedRelationships(string value) - { - if (value.Contains(".")) - throw new JsonApiException(400, "Deeply nested relationships are not supported"); - - return value - .Split(',') - .ToList(); - } - - private List ParseFieldsQuery(string key, string value) - { - // expected: fields[TYPE]=prop1,prop2 - var typeName = key.Split('[', ']')[1]; - - var includedFields = new List { "Id" }; - - if (typeName != _jsonApiContext.RequestEntity.EntityName) - return includedFields; - - var fields = value.Split(','); - foreach (var field in fields) - { - var internalAttrName = _jsonApiContext.RequestEntity - .Attributes - .SingleOrDefault(attr => attr.PublicAttributeName == field) - .InternalAttributeName; - includedFields.Add(internalAttrName); - } - - return includedFields; - } - - private AttrAttribute GetAttribute(string propertyName) - { - return _jsonApiContext.RequestEntity.Attributes - .FirstOrDefault(attr => - attr.InternalAttributeName.ToLower() == propertyName.ToLower() - ); - } } } \ No newline at end of file diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 03628876b9..c3c987f32a 100755 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -1,6 +1,6 @@  - 2.1.8 + 2.1.9 netstandard1.6 JsonApiDotNetCore JsonApiDotNetCore diff --git a/src/JsonApiDotNetCore/Services/ControllerContext.cs b/src/JsonApiDotNetCore/Services/ControllerContext.cs new file mode 100644 index 0000000000..1984262b15 --- /dev/null +++ b/src/JsonApiDotNetCore/Services/ControllerContext.cs @@ -0,0 +1,25 @@ +using System; +using System.Reflection; +using JsonApiDotNetCore.Internal; + +namespace JsonApiDotNetCore.Services +{ + public interface IControllerContext + { + Type ControllerType { get; set; } + ContextEntity RequestEntity { get; set; } + TAttribute GetControllerAttribute() where TAttribute : Attribute; + } + + public class ControllerContext : IControllerContext + { + public Type ControllerType { get; set; } + public ContextEntity RequestEntity { get; set; } + + public TAttribute GetControllerAttribute() where TAttribute : Attribute + { + var attribute = ControllerType.GetTypeInfo().GetCustomAttribute(typeof(TAttribute)); + return attribute == null ? null : (TAttribute)attribute; + } + } +} \ No newline at end of file diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs index e634938087..a93d76acdc 100644 --- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs +++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using JsonApiDotNetCore.Builders; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Data; @@ -17,6 +16,8 @@ public class JsonApiContext : IJsonApiContext { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IDbContextResolver _contextResolver; + private readonly IQueryParser _queryParser; + private readonly IControllerContext _controllerContext; public JsonApiContext( IDbContextResolver contextResolver, @@ -24,7 +25,9 @@ public JsonApiContext( IHttpContextAccessor httpContextAccessor, JsonApiOptions options, IMetaBuilder metaBuilder, - IGenericProcessorFactory genericProcessorFactory) + IGenericProcessorFactory genericProcessorFactory, + IQueryParser queryParser, + IControllerContext controllerContext) { _contextResolver = contextResolver; ContextGraph = contextGraph; @@ -32,11 +35,14 @@ public JsonApiContext( Options = options; MetaBuilder = metaBuilder; GenericProcessorFactory = genericProcessorFactory; + _queryParser = queryParser; + _controllerContext = controllerContext; } public JsonApiOptions Options { get; set; } public IContextGraph ContextGraph { get; set; } - public ContextEntity RequestEntity { get; set; } + [Obsolete("Use the proxied member IControllerContext.RequestEntity instead.")] + public ContextEntity RequestEntity { get => _controllerContext.RequestEntity; set => _controllerContext.RequestEntity = value; } public string BasePath { get; set; } public QuerySet QuerySet { get; set; } public bool IsRelationshipData { get; set; } @@ -54,21 +60,20 @@ public IJsonApiContext ApplyContext(object controller) if (controller == null) throw new JsonApiException(500, $"Cannot ApplyContext from null controller for type {typeof(T)}"); - ControllerType = controller.GetType(); + _controllerContext.ControllerType = controller.GetType(); + _controllerContext.RequestEntity = ContextGraph.GetContextEntity(typeof(T)); var context = _httpContextAccessor.HttpContext; var path = context.Request.Path.Value.Split('/'); - RequestEntity = ContextGraph.GetContextEntity(typeof(T)); - if (context.Request.Query.Any()) { - QuerySet = new QuerySet(this, context.Request.Query); + QuerySet = _queryParser.Parse(context.Request.Query); IncludedRelationships = QuerySet.IncludedRelationships; } var linkBuilder = new LinkBuilder(this); - BasePath = linkBuilder.GetBasePath(context, RequestEntity.EntityName); + BasePath = linkBuilder.GetBasePath(context, _controllerContext.RequestEntity.EntityName); PageManager = GetPageManager(); IsRelationshipPath = path[path.Length - 2] == "relationships"; return this; @@ -91,10 +96,8 @@ private PageManager GetPageManager() }; } + [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")] public TAttribute GetControllerAttribute() where TAttribute : Attribute - { - var attribute = ControllerType.GetTypeInfo().GetCustomAttribute(typeof(TAttribute)); - return attribute == null ? null : (TAttribute)attribute; - } + => _controllerContext.GetControllerAttribute(); } } diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs new file mode 100644 index 0000000000..26c735e30c --- /dev/null +++ b/src/JsonApiDotNetCore/Services/QueryParser.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Extensions; +using JsonApiDotNetCore.Internal; +using JsonApiDotNetCore.Internal.Query; +using JsonApiDotNetCore.Models; +using Microsoft.AspNetCore.Http; + +namespace JsonApiDotNetCore.Services +{ + public interface IQueryParser + { + QuerySet Parse(IQueryCollection query); + } + + public class QueryParser : IQueryParser + { + private readonly IControllerContext _controllerContext; + private readonly JsonApiOptions _options; + + public QueryParser( + IControllerContext controllerContext, + JsonApiOptions options) + { + _controllerContext = controllerContext; + _options = options; + } + + public QuerySet Parse(IQueryCollection query) + { + var querySet = new QuerySet(); + var disabledQueries = _controllerContext.GetControllerAttribute()?.QueryParams ?? QueryParams.None; + + foreach (var pair in query) + { + if (pair.Key.StartsWith("filter")) + { + if (disabledQueries.HasFlag(QueryParams.Filter) == false) + querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value)); + continue; + } + + if (pair.Key.StartsWith("sort")) + { + if (disabledQueries.HasFlag(QueryParams.Sort) == false) + querySet.SortParameters = ParseSortParameters(pair.Value); + continue; + } + + if (pair.Key.StartsWith("include")) + { + if (disabledQueries.HasFlag(QueryParams.Include) == false) + querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value); + continue; + } + + if (pair.Key.StartsWith("page")) + { + if (disabledQueries.HasFlag(QueryParams.Page) == false) + querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value); + continue; + } + + if (pair.Key.StartsWith("fields")) + { + if (disabledQueries.HasFlag(QueryParams.Fields) == false) + querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value); + continue; + } + + if (_options.AllowCustomQueryParameters == false) + throw new JsonApiException(400, $"{pair} is not a valid query."); + } + + return querySet; + } + + private List ParseFilterQuery(string key, string value) + { + // expected input = filter[id]=1 + // expected input = filter[id]=eq:1 + var queries = new List(); + + var propertyName = key.Split('[', ']')[1].ToProperCase(); + + var values = value.Split(','); + foreach (var val in values) + { + (var operation, var filterValue) = ParseFilterOperation(val); + queries.Add(new FilterQuery(propertyName, filterValue, operation)); + } + + return queries; + } + + private (string operation, string value) ParseFilterOperation(string value) + { + if (value.Length < 3) + return (string.Empty, value); + + var operation = value.Split(':'); + + if (operation.Length == 1) + return (string.Empty, value); + + // remove prefix from value + if (Enum.TryParse(operation[0], out FilterOperations op) == false) + return (string.Empty, value); + + var prefix = operation[0]; + value = string.Join(":", operation.Skip(1)); + + return (prefix, value); + } + + private PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value) + { + // expected input = page[size]=10 + // page[number]=1 + pageQuery = pageQuery ?? new PageQuery(); + + var propertyName = key.Split('[', ']')[1]; + + if (propertyName == "size") + pageQuery.PageSize = Convert.ToInt32(value); + else if (propertyName == "number") + pageQuery.PageOffset = Convert.ToInt32(value); + + return pageQuery; + } + + // sort=id,name + // sort=-id + private List ParseSortParameters(string value) + { + var sortParameters = new List(); + value.Split(',').ToList().ForEach(p => + { + var direction = SortDirection.Ascending; + if (p[0] == '-') + { + direction = SortDirection.Descending; + p = p.Substring(1); + } + + var attribute = GetAttribute(p.ToProperCase()); + + sortParameters.Add(new SortQuery(direction, attribute)); + }); + + return sortParameters; + } + + private List ParseIncludedRelationships(string value) + { + if (value.Contains(".")) + throw new JsonApiException(400, "Deeply nested relationships are not supported"); + + return value + .Split(',') + .ToList(); + } + + private List ParseFieldsQuery(string key, string value) + { + // expected: fields[TYPE]=prop1,prop2 + var typeName = key.Split('[', ']')[1]; + + var includedFields = new List { "Id" }; + + if (typeName != _controllerContext.RequestEntity.EntityName) + return includedFields; + + var fields = value.Split(','); + foreach (var field in fields) + { + var internalAttrName = _controllerContext.RequestEntity + .Attributes + .SingleOrDefault(attr => attr.PublicAttributeName == field) + .InternalAttributeName; + includedFields.Add(internalAttrName); + } + + return includedFields; + } + + private AttrAttribute GetAttribute(string propertyName) + => _controllerContext + .RequestEntity + .Attributes + .FirstOrDefault(attr => + string.Equals(attr.InternalAttributeName, propertyName, StringComparison.OrdinalIgnoreCase) + ); + } +} \ No newline at end of file diff --git a/test/UnitTests/Services/QueryAccessorTests.cs b/test/UnitTests/Services/QueryAccessorTests.cs index 45538fde66..aa8bc6ae7e 100644 --- a/test/UnitTests/Services/QueryAccessorTests.cs +++ b/test/UnitTests/Services/QueryAccessorTests.cs @@ -5,7 +5,6 @@ using JsonApiDotNetCore.Services; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; using Moq; using Xunit; @@ -28,19 +27,16 @@ public QueryAccessorTests() public void Can_Get_Guid_QueryValue() { // arrange - const string key = "some-id"; - var filterQuery = $"filter[{key}]"; + const string key = "SomeId"; var value = Guid.NewGuid(); - - var query = new Dictionary { - { filterQuery, value.ToString() } + var querySet = new QuerySet + { + Filters = new List { + new FilterQuery(key, value.ToString(), "eq") + } }; - _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator()); - - var querySet = new QuerySet(_contextMock.Object, _queryMock.Object); - _contextMock.Setup(c => c.QuerySet) - .Returns(querySet); + _contextMock.Setup(c => c.QuerySet).Returns(querySet); var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object); @@ -56,19 +52,17 @@ public void Can_Get_Guid_QueryValue() public void GetRequired_Throws_If_Not_Present() { // arrange - const string key = "some-id"; - var filterQuery = $"filter[{key}]"; + const string key = "SomeId"; var value = Guid.NewGuid(); - var query = new Dictionary { - { filterQuery, value.ToString() } + var querySet = new QuerySet + { + Filters = new List { + new FilterQuery(key, value.ToString(), "eq") + } }; - _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator()); - - var querySet = new QuerySet(_contextMock.Object, _queryMock.Object); - _contextMock.Setup(c => c.QuerySet) - .Returns(querySet); + _contextMock.Setup(c => c.QuerySet).Returns(querySet); var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object); @@ -83,19 +77,17 @@ public void GetRequired_Throws_If_Not_Present() public void GetRequired_Does_Not_Throw_If_Present() { // arrange - const string key = "some-id"; - var filterQuery = $"filter[{key}]"; + const string key = "SomeId"; var value = Guid.NewGuid(); - var query = new Dictionary { - { filterQuery, value.ToString() } + var querySet = new QuerySet + { + Filters = new List { + new FilterQuery(key, value.ToString(), "eq") + } }; - _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator()); - - var querySet = new QuerySet(_contextMock.Object, _queryMock.Object); - _contextMock.Setup(c => c.QuerySet) - .Returns(querySet); + _contextMock.Setup(c => c.QuerySet).Returns(querySet); var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object); diff --git a/test/UnitTests/Internal/QuerySet_Tests.cs b/test/UnitTests/Services/QueryParser_Tests.cs similarity index 72% rename from test/UnitTests/Internal/QuerySet_Tests.cs rename to test/UnitTests/Services/QueryParser_Tests.cs index 2a433e63af..a64c5b3692 100644 --- a/test/UnitTests/Internal/QuerySet_Tests.cs +++ b/test/UnitTests/Services/QueryParser_Tests.cs @@ -1,25 +1,23 @@ -using System; using System.Collections.Generic; using System.Linq; +using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers; -using JsonApiDotNetCore.Internal; -using JsonApiDotNetCore.Internal.Query; using JsonApiDotNetCore.Services; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Moq; using Xunit; -namespace UnitTests.Internal +namespace UnitTests.Services { - public class QuerySet_Tests + public class QueryParser_Tests { - private readonly Mock _jsonApiContextMock; + private readonly Mock _controllerContextMock; private readonly Mock _queryCollectionMock; - public QuerySet_Tests() + public QueryParser_Tests() { - _jsonApiContextMock = new Mock(); + _controllerContextMock = new Mock(); _queryCollectionMock = new Mock(); } @@ -35,14 +33,14 @@ public void Can_Build_Filters() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.None)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Equal("value", querySet.Filters.Single(f => f.Key == "Key").Value); @@ -61,14 +59,14 @@ public void Filters_Properly_Parses_DateTime_With_Operation() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.None)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value); @@ -88,14 +86,14 @@ public void Filters_Properly_Parses_DateTime_Without_Operation() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.None)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value); @@ -114,14 +112,14 @@ public void Can_Disable_Filters() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.Filter)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Empty(querySet.Filters); @@ -139,14 +137,14 @@ public void Can_Disable_Sort() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.Sort)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Empty(querySet.SortParameters); @@ -164,14 +162,14 @@ public void Can_Disable_Include() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.Include)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Empty(querySet.IncludedRelationships); @@ -189,14 +187,14 @@ public void Can_Disable_Page() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.Page)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Equal(0, querySet.PageQuery.PageSize); @@ -214,14 +212,14 @@ public void Can_Disable_Fields() .Setup(m => m.GetEnumerator()) .Returns(query.GetEnumerator()); - _jsonApiContextMock + _controllerContextMock .Setup(m => m.GetControllerAttribute()) .Returns(new DisableQueryAttribute(QueryParams.Fields)); - // act -- ctor calls BuildQuerySet() - var querySet = new QuerySet( - _jsonApiContextMock.Object, - _queryCollectionMock.Object); + var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions()); + + // act + var querySet = queryParser.Parse(_queryCollectionMock.Object); // assert Assert.Empty(querySet.Fields);