diff --git a/src/ZendeskApi_v2/Core.cs b/src/ZendeskApi_v2/Core.cs index 93baeec9..58c9cce5 100644 --- a/src/ZendeskApi_v2/Core.cs +++ b/src/ZendeskApi_v2/Core.cs @@ -13,6 +13,7 @@ using Newtonsoft.Json; using ZendeskApi_v2.Extensions; using ZendeskApi_v2.Models.Shared; +using System.Collections.Specialized; namespace ZendeskApi_v2 { @@ -28,14 +29,14 @@ public interface ICore { #if SYNC T GetByPageUrl(string pageUrl, int perPage = 100); - T RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null); - RequestResult RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null); + T RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null); + RequestResult RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null); #endif #if ASYNC Task GetByPageUrlAsync(string pageUrl, int perPage = 100); - Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null); - Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null); + Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null); + Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null); #endif } @@ -116,14 +117,14 @@ public T GetByPageUrl(string pageUrl, int perPage = 100) return RunRequest(resource, RequestMethod.Get); } - public T RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null) + public T RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null) { - var response = RunRequest(resource, requestMethod, body, timeout, formParameters); + var response = RunRequest(resource, requestMethod, body, timeout, formParameters, headers); var obj = JsonConvert.DeserializeObject(response.Content, jsonSettings); return obj; } - public RequestResult RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null) + public RequestResult RunRequest(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null) { try { @@ -137,6 +138,11 @@ public RequestResult RunRequest(string resource, string requestMethod, object bo } req.Headers["Authorization"] = GetPasswordOrTokenAuthHeader(); + if (headers != null) + { + req.Headers.Add(headers); + } + req.PreAuthenticate = true; AddCustomHeaders(req); @@ -297,9 +303,9 @@ protected T GenericDelete(string resource) return res; } - protected T GenericPost(string resource, object body = null) + protected T GenericPost(string resource, object body = null, NameValueCollection headers = null) { - var res = RunRequest(resource, RequestMethod.Post, body); + var res = RunRequest(resource, RequestMethod.Post, body, headers: headers); return res; } @@ -373,14 +379,14 @@ public async Task GetByPageUrlAsync(string pageUrl, int perPage = 100) return await RunRequestAsync(resource, RequestMethod.Get); } - public async Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null) + public async Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null) { var response = await RunRequestAsync(resource, requestMethod, body, timeout, formParameters); var obj = Task.Factory.StartNew(() => JsonConvert.DeserializeObject(response.Content, jsonSettings)); return await obj; } - public async Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null) + public async Task RunRequestAsync(string resource, string requestMethod, object body = null, int? timeout = null, Dictionary formParameters = null, NameValueCollection headers = null) { var requestUrl = ZendeskUrl + resource; try @@ -389,6 +395,11 @@ public async Task RunRequestAsync(string resource, string request req.ContentType = "application/json"; req.Headers["Authorization"] = GetPasswordOrTokenAuthHeader(); + if (headers != null) + { + req.Headers.Add(headers); + } + req.Method = requestMethod; //GET POST PUT DELETE req.Accept = "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml"; AddCustomHeaders(req); @@ -546,9 +557,9 @@ protected async Task GenericDeleteAsync(string resource) return await res; } - protected async Task GenericPostAsync(string resource, object body = null) + protected async Task GenericPostAsync(string resource, object body = null, NameValueCollection headers = null) { - return await RunRequestAsync(resource, RequestMethod.Post, body); + return await RunRequestAsync(resource, RequestMethod.Post, body, headers: headers); } protected async Task GenericPostFormAsync(string resource, object body = null, Dictionary formParameters = null) diff --git a/src/ZendeskApi_v2/Requests/Tickets.cs b/src/ZendeskApi_v2/Requests/Tickets.cs index 7c761c79..63d7d14c 100644 --- a/src/ZendeskApi_v2/Requests/Tickets.cs +++ b/src/ZendeskApi_v2/Requests/Tickets.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Net; #if ASYNC @@ -77,7 +78,16 @@ public interface ITickets : ICore GroupTicketResponse GetMultipleTickets(IEnumerable ids, TicketSideLoadOptionsEnum sideLoadOptions = TicketSideLoadOptionsEnum.None); - IndividualTicketResponse CreateTicket(Ticket ticket); + /// + /// Creates a ticket. + /// If a idempotency-key is provided and the same request using the same body and idempotency key is repeated, another ticket is not created. + /// Instead, you'll get the same response as before that is cached under the idempotency key + /// + /// + /// The Ticketing API lets you specify an idempotency key that allows you to retry a ticket creation request without the + /// risk of creating duplicate records. + /// + IndividualTicketResponse CreateTicket(Ticket ticket, string idempotencyKey = null); JobStatusResponse CreateManyTickets(IEnumerable tickets); @@ -188,7 +198,16 @@ public interface ITickets : ICore Task GetMultipleTicketsAsync(IEnumerable ids, TicketSideLoadOptionsEnum sideLoadOptions = TicketSideLoadOptionsEnum.None); - Task CreateTicketAsync(Ticket ticket); + /// + /// Creates a ticket. + /// If a idempotency-key is provided and the same request using the same body and idempotency key is repeated, another ticket is not created. + /// Instead, you'll get the same response as before that is cached under the idempotency key + /// + /// + /// The Ticketing API lets you specify an idempotency key that allows you to retry a ticket creation request without the + /// risk of creating duplicate records. + /// + Task CreateTicketAsync(Ticket ticket, string idempotencyKey = null); Task CreateManyTicketsAsync(IEnumerable tickets); @@ -418,9 +437,18 @@ public GroupTicketResponse GetMultipleTickets(IEnumerable ids, TicketSideL return GenericGet(resource); } - public IndividualTicketResponse CreateTicket(Ticket ticket) + public IndividualTicketResponse CreateTicket(Ticket ticket, string idempotencyKey = null) { - return GenericPost($"{_tickets}.json", new { ticket }); + NameValueCollection headers = null; + if (!string.IsNullOrEmpty(idempotencyKey)) + { + headers = new NameValueCollection + { + { "Idempotency-Key", idempotencyKey } + }; + } + + return GenericPost($"{_tickets}.json", new { ticket }, headers: headers); } public JobStatusResponse CreateManyTickets(IEnumerable tickets) @@ -798,9 +826,18 @@ public async Task GetMultipleTicketsAsync(IEnumerable return await GenericGetAsync(GetResourceStringWithSideLoadOptionsParam($"{_tickets}/show_many.json?ids={ids.ToCsv()}", sideLoadOptions)); } - public async Task CreateTicketAsync(Ticket ticket) + public async Task CreateTicketAsync(Ticket ticket, string idempotencyKey = null) { - return await GenericPostAsync($"{_tickets}.json", new { ticket }); + NameValueCollection headers = null; + if (!string.IsNullOrEmpty(idempotencyKey)) + { + headers = new NameValueCollection + { + { "Idempotency-Key", idempotencyKey } + }; + } + + return await GenericPostAsync($"{_tickets}.json", new { ticket }, headers: headers); } public async Task CreateManyTicketsAsync(IEnumerable tickets) diff --git a/src/global.json b/src/global.json index d5aa2bf7..27414bdd 100644 --- a/src/global.json +++ b/src/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "6.0.408" + "version": "6.0.423" } }