public IActionResult Post([Microsoft.AspNetCore.Mvc.FromBody] ZipCodeLookupRequest zipCodeLookupRequest) { var zipCodeLookupResponse = _addressProvider.SendZipCodeLookupRequest(zipCodeLookupRequest); if (zipCodeLookupResponse == null) { return(BadRequest(zipCodeLookupResponse)); } return(Ok(zipCodeLookupResponse)); }
public ZipCodeLookupResponse SendZipCodeLookupRequest(ZipCodeLookupRequest zipCodeLookupRequest) { var deserializer = new XmlDeserializer(); var request = new RestRequest(Method.GET); var lookupRequest = SerializeZipCodeLookupRequest(zipCodeLookupRequest); var baseUrl = new Uri($"https://secure.shippingapis.com/shippingapi.dll?API=ZipCodeLookup&XML={lookupRequest}"); _restClient.BaseUrl = baseUrl; var response = _restClient.Execute(request); var zipCodeLookupResponse = deserializer.Deserialize <ZipCodeLookupResponse>(response); return(zipCodeLookupResponse); }
public void Should_Return_Deserialized_Example_API_Result() { var addressProvider = new AddressProvider(new RestClient()); var zipCodeLookupRequest = new ZipCodeLookupRequest { Address = new Address { Address1 = "911 Military St", City = "Port Huron", State = "MI" } }; var zipCodeResponse = addressProvider.SendZipCodeLookupRequest(zipCodeLookupRequest); Assert.NotNull(zipCodeResponse); Assert.Equal("PORT HURON", zipCodeResponse.Address.City); Assert.Equal("48060", zipCodeResponse.Address.Zip5); Assert.Equal("5414", zipCodeResponse.Address.Zip4); }
private static string SerializeZipCodeLookupRequest(ZipCodeLookupRequest zipCodeLookupRequest) { var serializer = new System.Xml.Serialization.XmlSerializer(typeof(ZipCodeLookupRequest)); var settings = new XmlWriterSettings { Indent = false, NewLineHandling = NewLineHandling.None, OmitXmlDeclaration = true }; var namespaces = new XmlSerializerNamespaces(); namespaces.Add("", ""); var sw = new StringWriter(); var writer = XmlWriter.Create(sw, settings); serializer.Serialize(writer, zipCodeLookupRequest, namespaces); var lookupRequest = sw.ToString(); return(lookupRequest); }
internal static async Task <List <Address> > ZipCodeLookupAsync(List <Address> input) { // limit is 5 addresses per request string requestGuid = Guid.NewGuid().ToString(); Log.Information("{area}: New request for {packageTotal} packages. {requestGuid}", "ZipCodeLookup()", input.Count, requestGuid); List <Address> output = new(); ZipCodeLookupRequest request; int index = 0; while (index < input.Count) { request = new ZipCodeLookupRequest { Address = input.Skip(index).Take(5).ToList(), USERID = UspsApiUsername, }; Log.Information("{area}: Fetching rates for {packageCount} package(s). {requestGuid}", "ZipCodeLookup()", input.Count, requestGuid); XmlSerializer xsSubmit = new(typeof(ZipCodeLookupRequest)); var xml = ""; using (var sww = new StringWriter()) { using XmlWriter writer = XmlWriter.Create(sww); xsSubmit.Serialize(writer, request); xml = sww.ToString(); } string uspsUrl = "https://secure.shippingapis.com/ShippingAPI.dll"; var formData = new FormUrlEncodedContent(new[] { new KeyValuePair <string, string>("API", "ZipCodeLookup"), new KeyValuePair <string, string>("XML", xml) }); HttpClient httpClient = new() { Timeout = TimeSpan.FromSeconds(50) }; HttpResponseMessage response = null; int retryCount = 0; DateTime responseTimer = DateTime.Now; while (response == null || response.StatusCode != System.Net.HttpStatusCode.OK) { if (retryCount > 0) { Log.Warning("{area}: USPS Failed to Respond after " + retryCount + " seconds. Attempt {retryCount}. {requestGuid}", "ZipCodeLookup()", retryCount, requestGuid); } response = await httpClient.PostAsync(uspsUrl, formData).ConfigureAwait(false); Thread.Sleep(1000 * retryCount); httpClient.CancelPendingRequests(); retryCount++; if (retryCount > 50) { Log.Error("{area}: USPS Failed to Respond after 50 attempts. {requestGuid}", "ZipCodeLookup()", retryCount, requestGuid); throw new UspsApiException("408: After many attempts, the request to the USPS API did not recieve a response. Please try again later."); } } TimeSpan responseTime = DateTime.Now.TimeOfDay.Subtract(responseTimer.TimeOfDay); var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); Log.Information("{area}: USPS response received in {responseTime} ms. {requestGuid}", "ZipCodeLookup()", responseTime.Milliseconds, requestGuid); try { XmlSerializer deserializer = new(typeof(ZipCodeLookupResponse)); var ms = new MemoryStream(Encoding.UTF8.GetBytes(content)); ZipCodeLookupResponse responseJson = (ZipCodeLookupResponse)deserializer.Deserialize(ms); index += 5; foreach (Address validatedAddress in responseJson.Address) { Address orig = input.First(i => i.ID == validatedAddress.ID); if (validatedAddress.Error != null) { Log.Warning("{area}: USPS Returned Error: {uspsErrorNumber} {uspsErrorDescription} {requestGuid}", "ZipCodeLookup()", validatedAddress.Error.Number, validatedAddress.Error.Description, requestGuid); orig.Error = validatedAddress.Error; } orig.Zip5 = validatedAddress.Zip5; orig.Zip4 = validatedAddress.Zip4; output.Add(orig); } } catch (Exception ex) { Log.Error("{area}: Exception: {ex} {requestGuid}", "ZipCodeLookup()", ex.ToString(), requestGuid); throw new UspsApiException(ex); } } if (output.Count != input.Count) { // something went wrong because counts should always match Console.WriteLine("Counts did not match between input and output"); Log.Error("{area}: Counts did not match between input and output. {requestGuid}", "ZipCodeLookup()", requestGuid); throw new UspsApiException("Counts did not match between input and output"); } return(output); }
public static async Task <UspsAddress> ZipCodeLookupAsync(ZipCodeLookupRequest request) { const string API = "ZipCodeLookup"; string Url = String.Format("{0}{1}&XML={2}", BaseUrl, API, request.XML); string Address1 = ""; string Address2 = ""; string City = ""; string State = ""; string Zip4 = ""; string Zip5 = ""; string errorDescription = ""; try { WebRequest wr = WebRequest.Create(Url); wr.Timeout = 5000; WebResponse response = await wr.GetResponseAsync(); Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseFromServer = reader.ReadToEnd(); reader.Close(); dataStream.Close(); response.Close(); XDocument ZipCodeLookupResponse = XDocument.Parse(responseFromServer); //check for error response from api if (ZipCodeLookupResponse.Element("ZipCodeLookupResponse").Element("Address").HasElements) { IEnumerable <XElement> collection = ZipCodeLookupResponse.Element("ZipCodeLookupResponse").Element("Address").Elements(); foreach (XElement x in collection) { if (x.Name.LocalName == "Address1") { Address1 = x.Value; } else if (x.Name.LocalName == "Address2") { Address2 = x.Value; } else if (x.Name.LocalName == "City") { City = x.Value; } else if (x.Name.LocalName == "State") { State = x.Value; } else if (x.Name.LocalName == "Zip4") { Zip4 = x.Value; } else if (x.Name.LocalName == "Zip5") { Zip5 = x.Value; } else if (x.Name == "Error" && x.HasElements) { foreach (XElement error in x.Elements()) { if (error.Name == "Description") { errorDescription = error.Value; } } } } } } catch (Exception ex) { errorDescription = ex.Message; } //string[] Zip = new string[] { Zip5, Zip4, request.Name, errorDescription }; UspsAddress result = new UspsAddress { Name = request.Name, Address1 = Address1, Address2 = Address2, City = City, State = State, Zip4 = Zip4, Zip5 = Zip5, ErrorDescription = errorDescription }; return(result); }