LINQ to UPS to Calculate Shipping Rates
May 22, 2008 Posted by Kevin Lewis
I decided to cleanup my old UPS Webservice Rate Calculation code, and implement some XML literals as well as Linq to XML. The below code is much easier to understand and maintain. I love the new xml syntax for accessing elements.
Private Function GetShippingMethodsFromWeb(ByVal ZipTo As String, ByVal Weight As Integer) As List(Of Linq.ShippingMethod)
Const URL As String = "https://www.ups.com/ups.app/xml/Rate"
If Weight < 1 Then Weight = 1
Dim XMLAuth = <?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
<AccessLicenseNumber><%= App.Settings.UPSAccessKey %></AccessLicenseNumber>
<UserId><%= App.Settings.UPSUserID %></UserId>
<Password><%= App.Settings.UPSPassword %></Password>
</AccessRequest>
Dim XMLRequest = <?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
<Request>
<TransactionReference>
<CustomerContext>Rating and Service</CustomerContext>
<XpciVersion>1.0001</XpciVersion>
</TransactionReference>
<RequestAction>Rate</RequestAction>
<RequestOption>shop</RequestOption>
</Request>
<PickupType>
<Code>01</Code>
</PickupType>
<Shipment>
<Shipper>
<Address>
<PostalCode><%= App.Settings.ShipFromZipCode %></PostalCode>
</Address>
</Shipper>
<ShipTo>
<Address>
<PostalCode><%= ZipTo %></PostalCode>
<ResidentialAddressIndicator>0</ResidentialAddressIndicator>
<CountryCode>US</CountryCode>
</Address>
</ShipTo>
<Package>
<PackagingType>
<Code>02</Code>
<Description>Package</Description>
</PackagingType>
<Description>Rate Shopping</Description>
<PackageWeight>
<Weight><%= Weight %></Weight>
</PackageWeight>
</Package>
</Shipment>
</RatingServiceSelectionRequest>
'<% If Length > 0 And Width > 0 And Depth > 0 Then %>
' <Dimensions>
' If Length Then
' sXML &= "<Length>" & Length </Length>"
' End If
' If Width Then
' sXML &= "<Width>" & Width </Width>"
' End If
' If Depth Then
' sXML &= "<Height>" & Depth </Height>"
' End If
' sXML &= "</Dimensions>"
'End If
Dim objRequest = System.Net.WebRequest.Create(URL)
objRequest.Method = "POST"
objRequest.ContentType = "application/x-www-form-urlencoded"
Using myWriter = New System.IO.StreamWriter(objRequest.GetRequestStream())
myWriter.Write(XMLAuth.Declaration)
myWriter.Write(XMLAuth)
myWriter.Write(XMLRequest.Declaration)
myWriter.Write(XMLRequest)
myWriter.Flush()
myWriter.Close()
End Using
objRequest.Timeout = 5000
Dim xmlResponse As System.Xml.Linq.XDocument
Using objResponse = objRequest.GetResponse
Using sr As New System.IO.StreamReader(objResponse.GetResponseStream())
xmlResponse = System.Xml.Linq.XDocument.Load(sr)
End Using
End Using
If xmlResponse...<ResponseStatusCode>.Value = "1" Then
Dim Rates = From r In xmlResponse...<RatedShipment> _
Select Code = r...<Code>.Value, _
Charge = CDec(r...<MonetaryValue>.Value)
Dim db As New DataContext
Dim ShippingMethods = (From s In db.ShippingMethods _
Where s.Active AndAlso s.Carrier = "UPS" _
Order By s.SortOrder).ToList
For Each s In ShippingMethods
Dim r = Rates.SingleOrDefault(Function(a) a.Code = s.Code)
If r IsNot Nothing Then
s.ShippingCharge = r.Charge
End If
Next
ShippingMethods.RemoveAll(Function(a) a.ShippingCharge = 0)
Return ShippingMethods
Else
Throw New Exception("An error occurred while calculating UPS shipping rates: " & xmlResponse...<ErrorDescription>.Value & ". Location: " & xmlResponse...<ErrorLocationElementName>.Value)
End If
End Function

