async Task <string> PerformRequest(HttpMethod httpMethod, string additionalUrl, HttpContent content, bool throwExceptionOn404, CancellationToken token, TimeSpan?requestTimeout = null) { var reqMessage = CreateRequestMessage(httpMethod, additionalUrl, content); HttpResponseMessage httpResponse; string response; using (var cts = new CancellationTokenSource(requestTimeout ?? defaultRequestTimeout)) { var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, cts.Token); httpResponse = await httpClient.SendAsync(reqMessage, linkedTokenSource.Token); response = await httpResponse.Content.ReadAsStringAsync(); if (!throwExceptionOn404 && httpResponse.StatusCode == System.Net.HttpStatusCode.NotFound) { return(null); } } if (!httpResponse.IsSuccessStatusCode) { ProblemDetails problemDetails = null; try { problemDetails = HelperTools.JSONDeserializeNewtonsoft <ProblemDetails>(response); } catch (Exception) { // We can ignore exception here. If there was an exception, problemDetails will be null and it will be handled later in the code. } string errMessage; if (problemDetails != null) { errMessage = $"Error calling {reqMessage.RequestUri}. Response code: {problemDetails.Status}, content: '{problemDetails.Title}'"; } else { errMessage = $"Error calling {reqMessage.RequestUri}. Response code: {(int)httpResponse.StatusCode}, content: '{response}'"; } if (httpResponse.StatusCode == System.Net.HttpStatusCode.NotFound) { throw new NotFoundException(errMessage); } throw new BadRequestException(errMessage); } return(response); }