From da9b7758e8406b2d99b8a0c6ab3f02708ed91f6a Mon Sep 17 00:00:00 2001 From: Tobias Kamenicky Date: Thu, 31 Oct 2019 15:38:41 +0100 Subject: [PATCH 1/5] DEL-2330 Support includeTotalCount parameter --- .../DeliveryOptionsBuilderTests.cs | 13 ++ .../DeliveryClientTests.cs | 7 +- .../Kentico.Kontent.Delivery.Tests.csproj | 1 + .../QueryParameters/IncludeTotalCountTests.cs | 119 ++++++++++++++++++ .../DeliveryOptions/DeliveryOptionsBuilder.cs | 9 +- .../IDeliveryOptionsBuilder.cs | 10 +- .../Configuration/DeliveryOptions .cs | 6 + Kentico.Kontent.Delivery/DeliveryClient.cs | 22 +++- Kentico.Kontent.Delivery/Models/Pagination.cs | 8 +- .../Parameters/IncludeTotalCountParameter.cs | 23 ++++ 10 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 Kentico.Kontent.Delivery.Tests/QueryParameters/IncludeTotalCountTests.cs create mode 100644 Kentico.Kontent.Delivery/QueryParameters/Parameters/IncludeTotalCountParameter.cs diff --git a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs index 8226593a..b1bc3142 100644 --- a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs +++ b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs @@ -109,6 +109,19 @@ public void BuildWithWaitForLoadingNewContent() Assert.True(deliveryOptions.WaitForLoadingNewContent); } + [Fact] + public void BuildWithIncludeTotalCount() + { + var deliveryOptions = DeliveryOptionsBuilder + .CreateInstance() + .WithProjectId(Guid.NewGuid()) + .UseProductionApi() + .IncludeTotalCount() + .Build(); + + Assert.True(deliveryOptions.IncludeTotalCount); + } + [Fact] public void BuildWithCustomEndpointForPreviewApi() { diff --git a/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs b/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs index 6792ee0f..40c2af03 100644 --- a/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs +++ b/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs @@ -412,10 +412,10 @@ public async void GetTaxonomiesAsync() public async void QueryParameters() { - string url = $"{_baseUrl}/items?elements.personas%5Ball%5D=barista%2Ccoffee%2Cblogger&elements.personas%5Bany%5D=barista%2Ccoffee%2Cblogger&system.sitemap_locations%5Bcontains%5D=cafes&elements.product_name=Hario%20V60&elements.price%5Bgt%5D=1000&elements.price%5Bgte%5D=50&system.type%5Bin%5D=cafe%2Ccoffee&elements.price%5Blt%5D=10&elements.price%5Blte%5D=4&elements.country%5Brange%5D=Guatemala%2CNicaragua&depth=2&elements=price%2Cproduct_name&limit=10&order=elements.price%5Bdesc%5D&skip=2&language=en"; + string url = $"{_baseUrl}/items?elements.personas%5Ball%5D=barista%2Ccoffee%2Cblogger&elements.personas%5Bany%5D=barista%2Ccoffee%2Cblogger&system.sitemap_locations%5Bcontains%5D=cafes&elements.product_name=Hario%20V60&elements.price%5Bgt%5D=1000&elements.price%5Bgte%5D=50&system.type%5Bin%5D=cafe%2Ccoffee&elements.price%5Blt%5D=10&elements.price%5Blte%5D=4&elements.country%5Brange%5D=Guatemala%2CNicaragua&depth=2&elements=price%2Cproduct_name&limit=10&order=elements.price%5Bdesc%5D&skip=2&language=en&includeTotalCount"; _mockHttp .When($"{url}") - .Respond("application/json", " { 'items': [],'modular_content': {},'pagination': {'skip': 2,'limit': 10,'count': 0,'next_page': ''}}"); + .Respond("application/json", " { 'items': [],'modular_content': {},'pagination': {'skip': 2,'limit': 10,'count': 0, 'total_count': 0, 'next_page': ''}}"); var client = InitializeDeliveryClientWithACustomTypeProvider(_mockHttp); @@ -436,7 +436,8 @@ public async void QueryParameters() new LimitParameter(10), new OrderParameter("elements.price", SortOrder.Descending), new SkipParameter(2), - new LanguageParameter("en") + new LanguageParameter("en"), + new IncludeTotalCountParameter() }; var response = await client.GetItemsAsync(parameters); diff --git a/Kentico.Kontent.Delivery.Tests/Kentico.Kontent.Delivery.Tests.csproj b/Kentico.Kontent.Delivery.Tests/Kentico.Kontent.Delivery.Tests.csproj index af8aa15b..0bc2f6e4 100644 --- a/Kentico.Kontent.Delivery.Tests/Kentico.Kontent.Delivery.Tests.csproj +++ b/Kentico.Kontent.Delivery.Tests/Kentico.Kontent.Delivery.Tests.csproj @@ -38,6 +38,7 @@ + diff --git a/Kentico.Kontent.Delivery.Tests/QueryParameters/IncludeTotalCountTests.cs b/Kentico.Kontent.Delivery.Tests/QueryParameters/IncludeTotalCountTests.cs new file mode 100644 index 00000000..a0606781 --- /dev/null +++ b/Kentico.Kontent.Delivery.Tests/QueryParameters/IncludeTotalCountTests.cs @@ -0,0 +1,119 @@ +using System; +using FakeItEasy; +using FluentAssertions; +using Kentico.Kontent.Delivery.Tests.Factories; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RichardSzalay.MockHttp; +using Xunit; + +namespace Kentico.Kontent.Delivery.Tests.QueryParameters +{ + public class IncludeTotalCountTests + { + private static readonly Guid ProjectId = Guid.NewGuid(); + private static readonly string BaseUrl = $"https://deliver.kontent.ai/{ProjectId}"; + private static readonly MockHttpMessageHandler MockHttp = new MockHttpMessageHandler(); + private static readonly DeliveryOptions Options = new DeliveryOptions + { + ProjectId = ProjectId.ToString(), + EnableRetryPolicy = false, + IncludeTotalCount = true + }; + + [Fact] + public void PaginationResponse_WithoutTotalCount_DeserializedCorrectly() + { + var responsePagination = JObject.FromObject(new + { + skip = 20, + limit = 10, + count = 8, + next_page = "nextPage" + }); + var expected = new Pagination(20, 10, 8, null, "nextPage"); + + var result = responsePagination.ToObject(); + + result.Should().BeEquivalentTo(expected); + } + + [Fact] + public void PaginationResponse_WithTotalCount_DeserializedCorrectly() + { + var responsePagination = JObject.FromObject(new + { + skip = 20, + limit = 10, + count = 8, + total_count = 28, + next_page = "nextPage" + }); + var expected = new Pagination(20, 10, 8, 28, "nextPage"); + + var result = responsePagination.ToObject(); + + result.Should().BeEquivalentTo(expected); + } + + [Fact] + public async void GetItemsJson_DeliveryOptionsWithIncludeTotalCount_IncludeTotalCountParameterAdded() + { + var responseJson = JsonConvert.SerializeObject(CreateItemsResponse()); + MockHttp + .Expect($"{BaseUrl}/items") + .WithExactQueryString("includeTotalCount") + .Respond("application/json", responseJson); + var client = DeliveryClientFactory.GetMockedDeliveryClientWithOptions(Options, MockHttp); + + await client.GetItemsJsonAsync(); + + MockHttp.VerifyNoOutstandingExpectation(); + } + + [Fact] + public async void GetItems_DeliveryOptionsWithIncludeTotalCount_IncludeTotalCountParameterAdded() + { + var responseJson = JsonConvert.SerializeObject(CreateItemsResponse()); + MockHttp + .Expect($"{BaseUrl}/items") + .WithExactQueryString("includeTotalCount") + .Respond("application/json", responseJson); + var client = DeliveryClientFactory.GetMockedDeliveryClientWithOptions(Options, MockHttp); + + await client.GetItemsAsync(); + + MockHttp.VerifyNoOutstandingExpectation(); + } + + [Fact] + public async void GetItemsTyped_DeliveryOptionsWithIncludeTotalCount_IncludeTotalCountParameterAdded() + { + var responseJson = JsonConvert.SerializeObject(CreateItemsResponse()); + MockHttp + .Expect($"{BaseUrl}/items") + .WithExactQueryString("system.type=cafe&includeTotalCount") + .Respond("application/json", responseJson); + var client = DeliveryClientFactory.GetMockedDeliveryClientWithOptions(Options, MockHttp); + A.CallTo(() => client.TypeProvider.GetCodename(typeof(Cafe))).Returns("cafe"); + + await client.GetItemsAsync(); + + MockHttp.VerifyNoOutstandingExpectation(); + } + + private static object CreateItemsResponse() => new + { + items = new object[0], + modular_content = new { }, + pagination = new + { + skip = 0, + limit = 0, + count = 1, + total_count = 1, + next_page = "" + } + }; + } +} \ No newline at end of file diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs index 36794240..d6fb633c 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs @@ -16,7 +16,7 @@ public class DeliveryOptionsBuilder : IDeliveryApiConfiguration, IDeliveryOption public static IDeliveryOptionsBuilder CreateInstance() => new DeliveryOptionsBuilder(); - private DeliveryOptionsBuilder() {} + private DeliveryOptionsBuilder() { } IDeliveryApiConfiguration IDeliveryOptionsBuilder.WithProjectId(string projectId) { @@ -41,6 +41,13 @@ IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.WaitForLoadingNewC return this; } + IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.IncludeTotalCount() + { + _deliveryOptions.IncludeTotalCount = true; + + return this; + } + IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.DisableRetryPolicy() { _deliveryOptions.EnableRetryPolicy = false; diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs index 05aff150..daeae3a5 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs @@ -59,7 +59,15 @@ public interface IOptionalDeliveryConfiguration : IDeliveryOptionsBuild /// However, the request might take longer than usual to complete. /// IOptionalDeliveryConfiguration WaitForLoadingNewContent(); - + + /// + /// Provide information on how many items are there in total for a query to items endpoint. + /// This can be used to determine total number of pages that can be retrieved. + /// We don't recommend to enable this setting for all requests as this might increase response time. + /// + /// + IOptionalDeliveryConfiguration IncludeTotalCount(); + /// /// Change configuration of the default retry policy. /// diff --git a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs index 14c7cf3d..25f2c6ce 100644 --- a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs +++ b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs @@ -61,5 +61,11 @@ public class DeliveryOptions /// Gets or sets configuration of the default retry policy. /// public DefaultRetryPolicyOptions DefaultRetryPolicyOptions { get; set; } = new DefaultRetryPolicyOptions(); + + /// + /// Gets or sets a value that determines if the client provides total count for each query to items. + /// This can also be enabled on per request basis by query parameter . + /// + public bool IncludeTotalCount { get; set; } } } diff --git a/Kentico.Kontent.Delivery/DeliveryClient.cs b/Kentico.Kontent.Delivery/DeliveryClient.cs index 87e7bb76..ecf8d61c 100644 --- a/Kentico.Kontent.Delivery/DeliveryClient.cs +++ b/Kentico.Kontent.Delivery/DeliveryClient.cs @@ -93,7 +93,13 @@ public async Task GetItemJsonAsync(string codename, params string[] par /// The instance that represents the content items. If no query parameters are specified, all content items are returned. public async Task GetItemsJsonAsync(params string[] parameters) { - var endpointUrl = UrlBuilder.GetItemsUrl(parameters); + var parameterList = parameters?.ToList() ?? new List(); + if (DeliveryOptions.IncludeTotalCount && !parameterList.Contains(new IncludeTotalCountParameter().GetQueryStringParameter())) + { + parameterList.Add(new IncludeTotalCountParameter().GetQueryStringParameter()); + } + + var endpointUrl = UrlBuilder.GetItemsUrl(parameterList.ToArray()); return (await GetDeliverResponseAsync(endpointUrl)).Content; } @@ -182,7 +188,13 @@ public async Task GetItemsAsync(params IQueryParame /// The instance that contains the content items. If no query parameters are specified, all content items are returned. public async Task GetItemsAsync(IEnumerable parameters) { - var endpointUrl = UrlBuilder.GetItemsUrl(parameters); + var parameterList = parameters?.ToList() ?? new List(); + if (DeliveryOptions.IncludeTotalCount && !parameterList.Any(x => x is IncludeTotalCountParameter)) + { + parameterList.Add(new IncludeTotalCountParameter()); + } + + var endpointUrl = UrlBuilder.GetItemsUrl(parameterList); var response = await GetDeliverResponseAsync(endpointUrl); return new DeliveryItemListingResponse(response, ModelProvider, ContentLinkUrlResolver); @@ -207,7 +219,11 @@ public async Task> GetItemsAsync(params IQuery /// The instance that contains the content items. If no query parameters are specified, all content items are returned. public async Task> GetItemsAsync(IEnumerable parameters) { - var enhancedParameters = ExtractParameters(parameters); + var enhancedParameters = ExtractParameters(parameters).ToList(); + if (DeliveryOptions.IncludeTotalCount && !enhancedParameters.Any(x => x is IncludeTotalCountParameter)) + { + enhancedParameters.Add(new IncludeTotalCountParameter()); + } var endpointUrl = UrlBuilder.GetItemsUrl(enhancedParameters); var response = await GetDeliverResponseAsync(endpointUrl); diff --git a/Kentico.Kontent.Delivery/Models/Pagination.cs b/Kentico.Kontent.Delivery/Models/Pagination.cs index f26b5e58..cdca964c 100644 --- a/Kentico.Kontent.Delivery/Models/Pagination.cs +++ b/Kentico.Kontent.Delivery/Models/Pagination.cs @@ -22,6 +22,11 @@ public sealed class Pagination /// public int Count { get; } + /// + /// Gets the total number of items for query. + /// + public int? TotalCount { get; } + /// /// Gets the URL of the next page. /// @@ -32,11 +37,12 @@ public sealed class Pagination /// Initializes a new instance of the class with information from a response. /// [JsonConstructor] - internal Pagination(int skip, int limit, int count, string next_page) + internal Pagination(int skip, int limit, int count, int? total_count, string next_page) { Skip = skip; Limit = limit; Count = count; + TotalCount = total_count; NextPageUrl = next_page; } } diff --git a/Kentico.Kontent.Delivery/QueryParameters/Parameters/IncludeTotalCountParameter.cs b/Kentico.Kontent.Delivery/QueryParameters/Parameters/IncludeTotalCountParameter.cs new file mode 100644 index 00000000..efaefd59 --- /dev/null +++ b/Kentico.Kontent.Delivery/QueryParameters/Parameters/IncludeTotalCountParameter.cs @@ -0,0 +1,23 @@ +namespace Kentico.Kontent.Delivery +{ + /// + /// Specifies whether to include total count in the paging section. + /// + public sealed class IncludeTotalCountParameter : IQueryParameter + { + /// + /// Initializes a new instance of the class. + /// + public IncludeTotalCountParameter() + { + } + + /// + /// Returns the query string representation of the query parameter. + /// + public string GetQueryStringParameter() + { + return "includeTotalCount"; + } + } +} From fb5b00ff15712289549fa6e71d9c352949b15bd9 Mon Sep 17 00:00:00 2001 From: Tobias Kamenicky Date: Tue, 12 Nov 2019 13:21:54 +0100 Subject: [PATCH 2/5] DEL-2330 Update documentation & refactor url building --- .../IDeliveryOptionsBuilder.cs | 9 +++--- .../Configuration/DeliveryOptions .cs | 4 +-- Kentico.Kontent.Delivery/DeliveryClient.cs | 20 ++----------- .../DeliveryEndpointUrlBuilder.cs | 28 +++++++++++++++++-- Kentico.Kontent.Delivery/Models/Pagination.cs | 2 +- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs index daeae3a5..577e3ae3 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs @@ -59,13 +59,12 @@ public interface IOptionalDeliveryConfiguration : IDeliveryOptionsBuild /// However, the request might take longer than usual to complete. /// IOptionalDeliveryConfiguration WaitForLoadingNewContent(); - + /// - /// Provide information on how many items are there in total for a query to items endpoint. - /// This can be used to determine total number of pages that can be retrieved. - /// We don't recommend to enable this setting for all requests as this might increase response time. + /// Include the total number of items matching the search criteria in the response. + /// This behavior can also be enabled for individual requests with the . + /// Please note that using this option might increase the response time. /// - /// IOptionalDeliveryConfiguration IncludeTotalCount(); /// diff --git a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs index 25f2c6ce..794c62b9 100644 --- a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs +++ b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs @@ -63,8 +63,8 @@ public class DeliveryOptions public DefaultRetryPolicyOptions DefaultRetryPolicyOptions { get; set; } = new DefaultRetryPolicyOptions(); /// - /// Gets or sets a value that determines if the client provides total count for each query to items. - /// This can also be enabled on per request basis by query parameter . + /// Gets or sets a value that determines if the client includes the total number of items matching the search criteria in response. + /// This behavior can also be enabled for individual requests with the . /// public bool IncludeTotalCount { get; set; } } diff --git a/Kentico.Kontent.Delivery/DeliveryClient.cs b/Kentico.Kontent.Delivery/DeliveryClient.cs index ecf8d61c..a195f2d6 100644 --- a/Kentico.Kontent.Delivery/DeliveryClient.cs +++ b/Kentico.Kontent.Delivery/DeliveryClient.cs @@ -93,13 +93,7 @@ public async Task GetItemJsonAsync(string codename, params string[] par /// The instance that represents the content items. If no query parameters are specified, all content items are returned. public async Task GetItemsJsonAsync(params string[] parameters) { - var parameterList = parameters?.ToList() ?? new List(); - if (DeliveryOptions.IncludeTotalCount && !parameterList.Contains(new IncludeTotalCountParameter().GetQueryStringParameter())) - { - parameterList.Add(new IncludeTotalCountParameter().GetQueryStringParameter()); - } - - var endpointUrl = UrlBuilder.GetItemsUrl(parameterList.ToArray()); + var endpointUrl = UrlBuilder.GetItemsUrl(parameters); return (await GetDeliverResponseAsync(endpointUrl)).Content; } @@ -188,13 +182,7 @@ public async Task GetItemsAsync(params IQueryParame /// The instance that contains the content items. If no query parameters are specified, all content items are returned. public async Task GetItemsAsync(IEnumerable parameters) { - var parameterList = parameters?.ToList() ?? new List(); - if (DeliveryOptions.IncludeTotalCount && !parameterList.Any(x => x is IncludeTotalCountParameter)) - { - parameterList.Add(new IncludeTotalCountParameter()); - } - - var endpointUrl = UrlBuilder.GetItemsUrl(parameterList); + var endpointUrl = UrlBuilder.GetItemsUrl(parameters); var response = await GetDeliverResponseAsync(endpointUrl); return new DeliveryItemListingResponse(response, ModelProvider, ContentLinkUrlResolver); @@ -220,10 +208,6 @@ public async Task> GetItemsAsync(params IQuery public async Task> GetItemsAsync(IEnumerable parameters) { var enhancedParameters = ExtractParameters(parameters).ToList(); - if (DeliveryOptions.IncludeTotalCount && !enhancedParameters.Any(x => x is IncludeTotalCountParameter)) - { - enhancedParameters.Add(new IncludeTotalCountParameter()); - } var endpointUrl = UrlBuilder.GetItemsUrl(enhancedParameters); var response = await GetDeliverResponseAsync(endpointUrl); diff --git a/Kentico.Kontent.Delivery/DeliveryEndpointUrlBuilder.cs b/Kentico.Kontent.Delivery/DeliveryEndpointUrlBuilder.cs index 42b2ae96..1429258e 100644 --- a/Kentico.Kontent.Delivery/DeliveryEndpointUrlBuilder.cs +++ b/Kentico.Kontent.Delivery/DeliveryEndpointUrlBuilder.cs @@ -35,12 +35,14 @@ public string GetItemUrl(string codename, IEnumerable parameter public string GetItemsUrl(string[] parameters) { - return GetUrl(UrlTemplateItems, parameters); + var enrichedParameters = EnrichParameters(parameters).ToArray(); + return GetUrl(UrlTemplateItems, enrichedParameters); } public string GetItemsUrl(IEnumerable parameters) { - return GetUrl(UrlTemplateItems, parameters); + var updatedParameters = EnrichParameters(parameters); + return GetUrl(UrlTemplateItems, updatedParameters); } public string GetItemsFeedUrl(string[] parameters) @@ -138,5 +140,27 @@ private string AssembleHost() var hostUrl = string.Format(endpointUrlTemplate, projectId); return hostUrl; } + + private IEnumerable EnrichParameters(IEnumerable parameters) + { + var parameterList = parameters?.ToList() ?? new List(); + if (_deliveryOptions.IncludeTotalCount && !parameterList.Contains(new IncludeTotalCountParameter().GetQueryStringParameter())) + { + parameterList.Add(new IncludeTotalCountParameter().GetQueryStringParameter()); + } + + return parameterList; + } + + private IEnumerable EnrichParameters(IEnumerable parameters) + { + var parameterList = parameters?.ToList() ?? new List(); + if (_deliveryOptions.IncludeTotalCount && !parameterList.Any(x => x is IncludeTotalCountParameter)) + { + parameterList.Add(new IncludeTotalCountParameter()); + } + + return parameterList; + } } } diff --git a/Kentico.Kontent.Delivery/Models/Pagination.cs b/Kentico.Kontent.Delivery/Models/Pagination.cs index cdca964c..ae05257a 100644 --- a/Kentico.Kontent.Delivery/Models/Pagination.cs +++ b/Kentico.Kontent.Delivery/Models/Pagination.cs @@ -23,7 +23,7 @@ public sealed class Pagination public int Count { get; } /// - /// Gets the total number of items for query. + /// Gets the total number of items matching the search criteria. /// public int? TotalCount { get; } From 60b346b5a0544cb22932109704c714e02e900124 Mon Sep 17 00:00:00 2001 From: Tobias Kamenicky Date: Tue, 12 Nov 2019 14:32:32 +0100 Subject: [PATCH 3/5] DEL-2330 Rename method to clarify its purpose --- .../QueryParameters/ContentTypeExtractorTests.cs | 10 +++++----- Kentico.Kontent.Delivery/DeliveryClient.cs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Kentico.Kontent.Delivery.Tests/QueryParameters/ContentTypeExtractorTests.cs b/Kentico.Kontent.Delivery.Tests/QueryParameters/ContentTypeExtractorTests.cs index b7514b2b..6e41f916 100644 --- a/Kentico.Kontent.Delivery.Tests/QueryParameters/ContentTypeExtractorTests.cs +++ b/Kentico.Kontent.Delivery.Tests/QueryParameters/ContentTypeExtractorTests.cs @@ -49,7 +49,7 @@ public void ExtractParameters_WhenGivenTypeWithCodenameAndExistingParams_AddsCod { var existingParams = new List() { new SkipParameter(15) }; - var enhancedParams = new List(_client.ExtractParameters(existingParams)); + var enhancedParams = new List(_client.EnsureContentTypeFilter(existingParams)); Assert.Equal(2, enhancedParams.Count); Assert.True(enhancedParams.Find(x => x.GetQueryStringParameter() == $"system.type={CONTENT_TYPE_CODENAME}") != null); @@ -58,7 +58,7 @@ public void ExtractParameters_WhenGivenTypeWithCodenameAndExistingParams_AddsCod [Fact] public void ExtractParameters_WhenGivenTypeWithCodename_CreatesNewParams() { - var enhancedParams = new List(_client.ExtractParameters()); + var enhancedParams = new List(_client.EnsureContentTypeFilter()); Assert.Single(enhancedParams); Assert.True(enhancedParams.Find(x => x.GetQueryStringParameter() == $"system.type={CONTENT_TYPE_CODENAME}") != null); @@ -67,7 +67,7 @@ public void ExtractParameters_WhenGivenTypeWithCodename_CreatesNewParams() [Fact] public void ExtractParameters_WhenGivenTypeWithoutCodenameNoParams_CreatesEmptyParams() { - var enhancedParams = new List(_client.ExtractParameters()); + var enhancedParams = new List(_client.EnsureContentTypeFilter()); Assert.Empty(enhancedParams); } @@ -77,7 +77,7 @@ public void ExtractParameters_WhenGivenTypeWithoutCodenameAndParams_ReturnsParam { var existingParams = new List() { new SkipParameter(15) }; - var enhancedParams = new List(_client.ExtractParameters(existingParams)); + var enhancedParams = new List(_client.EnsureContentTypeFilter(existingParams)); Assert.Single(enhancedParams); Assert.True(enhancedParams.Find(x => x.GetQueryStringParameter() == $"system.type=TypeWithoutContentTypeCodename") == null); @@ -88,7 +88,7 @@ public void ExtractParameters_WhenGivenTypeWithCodenameAndExistingTypeParameter_ { var existingParams = new List() { new EqualsFilter("system.type", CONTENT_TYPE_CODENAME) }; - var enhancedParams = new List(_client.ExtractParameters(existingParams)); + var enhancedParams = new List(_client.EnsureContentTypeFilter(existingParams)); Assert.Single(enhancedParams); Assert.True(enhancedParams.Find(x => x.GetQueryStringParameter() == $"system.type={CONTENT_TYPE_CODENAME}") != null); diff --git a/Kentico.Kontent.Delivery/DeliveryClient.cs b/Kentico.Kontent.Delivery/DeliveryClient.cs index a195f2d6..d588781c 100644 --- a/Kentico.Kontent.Delivery/DeliveryClient.cs +++ b/Kentico.Kontent.Delivery/DeliveryClient.cs @@ -207,7 +207,7 @@ public async Task> GetItemsAsync(params IQuery /// The instance that contains the content items. If no query parameters are specified, all content items are returned. public async Task> GetItemsAsync(IEnumerable parameters) { - var enhancedParameters = ExtractParameters(parameters).ToList(); + var enhancedParameters = EnsureContentTypeFilter(parameters).ToList(); var endpointUrl = UrlBuilder.GetItemsUrl(enhancedParameters); var response = await GetDeliverResponseAsync(endpointUrl); @@ -261,7 +261,7 @@ public IDeliveryItemsFeed GetItemsFeed(params IQueryParameter[] parameters /// The instance that can be used to enumerate through content items. If no query parameters are specified, all content items are enumerated. public IDeliveryItemsFeed GetItemsFeed(IEnumerable parameters) { - var enhancedParameters = ExtractParameters(parameters).ToList(); + var enhancedParameters = EnsureContentTypeFilter(parameters).ToList(); ValidateItemsFeedParameters(enhancedParameters); var endpointUrl = UrlBuilder.GetItemsFeedUrl(enhancedParameters); return new DeliveryItemsFeed(GetItemsBatchAsync); @@ -555,7 +555,7 @@ private bool HasStaleContent(HttpResponseMessage httpResponseMessage) return httpResponseMessage.Headers.TryGetValues("X-Stale-Content", out var values) && values.Contains("1", StringComparer.Ordinal); } - internal IEnumerable ExtractParameters(IEnumerable parameters = null) + internal IEnumerable EnsureContentTypeFilter(IEnumerable parameters = null) { var enhancedParameters = parameters != null ? new List(parameters) From 7ee317c1125da54b784a9690ce76e61daaabe214 Mon Sep 17 00:00:00 2001 From: Tobias Kamenicky Date: Tue, 12 Nov 2019 15:14:19 +0100 Subject: [PATCH 4/5] DEL-2330 Add README section for pagination --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 2b4ccaba..a21b2a74 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,21 @@ DeliveryItemListingResponse response = await client.GetItemsAsync( ); ``` +### Pagination + +If you need to build a paging navigation for your items, you might need to retrieve the total number of items matching the search criteria. This can be achieved by adding `IncludeTotalCountParameter` to the request parameters. With the parameter included the `Pagination` section of the multiple content items response will contain `TotalCount` property. The parameter can also be configured globally by calling method `IncludeTotalCount()` on `IDeliveryOptionsBuilder`. This results in adding `IncludeTotalCountParameter` automatically to each request. + +```csharp +// Retrieves the second page of items including total number of items matching the search criteria +DeliveryItemListingResponse response = await client.GetItemsAsync( + new LanguageParameter("es-ES"), + new EqualsFilter("system.type", "brewer"), + new OrderParameter("elements.product_name"), + new SkipParameter(5), + new LimitParameter(5), + new IncludeTotalCountParameter(), +``` + ### Strongly-typed responses The `IDeliveryClient` also supports retrieving of strongly-typed models. From f24315862a692357bd293c2a286705b0eaffc9da Mon Sep 17 00:00:00 2001 From: Tobias Kamenicky Date: Tue, 12 Nov 2019 15:45:08 +0100 Subject: [PATCH 5/5] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Aleš Kalina --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a21b2a74..806a2bee 100644 --- a/README.md +++ b/README.md @@ -104,9 +104,9 @@ DeliveryItemListingResponse response = await client.GetItemsAsync( ); ``` -### Pagination +### Paging navigation -If you need to build a paging navigation for your items, you might need to retrieve the total number of items matching the search criteria. This can be achieved by adding `IncludeTotalCountParameter` to the request parameters. With the parameter included the `Pagination` section of the multiple content items response will contain `TotalCount` property. The parameter can also be configured globally by calling method `IncludeTotalCount()` on `IDeliveryOptionsBuilder`. This results in adding `IncludeTotalCountParameter` automatically to each request. +To display a paging navigation you need to retrieve the total number of items matching the search criteria. This can be achieved by adding the `IncludeTotalCountParameter` to the request parameters. With this parameter the item listing responses will contain the total number of items in the `Pagination.TotalCount` property. This behavior can also be enabled globally by calling the `IDeliveryOptionsBuilder.IncludeTotalCount` method. Please note that response times might increase slightly. ```csharp // Retrieves the second page of items including total number of items matching the search criteria