Kevin Lewis Blog
All about CODE - VB.net, ASP.net, SQL Server, and everything in between

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