From 714bf89ba9e8f0c587b23fe718c4fc93863268c3 Mon Sep 17 00:00:00 2001 From: Simon Hofer Date: Fri, 5 Aug 2016 19:10:42 +0200 Subject: [PATCH 1/3] Feat: added pagination with metadata - metadata to indicate the count of pages and total count of records - acceptance tests pagination in combination with filters and sorting --- .../Pagination/GetAllResponsePaged-2-2.json | 66 ++++++++++++++++ .../GetFilterPaged-1-2-sorted-desc.json | 64 +++++++++++++++ .../Pagination/GetFilterPaged-1-2-sorted.json | 64 +++++++++++++++ .../Pagination/GetFilterPaged-2-1.json | 36 +++++++++ ...sts.EntityFrameworkTestWebApp.Tests.csproj | 6 ++ .../PaginationTests.cs | 77 +++++++++++++++++++ ...tionDocument_for_all_possible_members.json | 20 ++--- ...nt_for_primary_data_only_and_metadata.json | 10 +-- ...ryableResourceCollectionDocumentBuilder.cs | 13 +++- JSONAPI/Documents/Metadata.cs | 16 ++++ JSONAPI/JSONAPI.csproj | 1 + .../ResourceCollectionDocumentFormatter.cs | 12 +-- README.md | 9 +++ 13 files changed, 372 insertions(+), 22 deletions(-) create mode 100644 JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetAllResponsePaged-2-2.json create mode 100644 JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted-desc.json create mode 100644 JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted.json create mode 100644 JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-2-1.json create mode 100644 JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/PaginationTests.cs create mode 100644 JSONAPI/Documents/Metadata.cs diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetAllResponsePaged-2-2.json b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetAllResponsePaged-2-2.json new file mode 100644 index 00000000..7bf2f5ba --- /dev/null +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetAllResponsePaged-2-2.json @@ -0,0 +1,66 @@ +{ + "meta": { + "total-pages": 2, + "total-count": 4 + }, + "data": [ + { + "type": "posts", + "id": "203", + "attributes": { + "content": "Post 3 content", + "created": "2015-02-07T11:11:00.0000000+00:00", + "title": "Post 3" + }, + "relationships": { + "author": { + "links": { + "self": "https://www.example.com/posts/203/relationships/author", + "related": "https://www.example.com/posts/203/author" + } + }, + "comments": { + "links": { + "self": "https://www.example.com/posts/203/relationships/comments", + "related": "https://www.example.com/posts/203/comments" + } + }, + "tags": { + "links": { + "self": "https://www.example.com/posts/203/relationships/tags", + "related": "https://www.example.com/posts/203/tags" + } + } + } + }, + { + "type": "posts", + "id": "204", + "attributes": { + "content": "Post 4 content", + "created": "2015-02-08T06:59:00.0000000+00:00", + "title": "Post 4" + }, + "relationships": { + "author": { + "links": { + "self": "https://www.example.com/posts/204/relationships/author", + "related": "https://www.example.com/posts/204/author" + } + }, + "comments": { + "links": { + "self": "https://www.example.com/posts/204/relationships/comments", + "related": "https://www.example.com/posts/204/comments" + } + }, + "tags": { + "links": { + "self": "https://www.example.com/posts/204/relationships/tags", + "related": "https://www.example.com/posts/204/tags" + } + } + } + } + ] +} \ No newline at end of file diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted-desc.json b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted-desc.json new file mode 100644 index 00000000..b65cea48 --- /dev/null +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted-desc.json @@ -0,0 +1,64 @@ +{ + "meta": { + "total-pages": 2, + "total-count": 3 + }, + "data": [ + { + "type": "users", + "id": "410", + "attributes": { + "first-name": "Sally", + "last-name": "Burns" + }, + "relationships": { + "comments": { + "links": { + "self": "https://www.example.com/users/410/relationships/comments", + "related": "https://www.example.com/users/410/comments" + } + }, + "posts": { + "links": { + "self": "https://www.example.com/users/410/relationships/posts", + "related": "https://www.example.com/users/410/posts" + } + }, + "user-groups": { + "links": { + "self": "https://www.example.com/users/410/relationships/user-groups", + "related": "https://www.example.com/users/410/user-groups" + } + } + } + }, + { + "type": "users", + "id": "406", + "attributes": { + "first-name": "Ed", + "last-name": "Burns" + }, + "relationships": { + "comments": { + "links": { + "self": "https://www.example.com/users/406/relationships/comments", + "related": "https://www.example.com/users/406/comments" + } + }, + "posts": { + "links": { + "self": "https://www.example.com/users/406/relationships/posts", + "related": "https://www.example.com/users/406/posts" + } + }, + "user-groups": { + "links": { + "self": "https://www.example.com/users/406/relationships/user-groups", + "related": "https://www.example.com/users/406/user-groups" + } + } + } + } + ] +} \ No newline at end of file diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted.json b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted.json new file mode 100644 index 00000000..ee562655 --- /dev/null +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-1-2-sorted.json @@ -0,0 +1,64 @@ +{ + "meta": { + "total-pages": 2, + "total-count": 3 + }, + "data": [ + { + "type": "users", + "id": "409", + "attributes": { + "first-name": "Charlie", + "last-name": "Burns" + }, + "relationships": { + "comments": { + "links": { + "self": "https://www.example.com/users/409/relationships/comments", + "related": "https://www.example.com/users/409/comments" + } + }, + "posts": { + "links": { + "self": "https://www.example.com/users/409/relationships/posts", + "related": "https://www.example.com/users/409/posts" + } + }, + "user-groups": { + "links": { + "self": "https://www.example.com/users/409/relationships/user-groups", + "related": "https://www.example.com/users/409/user-groups" + } + } + } + }, + { + "type": "users", + "id": "406", + "attributes": { + "first-name": "Ed", + "last-name": "Burns" + }, + "relationships": { + "comments": { + "links": { + "self": "https://www.example.com/users/406/relationships/comments", + "related": "https://www.example.com/users/406/comments" + } + }, + "posts": { + "links": { + "self": "https://www.example.com/users/406/relationships/posts", + "related": "https://www.example.com/users/406/posts" + } + }, + "user-groups": { + "links": { + "self": "https://www.example.com/users/406/relationships/user-groups", + "related": "https://www.example.com/users/406/user-groups" + } + } + } + } + ] +} \ No newline at end of file diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-2-1.json b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-2-1.json new file mode 100644 index 00000000..16e92908 --- /dev/null +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/Pagination/GetFilterPaged-2-1.json @@ -0,0 +1,36 @@ +{ + "meta": { + "total-pages": 3, + "total-count": 3 + }, + "data": [ + { + "type": "users", + "id": "409", + "attributes": { + "first-name": "Charlie", + "last-name": "Burns" + }, + "relationships": { + "comments": { + "links": { + "self": "https://www.example.com/users/409/relationships/comments", + "related": "https://www.example.com/users/409/comments" + } + }, + "posts": { + "links": { + "self": "https://www.example.com/users/409/relationships/posts", + "related": "https://www.example.com/users/409/posts" + } + }, + "user-groups": { + "links": { + "self": "https://www.example.com/users/409/relationships/user-groups", + "related": "https://www.example.com/users/409/user-groups" + } + } + } + } + ] +} \ No newline at end of file diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests.csproj b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests.csproj index b8546fbf..e9cb8a2c 100644 --- a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests.csproj +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests.csproj @@ -106,6 +106,7 @@ + @@ -275,8 +276,13 @@ + + + + + diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/PaginationTests.cs b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/PaginationTests.cs new file mode 100644 index 00000000..0db20f57 --- /dev/null +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/PaginationTests.cs @@ -0,0 +1,77 @@ +using System.Net; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests +{ + [TestClass] + public class PaginationTests : AcceptanceTestsBase + { + [TestMethod] + [DeploymentItem(@"Data\Comment.csv", @"Data")] + [DeploymentItem(@"Data\Post.csv", @"Data")] + [DeploymentItem(@"Data\PostTagLink.csv", @"Data")] + [DeploymentItem(@"Data\Tag.csv", @"Data")] + [DeploymentItem(@"Data\User.csv", @"Data")] + public async Task GetPage2Post2() + { + using (var effortConnection = GetEffortConnection()) + { + var response = await SubmitGet(effortConnection, "posts?page[number]=1&page[size]=2"); + + await AssertResponseContent(response, @"Fixtures\Pagination\GetAllResponsePaged-2-2.json", HttpStatusCode.OK); + } + } + + [TestMethod] + [DeploymentItem(@"Data\Comment.csv", @"Data")] + [DeploymentItem(@"Data\Post.csv", @"Data")] + [DeploymentItem(@"Data\PostTagLink.csv", @"Data")] + [DeploymentItem(@"Data\Tag.csv", @"Data")] + [DeploymentItem(@"Data\User.csv", @"Data")] + public async Task GetWithFilter() + { + using (var effortConnection = GetEffortConnection()) + { + var response = await SubmitGet(effortConnection, "users?filter[last-name]=Burns&page[number]=1&page[size]=1"); + + await AssertResponseContent(response, @"Fixtures\Pagination\GetFilterPaged-2-1.json", HttpStatusCode.OK); + } + } + + + [TestMethod] + [DeploymentItem(@"Data\Comment.csv", @"Data")] + [DeploymentItem(@"Data\Post.csv", @"Data")] + [DeploymentItem(@"Data\PostTagLink.csv", @"Data")] + [DeploymentItem(@"Data\Tag.csv", @"Data")] + [DeploymentItem(@"Data\User.csv", @"Data")] + public async Task GetWithFilterSortedAscTest() + { + using (var effortConnection = GetEffortConnection()) + { + var response = await SubmitGet(effortConnection, "users?filter[last-name]=Burns&page[number]=0&page[size]=2&sort=first-name"); + + await AssertResponseContent(response, @"Fixtures\Pagination\GetFilterPaged-1-2-sorted.json", HttpStatusCode.OK); + } + } + + + [TestMethod] + [DeploymentItem(@"Data\Comment.csv", @"Data")] + [DeploymentItem(@"Data\Post.csv", @"Data")] + [DeploymentItem(@"Data\PostTagLink.csv", @"Data")] + [DeploymentItem(@"Data\Tag.csv", @"Data")] + [DeploymentItem(@"Data\User.csv", @"Data")] + public async Task GetWithFilterSortedDescTest() + { + using (var effortConnection = GetEffortConnection()) + { + var response = await SubmitGet(effortConnection, "users?filter[last-name]=Burns&page[number]=0&page[size]=2&sort=-first-name"); + + await AssertResponseContent(response, @"Fixtures\Pagination\GetFilterPaged-1-2-sorted-desc.json", HttpStatusCode.OK); + } + } + + } +} diff --git a/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_all_possible_members.json b/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_all_possible_members.json index 9eb2c810..fad9ad33 100644 --- a/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_all_possible_members.json +++ b/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_all_possible_members.json @@ -1,12 +1,12 @@ { - "data": [ - "Primary data 1", - "Primary data 2" - ], - "included": [ - "Related data object 1", - "Related data object 2", - "Related data object 3" - ], - "meta": "Placeholder metadata object" + "meta": "Placeholder metadata object", + "data": [ + "Primary data 1", + "Primary data 2" + ], + "included": [ + "Related data object 1", + "Related data object 2", + "Related data object 3" + ] } \ No newline at end of file diff --git a/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_primary_data_only_and_metadata.json b/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_primary_data_only_and_metadata.json index ef98daf7..6d770373 100644 --- a/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_primary_data_only_and_metadata.json +++ b/JSONAPI.Tests/Json/Fixtures/ResourceCollectionDocumentFormatter/Serialize_ResourceCollectionDocument_for_primary_data_only_and_metadata.json @@ -1,7 +1,7 @@ { - "data": [ - "Primary data 1", - "Primary data 2" - ], - "meta": "Placeholder metadata object" + "meta": "Placeholder metadata object", + "data": [ + "Primary data 1", + "Primary data 2" + ] } \ No newline at end of file diff --git a/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs b/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs index d47e93c6..68534218 100644 --- a/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs +++ b/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs @@ -1,9 +1,11 @@ -using System.Linq; +using System; +using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using JSONAPI.Http; using JSONAPI.QueryableTransformers; +using Newtonsoft.Json.Linq; namespace JSONAPI.Documents.Builders { @@ -60,7 +62,14 @@ public async Task BuildDocument(IQueryable qu protected virtual Task GetDocumentMetadata(IQueryable originalQuery, IQueryable filteredQuery, IOrderedQueryable sortedQuery, IPaginationTransformResult paginationResult, CancellationToken cancellationToken) { - return Task.FromResult((IMetadata)null); + var metadata = new Metadata(); + if (paginationResult.PaginationWasApplied) { + metadata.MetaObject.Add("total-pages", (int)Math.Ceiling((decimal)filteredQuery.Count() / paginationResult.PageSize)); + metadata.MetaObject.Add("total-count", filteredQuery.Count()); + } + if (metadata.MetaObject.HasValues) + return Task.FromResult((IMetadata)metadata); + return Task.FromResult((IMetadata) null); } } } diff --git a/JSONAPI/Documents/Metadata.cs b/JSONAPI/Documents/Metadata.cs new file mode 100644 index 00000000..004de8c7 --- /dev/null +++ b/JSONAPI/Documents/Metadata.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json.Linq; + +namespace JSONAPI.Documents +{ + /// + /// Default implementation of + /// + public class Metadata : IMetadata + { + public Metadata() + { + MetaObject = new JObject(); + } + public JObject MetaObject { get; } + } +} diff --git a/JSONAPI/JSONAPI.csproj b/JSONAPI/JSONAPI.csproj index 4336261f..9bd3d2e2 100644 --- a/JSONAPI/JSONAPI.csproj +++ b/JSONAPI/JSONAPI.csproj @@ -91,6 +91,7 @@ + diff --git a/JSONAPI/Json/ResourceCollectionDocumentFormatter.cs b/JSONAPI/Json/ResourceCollectionDocumentFormatter.cs index 79cd75d8..b7a0c999 100644 --- a/JSONAPI/Json/ResourceCollectionDocumentFormatter.cs +++ b/JSONAPI/Json/ResourceCollectionDocumentFormatter.cs @@ -75,6 +75,12 @@ public Task Serialize(IResourceCollectionDocument document, JsonWriter writer) { writer.WriteStartObject(); + if (document.Metadata != null) + { + writer.WritePropertyName(MetaKeyName); + MetadataFormatter.Serialize(document.Metadata, writer); + } + writer.WritePropertyName(PrimaryDataKeyName); writer.WriteStartArray(); @@ -95,11 +101,7 @@ public Task Serialize(IResourceCollectionDocument document, JsonWriter writer) writer.WriteEndArray(); } - if (document.Metadata != null) - { - writer.WritePropertyName(MetaKeyName); - MetadataFormatter.Serialize(document.Metadata, writer); - } + writer.WriteEndObject(); diff --git a/README.md b/README.md index 129060b7..855df218 100644 --- a/README.md +++ b/README.md @@ -139,3 +139,12 @@ configuration.CustomBaseUrlService = new BaseUrlService(new Uri("https://api.exa ``` +# Metadata + + + +## Pagination + +### total-pages / total-count +When pagination is used the `total-pages` and `total-count` meta properties are provided to indicate the number of pages and records to the client. + From eaea63909ba2cbb9d2a71cf8bca24b2c39b0baa2 Mon Sep 17 00:00:00 2001 From: Simon Hofer Date: Mon, 12 Sep 2016 09:19:26 +0200 Subject: [PATCH 2/3] moved total-pages and total-count to Entity Framework specific subclass. reduced the number of count calls to save roundtrips --- .../Startup.cs | 4 ++ ...ryableResourceCollectionDocumentBuilder.cs | 55 +++++++++++++++++++ .../JSONAPI.EntityFramework.csproj | 1 + ...ryableResourceCollectionDocumentBuilder.cs | 11 +--- README.md | 1 + 5 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Startup.cs b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Startup.cs index aec594d2..678f8532 100644 --- a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Startup.cs +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Startup.cs @@ -14,6 +14,8 @@ using JSONAPI.EntityFramework.Configuration; using Owin; using System.Collections.Generic; +using JSONAPI.Documents.Builders; +using JSONAPI.EntityFramework.Documents.Builders; namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp { @@ -112,6 +114,8 @@ internal JsonApiHttpAutofacConfigurator BuildAutofacConfigurator(IAppBuilder app builder.RegisterType() .As(); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); + builder.RegisterType().As(); + }); configurator.OnApplicationLifetimeScopeBegun(applicationLifetimeScope => { diff --git a/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs b/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs new file mode 100644 index 00000000..d630b0aa --- /dev/null +++ b/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs @@ -0,0 +1,55 @@ +using System; +using System.Data.Entity; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using JSONAPI.Documents; +using JSONAPI.Documents.Builders; +using JSONAPI.Http; +using JSONAPI.QueryableTransformers; + +namespace JSONAPI.EntityFramework.Documents.Builders +{ + /// + /// Provides a entity framework implementation of an IQueryableResourceCollectionDocumentBuilder + /// + public class EntityFrameworkQueryableResourceCollectionDocumentBuilder: DefaultQueryableResourceCollectionDocumentBuilder + { + /// + /// Creates a new EntityFrameworkQueryableResourceCollectionDocumentBuilder + /// + public EntityFrameworkQueryableResourceCollectionDocumentBuilder( + IResourceCollectionDocumentBuilder resourceCollectionDocumentBuilder, + IQueryableEnumerationTransformer enumerationTransformer, + IQueryableFilteringTransformer filteringTransformer, + IQueryableSortingTransformer sortingTransformer, + IQueryablePaginationTransformer paginationTransformer, + IBaseUrlService baseUrlService) : + base(resourceCollectionDocumentBuilder, + enumerationTransformer, + filteringTransformer, + sortingTransformer, + paginationTransformer, + baseUrlService) + { + } + + /// + /// Returns the metadata that should be sent with this document. + /// + protected override async Task GetDocumentMetadata(IQueryable originalQuery, IQueryable filteredQuery, IOrderedQueryable sortedQuery, + IPaginationTransformResult paginationResult, CancellationToken cancellationToken) + { + var metadata = new Metadata(); + if (paginationResult.PaginationWasApplied) + { + var count = filteredQuery.CountAsync(cancellationToken); + metadata.MetaObject.Add("total-pages", (int)Math.Ceiling((decimal) await count / paginationResult.PageSize)); + metadata.MetaObject.Add("total-count", await count); + } + if (metadata.MetaObject.HasValues) + return metadata; + return null; + } + } +} diff --git a/JSONAPI.EntityFramework/JSONAPI.EntityFramework.csproj b/JSONAPI.EntityFramework/JSONAPI.EntityFramework.csproj index 0f1dd5c8..2045b33d 100644 --- a/JSONAPI.EntityFramework/JSONAPI.EntityFramework.csproj +++ b/JSONAPI.EntityFramework/JSONAPI.EntityFramework.csproj @@ -72,6 +72,7 @@ + diff --git a/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs b/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs index 68534218..d0488b1c 100644 --- a/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs +++ b/JSONAPI/Documents/Builders/DefaultQueryableResourceCollectionDocumentBuilder.cs @@ -1,11 +1,9 @@ -using System; -using System.Linq; +using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using JSONAPI.Http; using JSONAPI.QueryableTransformers; -using Newtonsoft.Json.Linq; namespace JSONAPI.Documents.Builders { @@ -62,13 +60,6 @@ public async Task BuildDocument(IQueryable qu protected virtual Task GetDocumentMetadata(IQueryable originalQuery, IQueryable filteredQuery, IOrderedQueryable sortedQuery, IPaginationTransformResult paginationResult, CancellationToken cancellationToken) { - var metadata = new Metadata(); - if (paginationResult.PaginationWasApplied) { - metadata.MetaObject.Add("total-pages", (int)Math.Ceiling((decimal)filteredQuery.Count() / paginationResult.PageSize)); - metadata.MetaObject.Add("total-count", filteredQuery.Count()); - } - if (metadata.MetaObject.HasValues) - return Task.FromResult((IMetadata)metadata); return Task.FromResult((IMetadata) null); } } diff --git a/README.md b/README.md index 855df218..1fb411ca 100644 --- a/README.md +++ b/README.md @@ -146,5 +146,6 @@ configuration.CustomBaseUrlService = new BaseUrlService(new Uri("https://api.exa ## Pagination ### total-pages / total-count +When using Entity Framework you can register type `EntityFrameworkQueryableResourceCollectionDocumentBuilder` to enable the `total-pages` and `total-count` meta properties. When pagination is used the `total-pages` and `total-count` meta properties are provided to indicate the number of pages and records to the client. From 5055a88c2a89c9c5ba62f4450608aea354aab59f Mon Sep 17 00:00:00 2001 From: Simon Hofer Date: Tue, 13 Sep 2016 08:19:33 +0200 Subject: [PATCH 3/3] awaits corrected --- ...tyFrameworkQueryableResourceCollectionDocumentBuilder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs b/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs index d630b0aa..1bd9e2c8 100644 --- a/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs +++ b/JSONAPI.EntityFramework/Documents/Builders/EntityFrameworkQueryableResourceCollectionDocumentBuilder.cs @@ -43,9 +43,9 @@ protected override async Task GetDocumentMetadata(IQueryable or var metadata = new Metadata(); if (paginationResult.PaginationWasApplied) { - var count = filteredQuery.CountAsync(cancellationToken); - metadata.MetaObject.Add("total-pages", (int)Math.Ceiling((decimal) await count / paginationResult.PageSize)); - metadata.MetaObject.Add("total-count", await count); + var count = await filteredQuery.CountAsync(cancellationToken); + metadata.MetaObject.Add("total-pages", (int)Math.Ceiling((decimal) count / paginationResult.PageSize)); + metadata.MetaObject.Add("total-count", count); } if (metadata.MetaObject.HasValues) return metadata;