Skip to content

Commit c2670c7

Browse files
authored
Merge pull request #327 from justeat/develop
develop -> master ([RED-2026])
2 parents b0f5735 + c8c2a14 commit c2670c7

24 files changed

+450
-13
lines changed

README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A .netstandard NuGet package for use with the Zendesk v2 API.
1111

1212
#### The deprecation and replacement of Status API endpoints
1313

14-
More detailed information on the exact changes and motivation can be found [here](https://support.zendesk.com/hc/en-us/articles/5414949730842).
14+
More detailed information on the exact changes and motivation can be found [here](https://support.zendesk.com/hc/en-us/articles/5414949730842).
1515

1616
For the sake of this library, it means the following methods have been removed:
1717

@@ -50,6 +50,7 @@ Groups:
5050
Help Center:
5151
- GET api/v2/help_center/articles
5252
- GET api/v2/help_center/categories
53+
- GET api/v2/help_center/sections
5354

5455
Organization:
5556
- GET /api/v2/organization_fields
@@ -63,11 +64,19 @@ Tickets:
6364
- GET /api/v2/tickets
6465
- GET /api/v2/tickets/{ticketId}/comments
6566
- GET /api/v2/ticket_fields
66-
- GET /api/v2/ticket_audits - [Cursor Variant](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket_audits/#pagination)
67+
- GET /api/v2/ticket_audits
68+
- GET
6769

6870
Satisfaction ratings:
6971
- GET /api/v2/satisfaction_ratings
7072

73+
Requests
74+
- GET /api/v2/requests
75+
- GET /api/v2/requests/{requestId}/comments
76+
77+
Job Statuses
78+
- GET /api/v2/job_statuses
79+
7180
[Further reading on Zendesk Pagination changes](https://support.zendesk.com/hc/en-us/articles/4402610093338-Introducing-Pagination-Changes-Zendesk-API)
7281

7382
## 3.x.x
@@ -126,6 +135,43 @@ await client.Search.SearchAsync<Ticket>(q =>
126135
);
127136
```
128137

138+
## Using Cursor Based Pagination
139+
You can use the `CursorPaginatedIterator` to loop through multiple pages as shown below:
140+
```c#
141+
142+
var services = new ServiceCollection();
143+
services.AddZendeskClientWithHttpClientFactory("https://yoursubomain.zendesk.com", "your@email.com", "your_token_");
144+
var serviceProvider = services.BuildServiceProvider();
145+
var client = serviceProvider.GetRequiredService<IZendeskClient>();
146+
147+
var ticketCursorResponse = await client.Tickets.GetAllAsync(new CursorPager { Size = 5 }); // low page number to force pagination
148+
149+
var iteratorFactory = serviceProvider.GetRequiredService<ICursorPaginatedIteratorFactory>();
150+
// creates the iterator with the response object of the first request
151+
var iterator = iteratorFactory.Create<Ticket>(ticketCursorResponse);
152+
153+
foreach (var ticket in iterator)
154+
{
155+
Console.WriteLine("the id of this ticket is:" + ticket.Id);
156+
} // this loop will stop at the first page
157+
158+
while (iterator.HasMore()) // to loop through all pages
159+
{
160+
await iterator.NextPage();
161+
foreach (var ticket in iterator)
162+
{
163+
Console.WriteLine("the id of this ticket is:" + ticket.Id);
164+
}
165+
}
166+
167+
// alternatively you can use .All() from the iterator
168+
await foreach (var ticket in iterator.All())
169+
{
170+
Console.WriteLine("the id of this ticket is:" + ticket.Id);
171+
}
172+
173+
```
174+
129175
## The Zendesk API
130176

131177
The zendesk api documentation is available at http://developer.zendesk.com/documentation/rest_api/introduction.html

src/ZendeskApi.Build/ZendeskApi.Commons.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<PropertyGroup>
2424
<Major>7</Major>
2525
<Minor>0</Minor>
26-
<Revision>6</Revision>
26+
<Revision>7</Revision>
2727
<PackageVersion>$(Major).$(Minor).$(Revision)</PackageVersion>
2828
</PropertyGroup>
2929
<ItemGroup>

src/ZendeskApi.Client/Extensions/ServiceCollectionExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Net.Http;
33
using Microsoft.Extensions.DependencyInjection;
4+
using ZendeskApi.Client.Models;
45
using ZendeskApi.Client.Options;
6+
using ZendeskApi.Client.Pagination;
57
#pragma warning disable 618
68

79
namespace ZendeskApi.Client.Extensions
@@ -33,6 +35,7 @@ public static IServiceCollection AddZendeskClientWithHttpClientFactory(this ISer
3335
{
3436
services.AddScoped<IZendeskClient, ZendeskClient>();
3537
services.AddScoped<IZendeskApiClient, ZendeskApiClientFactory>();
38+
services.AddScoped<ICursorPaginatedIteratorFactory, CursorPaginatedIteratorFactory>();
3639

3740
services.AddHttpClient("zendeskApiClient", c =>
3841
{

src/ZendeskApi.Client/IZendeskClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ public interface IZendeskClient
2929
ILocaleResource Locales { get; }
3030
ITagsResource Tags { get; }
3131
}
32-
}
32+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Threading.Tasks;
5+
using Newtonsoft.Json;
6+
using ZendeskApi.Client.Responses;
7+
8+
namespace ZendeskApi.Client.Pagination;
9+
public class CursorPaginatedIterator<T> : IEnumerable<T>
10+
{
11+
12+
public ICursorPagination<T> Response { get; set; }
13+
14+
private IZendeskApiClient client;
15+
16+
17+
private string ResponseType { get; }
18+
19+
public CursorPaginatedIterator(ICursorPagination<T> response, IZendeskApiClient client)
20+
{
21+
Response = response;
22+
this.client = client;
23+
ResponseType = response.GetType().FullName;
24+
}
25+
26+
public bool HasMore() => Response.Meta.HasMore;
27+
28+
public IEnumerator<T> GetEnumerator()
29+
{
30+
return Response.GetEnumerator();
31+
}
32+
33+
IEnumerator IEnumerable.GetEnumerator()
34+
{
35+
return Response.GetEnumerator();
36+
}
37+
38+
39+
public async Task NextPage()
40+
{
41+
await ExecuteRequest(Response.Links.Next);
42+
}
43+
44+
public async Task PrevPage()
45+
{
46+
await ExecuteRequest(Response.Links.Prev);
47+
}
48+
49+
public async IAsyncEnumerable<T> All()
50+
{
51+
foreach (var item in Response)
52+
{
53+
yield return item;
54+
}
55+
while (HasMore())
56+
{
57+
await NextPage();
58+
foreach (var item in Response)
59+
{
60+
yield return item;
61+
}
62+
}
63+
yield break;
64+
}
65+
66+
private async Task ExecuteRequest(string requestUrl)
67+
{
68+
var httpResponseMessage = await client.CreateClient().GetAsync(requestUrl);
69+
var responseBody = await httpResponseMessage.Content.ReadAsStringAsync();
70+
Response = (ICursorPagination<T>)JsonConvert.DeserializeObject(responseBody, Type.GetType(ResponseType));
71+
}
72+
73+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using ZendeskApi.Client.Responses;
2+
3+
namespace ZendeskApi.Client.Pagination
4+
{
5+
public interface ICursorPaginatedIteratorFactory
6+
{
7+
CursorPaginatedIterator<T> Create<T>(ICursorPagination<T> response);
8+
}
9+
10+
public class CursorPaginatedIteratorFactory : ICursorPaginatedIteratorFactory
11+
{
12+
private readonly IZendeskApiClient zendeskApiClient;
13+
14+
public CursorPaginatedIteratorFactory(IZendeskApiClient _zendeskApiClient)
15+
{
16+
zendeskApiClient = _zendeskApiClient;
17+
}
18+
19+
public CursorPaginatedIterator<T> Create<T>(ICursorPagination<T> response)
20+
{
21+
return new CursorPaginatedIterator<T>(response, zendeskApiClient);
22+
}
23+
}
24+
}
25+

src/ZendeskApi.Client/Resources/Interfaces/IJobStatusResource.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@ public interface IJobStatusResource
1313
/// <summary>
1414
/// Shows the current statuses for background jobs running.
1515
/// </summary>
16-
[Obsolete("Use `GetAllAsync` instead.")]
16+
[Obsolete("Use `GetAllAsync` with CursorPager instead.")]
1717
Task<IPagination<JobStatusResponse>> ListAsync(
1818
PagerParameters pagerParameters = null,
1919
CancellationToken cancellationToken = default(CancellationToken));
2020

2121
/// <summary>
2222
/// Shows the current statuses for background jobs running.
2323
/// </summary>
24+
[Obsolete("Use `GetAllAsync` with CursorPager instead.")]
2425
Task<IPagination<JobStatusResponse>> GetAllAsync(
2526
PagerParameters pagerParameters = null,
2627
CancellationToken cancellationToken = default(CancellationToken));
2728

29+
Task<ICursorPagination<JobStatusResponse>> GetAllAsync(
30+
CursorPager pagerParameters = null,
31+
CancellationToken cancellationToken = default(CancellationToken));
2832
#endregion
2933

3034
#region Show

src/ZendeskApi.Client/Resources/Interfaces/IRequestsResource.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ Task<IPagination<Request>> GetAllAsync(
1414
PagerParameters pager = null,
1515
CancellationToken cancellationToken = default);
1616

17+
Task<ICursorPagination<Request>> GetAllAsync(
18+
CursorPager pager,
19+
CancellationToken cancellationToken = default);
20+
1721
Task<Request> GetAsync(
1822
long requestId,
1923
CancellationToken cancellationToken = default);
@@ -29,6 +33,11 @@ Task<IPagination<TicketComment>> GetAllComments(
2933
PagerParameters pager = null,
3034
CancellationToken cancellationToken = default);
3135

36+
Task<ICursorPagination<TicketComment>> GetAllComments(
37+
long requestId,
38+
CursorPager pager,
39+
CancellationToken cancellationToken = default);
40+
3241
Task<TicketComment> GetTicketCommentAsync(
3342
long requestId,
3443
long commentId,

src/ZendeskApi.Client/Resources/Interfaces/Ticket/ITicketAuditResource.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace ZendeskApi.Client.Resources
88
public interface ITicketAuditResource
99
{
1010
Task<TicketAuditResponse> GetAllAsync(CursorPagerVariant pager = null, CancellationToken cancellationToken = default);
11+
Task<TicketAuditCursorResponse> GetAllAsync(CursorPager pager, CancellationToken cancellationToken = default);
1112
Task<TicketAuditResponse> GetAllByTicketAsync(long ticketId, CancellationToken cancellationToken = default);
1213
Task<SingleTicketAuditResponse> Get(int ticketId, int auditId, CancellationToken cancellationToken = default);
1314
}

src/ZendeskApi.Client/Resources/JobStatusResource.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public JobStatusResource(
1919
: base(apiClient, logger, "job_statuses")
2020
{ }
2121

22-
[Obsolete("Use `GetAllAsync` instead.")]
22+
[Obsolete("Use `GetAllAsync` with CursorPager instead.")]
2323
public async Task<IPagination<JobStatusResponse>> ListAsync(
2424
PagerParameters pagerParameters = null,
2525
CancellationToken cancellationToken = default(CancellationToken))
@@ -29,6 +29,18 @@ public async Task<IPagination<JobStatusResponse>> ListAsync(
2929
cancellationToken);
3030
}
3131

32+
public async Task<ICursorPagination<JobStatusResponse>> GetAllAsync(CursorPager pagerParameters, CancellationToken cancellationToken = default)
33+
{
34+
return await GetAsync<JobStatusListCursorResponse>(
35+
ResourceUri,
36+
"list-job-statuses",
37+
"ListAsync",
38+
pagerParameters,
39+
null,
40+
cancellationToken: cancellationToken);
41+
}
42+
43+
[Obsolete("Use `GetAllAsync` with CursorPager instead.")]
3244
public async Task<IPagination<JobStatusResponse>> GetAllAsync(
3345
PagerParameters pagerParameters = null,
3446
CancellationToken cancellationToken = default(CancellationToken))

0 commit comments

Comments
 (0)