2012-07-06 103 views
0

對此的答案可能是非常明顯的。但需要一些幫助...需要原始XML請求和響應在UPS API(.Net)

我目前使用UPS API /服務來生成測試標籤。一切都很好。但要獲得認證,我必須向UPS發送請求&響應中的原始XML。

我不是發送原始xml,而是使用服務及其各種屬性。發貨結果中是否有原始XML返回?或者必須手動序列化請求&響應才能滿足UPS在其審閱中需要的內容?

這裏是我的代碼(一切正常,我能夠產生一個標籤,但我如何才能請求&響應XML?)

try 
     { 
      ShipService shpSvc = new ShipService(); 
      ShipmentRequest shipmentRequest = new ShipmentRequest(); 
      UPSSecurity upss = new UPSSecurity(); 
      UPSSecurityServiceAccessToken upssSvcAccessToken = new UPSSecurityServiceAccessToken(); 
      upssSvcAccessToken.AccessLicenseNumber = s.APIKey; 
      upss.ServiceAccessToken = upssSvcAccessToken; 
      UPSSecurityUsernameToken upssUsrNameToken = new UPSSecurityUsernameToken(); 
      upssUsrNameToken.Username = s.Username; 
      upssUsrNameToken.Password = s.Password; 
      upss.UsernameToken = upssUsrNameToken; 
      shpSvc.UPSSecurityValue = upss; 
      RequestType request = new RequestType(); 

      String[] requestOption = { "nonvalidate" }; 
      request.RequestOption = requestOption; 
      shipmentRequest.Request = request;     

    ShipmentType shipment = new ShipmentType();     
      ShipperType shipper = new ShipperType(); 
      shipper.ShipperNumber = s.ShipperAccountNumber; 
      PaymentInfoType paymentInfo = new PaymentInfoType(); 

    ShipmentChargeType shpmentCharge = new ShipmentChargeType(); 
      BillShipperType billShipper = new BillShipperType(); 
      billShipper.AccountNumber = s.ShipperAccountNumber; 
      shpmentCharge.BillShipper = billShipper; 
      shpmentCharge.Type = "01"; 

    ShipmentChargeType[] shpmentChargeArray = { shpmentCharge }; 
      paymentInfo.ShipmentCharge = shpmentChargeArray; 
      shipment.PaymentInformation = paymentInfo; 
      ShipWebReference.ShipAddressType shipperAddress = new ShipWebReference.ShipAddressType(); 
      String[] addressLine = { s.ShipperAddressLine }; 

    shipperAddress.AddressLine = addressLine; 
      shipperAddress.City = s.ShipperCity; 
      shipperAddress.PostalCode = s.ShipperZip; 
      shipperAddress.StateProvinceCode = s.ShipperState; 
      shipperAddress.CountryCode = "US"; 
      shipperAddress.AddressLine = addressLine; 
      shipper.Address = shipperAddress; 
      shipper.Name = s.ShipperName; 
      shipper.AttentionName = s.ShipperName; 
      ShipPhoneType shipperPhone = new ShipPhoneType(); 
      shipperPhone.Number = s.ShipperPhone; 
      shipper.Phone = shipperPhone; 
      shipment.Shipper = shipper; 
      ShipFromType shipFrom = new ShipFromType(); 

    ShipWebReference.ShipAddressType shipFromAddress = new ShipWebReference.ShipAddressType(); 
      String[] shipFromAddressLine = { s.ShipperAddressLine }; 
      shipFromAddress.AddressLine = addressLine; 
      shipFromAddress.City = s.ShipperCity; 
      shipFromAddress.PostalCode = s.ShipperZip; 
      shipFromAddress.StateProvinceCode = s.ShipperState; 
      shipFromAddress.CountryCode = "US"; 
      shipFrom.Address = shipFromAddress; 
      shipFrom.AttentionName = s.ShipperName; 
      shipFrom.Name = s.ShipperName; 
      shipment.ShipFrom = shipFrom; 

    ShipToType shipTo = new ShipToType(); 
      ShipToAddressType shipToAddress = new ShipToAddressType(); 
      String[] addressLine1 = { s.ShipToAddressLine }; 
      shipToAddress.AddressLine = addressLine1; 
      shipToAddress.City = s.ShipToCity; 
      shipToAddress.PostalCode = s.ShipToZip; 
      shipToAddress.StateProvinceCode = s.ShipToState; 
      shipToAddress.CountryCode = "US"; 
      shipTo.Address = shipToAddress; 
      shipTo.AttentionName = s.ShipToName; 
      shipTo.Name = s.ShipToName; 

      ShipPhoneType shipToPhone = new ShipPhoneType(); 
      shipToPhone.Number = s.ShipToPhone; 
      shipTo.Phone = shipToPhone; 
      shipment.ShipTo = shipTo; 
      ServiceType service = new ServiceType(); 

      service.Code = "03"; 
      shipment.Service = service; 
      PackageType package = new PackageType(); 
      PackageWeightType packageWeight = new PackageWeightType(); 
      packageWeight.Weight = s.PackageWeight; 
      ShipUnitOfMeasurementType uom = new ShipUnitOfMeasurementType(); 
      uom.Code = "LBS"; 
      packageWeight.UnitOfMeasurement = uom; 
      package.PackageWeight = packageWeight; 
      PackagingType packType = new PackagingType(); 
      packType.Code = "02"; 
      package.Packaging = packType; 
      PackageType[] pkgArray = { package }; 
      shipment.Package = pkgArray; 
      LabelSpecificationType labelSpec = new LabelSpecificationType(); 
      LabelStockSizeType labelStockSize = new LabelStockSizeType(); 
      labelStockSize.Height = "6"; 
      labelStockSize.Width = "4"; 
      labelSpec.LabelStockSize = labelStockSize; 
      LabelImageFormatType labelImageFormat = new LabelImageFormatType(); 
      LabelDeliveryType labelDel = new LabelDeliveryType(); 
      labelDel.LabelLinksIndicator = ""; 
      labelImageFormat.Code = "GIF"; 

      PackageServiceOptionsType packServiceOptions = new PackageServiceOptionsType(); 
      PackageDeclaredValueType decType = new PackageDeclaredValueType(); 
      decType.CurrencyCode = "USD"; 
      decType.MonetaryValue = s.PackageValue; 
      packServiceOptions.DeclaredValue = decType; 
      package.PackageServiceOptions = packServiceOptions; 


      labelSpec.LabelImageFormat = labelImageFormat; 
      ShipmentTypeShipmentServiceOptions shipServOpt = new ShipmentTypeShipmentServiceOptions(); 

      shipment.ShipmentServiceOptions = shipServOpt; 


      shipmentRequest.LabelSpecification = labelSpec; 
      shipmentRequest.Shipment = shipment; 

      System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy(); 
      Console.WriteLine(shipmentRequest); 

      shipmentResponse = shpSvc.ProcessShipment(shipmentRequest);    

     } 

