/// <summary> /// Implementation of raw string-returning async API /// </summary> /// <param name="cd"></param> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private async Task <string> RestCallStringAsync(string verb, AvaTaxPath relativePath, object content = null, CallDuration cd = null) { if (cd == null) { cd = new CallDuration(); } // Convert the JSON payload, if any object jsonPayload = null; string mimeType = null; if (content != null && content is FileResult) { var fr = (FileResult)content; mimeType = fr.ContentType; MultipartFormDataContent mpfdc = new MultipartFormDataContent("----dataBoundary"); ByteArrayContent byteArrayContent = new ByteArrayContent(fr.Data); byteArrayContent.Headers.Add("Content-Type", "application/octet-stream"); mpfdc.Add(byteArrayContent, fr.Filename, fr.Filename); jsonPayload = mpfdc; } else if (content != null) { jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); mimeType = "application/json"; } // Call REST using (var result = await InternalRestCallAsync(cd, verb, relativePath, jsonPayload, mimeType).ConfigureAwait(false)) { // Read the result var responseString = await result.Content.ReadAsStringAsync().ConfigureAwait(false); // Determine server duration var sd = DetectDuration(result, "serverduration"); var dd = DetectDuration(result, "dataduration"); var td = DetectDuration(result, "serviceduration"); cd.FinishReceive(sd, dd, td); // Capture information about this API call and make it available for logging var eventargs = new AvaTaxCallEventArgs() { HttpVerb = verb.ToUpper(), Code = result.StatusCode, RequestUri = new Uri(_envUri, relativePath.ToString()), RequestBody = jsonPayload as string, ResponseString = responseString, Duration = cd }; OnCallCompleted(eventargs); // Deserialize the result if (result.IsSuccessStatusCode) { return(responseString); } else { var err = JsonConvert.DeserializeObject <ErrorResult>(responseString); cd.FinishParse(); this.LastCallTime = cd; throw new AvaTaxError(err, result.StatusCode); } } }
/// <summary> /// Implementation of raw file-returning async API /// </summary> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private async Task <FileResult> RestCallFileAsync(string verb, AvaTaxPath relativePath, object content = null) { CallDuration cd = new CallDuration(); // Convert the JSON payload, if any string jsonPayload = null; if (content != null) { jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); } // Call REST using (var result = await InternalRestCallAsync(cd, verb, relativePath, jsonPayload).ConfigureAwait(false)) { // Read the result if (result.IsSuccessStatusCode) { var fr = new FileResult() { ContentType = result.Content.Headers.GetValues("Content-Type").FirstOrDefault(), Filename = GetDispositionFilename(result.Content.Headers.GetValues("Content-Disposition").FirstOrDefault()), Data = await result.Content.ReadAsByteArrayAsync().ConfigureAwait(false) }; // Capture timings cd.FinishParse(); this.LastCallTime = cd; // Capture information about this API call and make it available for logging var eventargs = new AvaTaxCallEventArgs() { HttpVerb = verb.ToUpper(), Code = result.StatusCode, RequestUri = new Uri(_envUri, relativePath.ToString()), RequestBody = jsonPayload, ResponseBody = fr.Data, Duration = cd }; OnCallCompleted(eventargs); return(fr); // Handle exceptions and convert them to AvaTax results } else { var errorResponseString = await result.Content.ReadAsStringAsync().ConfigureAwait(false); var err = JsonConvert.DeserializeObject <ErrorResult>(errorResponseString); cd.FinishParse(); this.LastCallTime = cd; // Capture information about this API call error and make it available for logging var eventargs = new AvaTaxCallEventArgs() { HttpVerb = verb.ToUpper(), Code = result.StatusCode, RequestUri = new Uri(_envUri, relativePath.ToString()), RequestBody = jsonPayload, ResponseString = errorResponseString, Duration = cd }; OnCallCompleted(eventargs); throw new AvaTaxError(err, result.StatusCode); } } }
/// <summary> /// Implementation of raw string-returning async API /// </summary> /// <param name="cd"></param> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private async Task <string> RestCallStringAsync(string verb, AvaTaxPath relativePath, object content = null, CallDuration cd = null) { if (cd == null) { cd = new CallDuration(); } // Convert the JSON payload, if any string jsonPayload = null; if (content != null) { jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); } // Call REST using (var result = await InternalRestCallAsync(cd, verb, relativePath, jsonPayload).ConfigureAwait(false)) { // Read the result var responseString = await result.Content.ReadAsStringAsync().ConfigureAwait(false); // Determine server duration var sd = DetectDuration(result, "serverduration"); var dd = DetectDuration(result, "dataduration"); var td = DetectDuration(result, "serviceduration"); cd.FinishReceive(sd, dd, td); // Capture information about this API call and make it available for logging var eventargs = new AvaTaxCallEventArgs() { HttpVerb = verb.ToUpper(), Code = result.StatusCode, RequestUri = new Uri(_envUri, relativePath.ToString()), RequestBody = jsonPayload, ResponseString = responseString, Duration = cd }; OnCallCompleted(eventargs); // Deserialize the result if (result.IsSuccessStatusCode) { return(responseString); } else { var err = JsonConvert.DeserializeObject <ErrorResult>(responseString); cd.FinishParse(); this.LastCallTime = cd; throw new AvaTaxError(err, result.StatusCode); } } }
/// <summary> /// Direct implementation of client APIs to string values /// </summary> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private string RestCallString(string verb, AvaTaxPath relativePath, object content = null) { string path = CombinePath(_envUri.ToString(), relativePath.ToString()); string jsonPayload = null; string mimeType = null; // Use HttpWebRequest so we can get a decent response var wr = (HttpWebRequest)WebRequest.Create(path); wr.Proxy = null; // Add headers foreach (var key in _clientHeaders.Keys) { wr.Headers.Add(key, _clientHeaders[key]); } // Convert the name-value pairs into a byte array wr.Method = verb; //Upload file. if (content != null && content is FileResult) { wr.KeepAlive = true; var fr = (FileResult)content; mimeType = fr.ContentType; content = fr.Data; string dataBoundary = "----dataBoundary"; wr.ContentType = "multipart/form-data; boundary=" + dataBoundary; byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + dataBoundary + "\r\n"); Stream rs = wr.GetRequestStream(); rs.Write(boundaryBytes, 0, boundaryBytes.Length); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; string header = string.Format(headerTemplate, fr.Filename, fr.Filename, fr.ContentType); byte[] headerBytes = Encoding.UTF8.GetBytes(header); rs.Write(headerBytes, 0, headerBytes.Length); rs.Write(fr.Data, 0, fr.Data.Length); byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + dataBoundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); } else if (content != null) { wr.ContentType = mimeType ?? Constants.JSON_MIME_TYPE; wr.ServicePoint.Expect100Continue = false; // Encode the payload jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); var encoding = new UTF8Encoding(); byte[] data = encoding.GetBytes(jsonPayload); wr.ContentLength = data.Length; // Call the server using (var s = wr.GetRequestStream()) { s.Write(data, 0, data.Length); s.Close(); } } // Transmit, and get back the response, save it to a temp file try { using (var response = wr.GetResponse()) { using (var inStream = response.GetResponseStream()) { using (var reader = new StreamReader(inStream)) { var responseString = reader.ReadToEnd(); // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)response).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseString = responseString, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); // Here's the results return(responseString); } } } // Catch a web exception } catch (WebException webex) { HttpWebResponse httpWebResponse = webex.Response as HttpWebResponse; if (httpWebResponse != null) { using (Stream stream = httpWebResponse.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { var errString = reader.ReadToEnd(); // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)httpWebResponse).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseString = errString, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); // Here's the results var err = JsonConvert.DeserializeObject <ErrorResult>(errString); throw new AvaTaxError(err, httpWebResponse.StatusCode); } } } // If we can't parse it as an AvaTax error, just throw throw webex; } }
/// <summary> /// Direct implementation of client APIs to string values /// </summary> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private FileResult RestCallFile(string verb, AvaTaxPath relativePath, object content = null) { string path = CombinePath(_envUri.ToString(), relativePath.ToString()); string jsonPayload = null; // Use HttpWebRequest so we can get a decent response var wr = (HttpWebRequest)WebRequest.Create(path); wr.Proxy = null; // Add headers foreach (var key in _clientHeaders.Keys) { wr.Headers.Add(key, _clientHeaders[key]); } // Convert the name-value pairs into a byte array wr.Method = verb; if (content != null) { wr.ContentType = Constants.JSON_MIME_TYPE; wr.ServicePoint.Expect100Continue = false; // Encode the payload jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); var encoding = new UTF8Encoding(); byte[] data = encoding.GetBytes(jsonPayload); wr.ContentLength = data.Length; // Call the server using (var s = wr.GetRequestStream()) { s.Write(data, 0, data.Length); s.Close(); } } // Transmit, and get back the response, save it to a temp file try { using (var response = wr.GetResponse()) { using (var inStream = response.GetResponseStream()) { const int BUFFER_SIZE = 1024; var chunks = new List <byte>(); var totalBytes = 0; var bytesRead = 0; do { var buffer = new byte[BUFFER_SIZE]; bytesRead = inStream.Read(buffer, 0, BUFFER_SIZE); if (bytesRead == BUFFER_SIZE) { chunks.AddRange(buffer); } else { for (int i = 0; i < bytesRead; i++) { chunks.Add(buffer[i]); } } totalBytes += bytesRead; } while (bytesRead > 0); if (totalBytes <= 0) { throw new IOException("Response contained no data"); } // Here's your file result var fr = new FileResult() { ContentType = response.Headers["Content-Type"].ToString(), Filename = GetDispositionFilename(response.Headers["Content-Disposition"].ToString()), Data = chunks.ToArray() }; // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)response).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseBody = fr.Data, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); return(fr); } } // Catch a web exception } catch (WebException webex) { HttpWebResponse httpWebResponse = webex.Response as HttpWebResponse; if (httpWebResponse != null) { using (Stream stream = httpWebResponse.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { var errString = reader.ReadToEnd(); // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)httpWebResponse).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseString = errString, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); // Pass on the error var err = JsonConvert.DeserializeObject <ErrorResult>(errString); throw new AvaTaxError(err, httpWebResponse.StatusCode); } } } // If we can't parse it as an AvaTax error, just throw throw webex; } }
/// <summary> /// Direct implementation of client APIs to string values /// </summary> /// <param name="verb"></param> /// <param name="relativePath"></param> /// <param name="content"></param> /// <returns></returns> private string RestCallString(string verb, AvaTaxPath relativePath, object content = null) { string path = CombinePath(_envUri.ToString(), relativePath.ToString()); string jsonPayload = null; // Use HttpWebRequest so we can get a decent response var wr = (HttpWebRequest)WebRequest.Create(path); wr.Proxy = null; // Add headers foreach (var key in _clientHeaders.Keys) { wr.Headers.Add(key, _clientHeaders[key]); } // Convert the name-value pairs into a byte array wr.Method = verb; wr.ContentLength = 0; if (content != null) { wr.ContentType = Constants.JSON_MIME_TYPE; wr.ServicePoint.Expect100Continue = false; // Encode the payload jsonPayload = JsonConvert.SerializeObject(content, SerializerSettings); var encoding = new UTF8Encoding(); byte[] data = encoding.GetBytes(jsonPayload); wr.ContentLength = data.Length; // Call the server using (var s = wr.GetRequestStream()) { s.Write(data, 0, data.Length); s.Close(); } } // Transmit, and get back the response, save it to a temp file try { using (var response = wr.GetResponse()) { using (var inStream = response.GetResponseStream()) { using (var reader = new StreamReader(inStream)) { var responseString = reader.ReadToEnd(); // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)response).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseString = responseString, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); // Here's the results return(responseString); } } } // Catch a web exception } catch (WebException webex) { HttpWebResponse httpWebResponse = webex.Response as HttpWebResponse; if (httpWebResponse != null) { using (Stream stream = httpWebResponse.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { var errString = reader.ReadToEnd(); // Track the API call var eventargs = new AvaTaxCallEventArgs() { Code = ((HttpWebResponse)httpWebResponse).StatusCode, Duration = null, HttpVerb = wr.Method, RequestBody = jsonPayload, ResponseString = errString, RequestUri = new Uri(path) }; OnCallCompleted(eventargs); // Here's the results var err = JsonConvert.DeserializeObject <ErrorResult>(errString); throw new AvaTaxError(err, httpWebResponse.StatusCode); } } } // If we can't parse it as an AvaTax error, just throw throw webex; } }