回答

1

我遇到漂亮了同樣的問題,幸運的是我解決了這個問題;)

你需要的東西註冊一個SOAP擴展:

[ReflectionPermission(SecurityAction.Demand, Unrestricted = true)] 
    public static void RegisterSoapExtension(Type type, int priority, PriorityGroup group) 
    { 
     if (!type.IsSubclassOf(typeof(SoapExtension))) 
     { 
      throw new ArgumentException("Type must be derived from SoapException.", "type"); 
     } 

     if (priority < 1) 
     { 
      throw new ArgumentOutOfRangeException("priority", priority, "Priority must be greater or equal to 1."); 
     } 

     // get the current web services settings... 
     WebServicesSection wss = WebServicesSection.Current; 

     // set SoapExtensionTypes collection to read/write... 
     FieldInfo readOnlyField = typeof(System.Configuration.ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 
     readOnlyField.SetValue(wss.SoapExtensionTypes, false); 

     // inject SoapExtension... 
     //wss.SoapExtensionTypes.Add(new SoapExtensionTypeElement(type, priority, group)); 

     System.Web.Services.Configuration.SoapExtensionTypeElement soapInterceptor = new SoapExtensionTypeElement(); 
     soapInterceptor.Type = type; 
     soapInterceptor.Priority = priority; 
     soapInterceptor.Group = group; 
     wss.SoapExtensionTypes.Add(soapInterceptor); 

     // set SoapExtensionTypes collection back to readonly and clear modified flags... 
     MethodInfo resetModifiedMethod = typeof(System.Configuration.ConfigurationElement).GetMethod("ResetModified", BindingFlags.NonPublic | BindingFlags.Instance); 
     resetModifiedMethod.Invoke(wss.SoapExtensionTypes, null); 
     MethodInfo setReadOnlyMethod = typeof(System.Configuration.ConfigurationElement).GetMethod("SetReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 
     setReadOnlyMethod.Invoke(wss.SoapExtensionTypes, null); 
    } 

您需要定義實際的擴展:

/// <summary> 
/// SOAP Extension that traces the SOAP request and 
/// SOAP response to a SOAP API Web service. 
/// </summary> 
public class TraceExtension : SoapExtension 
{ 
    private Stream oldStream; 
    private Stream newStream; 

    private static XmlDocument xmlRequest; 

    /// <summary> 
    /// Gets the outgoing XML request 
    /// </summary> 
    public static XmlDocument XmlRequest 
    { 
     get { return xmlRequest; } 
    } 

    private static XmlDocument xmlResponse; 

    /// <summary> 
    /// Gets the incoming XML response 
    /// </summary> 
    public static XmlDocument XmlResponse 
    { 
     get { return xmlResponse; } 
    } 

    /// <summary> 
    /// Save the Stream representing the SOAP request 
    /// or SOAP response into a local memory buffer. 
    /// </summary> 
    /// <param name="stream"></param> 
    /// <returns></returns> 
    public override Stream ChainStream(Stream stream) 
    { 
     oldStream = stream; 
     newStream = new MemoryStream(); 
     return newStream; 
    } 

    /// <summary> 
    /// If the SoapMessageStage is such that the SoapRequest or 
    /// SoapResponse is still in the SOAP format to be sent or received, 
    /// save it to the xmlRequest or xmlResponse property. 
    /// </summary> 
    /// <param name="message"></param> 
    public override void ProcessMessage(SoapMessage message) 
    { 
     switch (message.Stage) 
     { 
      case SoapMessageStage.BeforeSerialize: 
       break; 
      case SoapMessageStage.AfterSerialize: 
       xmlRequest = GetSoapEnvelope(newStream); 
       CopyStream(newStream, oldStream); 
       break; 
      case SoapMessageStage.BeforeDeserialize: 
       CopyStream(oldStream, newStream); 
       xmlResponse = GetSoapEnvelope(newStream); 
       break; 
      case SoapMessageStage.AfterDeserialize: 
       break; 
     } 
    } 

    /// <summary> 
    /// Returns the XML representation of the Soap Envelope in the supplied stream. 
    /// Resets the position of stream to zero. 
    /// </summary> 
    /// <param name="stream"></param> 
    /// <returns></returns> 
    private XmlDocument GetSoapEnvelope(Stream stream) 
    { 
     var xml = new XmlDocument(); 
     stream.Position = 0; 
     var reader = new StreamReader(stream); 
     xml.LoadXml(reader.ReadToEnd()); 
     stream.Position = 0; 
     return xml; 
    } 

    /// <summary> 
    /// Copies a stream. 
    /// </summary> 
    /// <param name="from"></param> 
    /// <param name="to"></param> 
    private void CopyStream(Stream from, Stream to) 
    { 
     TextReader reader = new StreamReader(from); 
     TextWriter writer = new StreamWriter(to); 
     writer.WriteLine(reader.ReadToEnd()); 
     writer.Flush(); 
    } 


    /// <summary> 
    /// Included only because it must be implemented. 
    /// </summary> 
    /// <param name="methodInfo"></param> 
    /// <param name="attribute"></param> 
    /// <returns></returns> 
    public override object GetInitializer(LogicalMethodInfo methodInfo, 
              SoapExtensionAttribute attribute) 
    { 
     return null; 
    } 

    /// <summary> 
    /// Included only because it must be implemented. 
    /// </summary> 
    /// <param name="WebServiceType"></param> 
    /// <returns></returns> 
    public override object GetInitializer(Type WebServiceType) 
    { 
     return null; 
    } 

    /// <summary> 
    /// Included only because it must be implemented. 
    /// </summary> 
    /// <param name="initializer"></param> 
    public override void Initialize(object initializer) 
    { 
    } 


} 

然後,你需要註冊擴展:

RegisterSoapExtension(typeof(TraceExtension), 1, 0); 

最後,你的請求/響應完成後,您需要保存XML:

TraceExtension.XmlRequest.Save(@"c:\temp\ForwardRequest.xml"); 
TraceExtension.XmlResponse.Save(@"c:\temp\ForwardResponse{0}.xml"); 

警告:這是其實我差不多是通過UPS認證的,但是這個代碼只用過一次。因此,它可能並不是最好的質量,除了這一件事之外,還可以是漂亮的或者非常有用的。

0

對於那些像我一樣掙扎的人,如果您對Request和Respose都獲得Null,則需要在實例化ShipService之前註冊擴展。

TraceExtension.RegisterSoapExtension(typeof(TraceExtension),1,0); ShipService shpSvc = new ShipService();

希望這可以幫助某人:)