Article

From:
To:
All
Subject:
Errors in generated SOAP packet with Arrays
Newsgroup:
embarcadero.public.delphi.webservices

Errors in generated SOAP packet with Arrays

Hello

(Warning, long post) I am trying to use the Fedex Address Verification v2 WSDL in a D2005 program (w/D2007 WSDLImp update) and the SOAP packet that is being generated is not correct.

Service is expecting (in simplest form):
<m:AddressesToValidate>    <m:Address>      <m:StreetLines>475 PARK AVE S FL 11</m:StreetLines>      <m:City>NEW YORK</m:City>      <m:StateOrProvinceCode>NY</m:StateOrProvinceCode>      <m:PostalCode>10016</m:PostalCode>      <m:CountryCode>US</m:CountryCode>    </m:Address> </m:AddressesToValidate>
Delphi is generating:
<AddressesToValidate>    <AddressToValidate>      <Address>        <StreetLines>          <string>2551 SW RIVIERA RD</string>        </StreetLines>        <City>STUART</City>        <StateOrProvinceCode>FL</StateOrProvinceCode>        <PostalCode>34997</PostalCode>        <CountryCode>US</CountryCode>        <Residential>false</Residential>      </Address>    </AddressToValidate> </AddressesToValidate>
There are 3 problems:
1) The extra <AddressToValidate>...</AddressToValidate> element
2) The extra <string>...</string> element
3) <Residential>false</Residential> is an optional element but if I leave out assigning it a value in the program, it gets added as an attribute to the <Address> element: <Address Residential="False">...
Excerpts from WSDL
   <xs:complexType name="AddressValidationRequest">      <xs:sequence> ... .. more elements ...
<xs:element name="AddressesToValidate" type="ns:AddressToValidate" maxOccurs="100"/>
     </xs:sequence>
   </xs:complexType>
...
...
   <xs:complexType name="AddressToValidate">
     <xs:sequence>
       <xs:element name="AddressId" type="xs:string" minOccurs="0"/>
       <xs:element name="CompanyName" type="xs:string" minOccurs="0"/>
       <xs:element name="Address" type="ns:Address"/>
     </xs:sequence>
   </xs:complexType>
...
...
   <xs:complexType name="Address">
     <xs:annotation>
<xs:documentation>The descriptive data for a physical location.</xs:documentation>
     </xs:annotation>
     <xs:sequence>
<xs:element name="StreetLines" type="xs:string" minOccurs="0" maxOccurs="4">
         <xs:annotation>
<xs:documentation>Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included.</xs:documentation>
           <xs:appinfo>              <xs:MaxLength>35</xs:MaxLength>            </xs:appinfo>
         </xs:annotation>
	</xs:element>
       <xs:element name="City" type="xs:string" minOccurs="0">
         <xs:annotation>
           <xs:documentation>Name of city, town, etc.</xs:documentation>
           <xs:appinfo>
             <xs:MaxLength>
               <ns:Express>35</ns:Express>
               <ns:Ground>20</ns:Ground>
             </xs:MaxLength>
           </xs:appinfo>
         </xs:annotation>
       </xs:element>
...
.. more elements
...
       <xs:element name="Residential" type="xs:boolean" minOccurs="0">
         <xs:annotation>
<xs:documentation>Indicates whether this address is residential (as opposed to commercial).</xs:documentation>
         </xs:annotation>
       </xs:element>
     </xs:sequence>
   </xs:complexType>


Excerpts from WSDLImp generated unit (generated with default options):
... ...
AddressToValidate = class; { "http://fedex.com/ws/addressvalidation/v2"[GblCplx] }
...
AddressValidationRequest = class; { "http://fedex.com/ws/addressvalidation/v2"[Lit][GblCplx] }
...
Address = class; { "http://fedex.com/ws/addressvalidation/v2"[GblCplx] }
...
...
...
// ************************************************************************ //
   // XML       : AddressToValidate, global, <complexType>
   // Namespace : http://fedex.com/ws/addressvalidation/v2
// ************************************************************************ //
   AddressToValidate = class(TRemotable)
   private
     FAddressId: WideString;
     FAddressId_Specified: boolean;
     FCompanyName: WideString;
     FCompanyName_Specified: boolean;
     FAddress: Address;
     procedure SetAddressId(Index: Integer; const AWideString: WideString);
     function  AddressId_Specified(Index: Integer): boolean;
     procedure SetCompanyName(Index: Integer; const AWideString: WideString);
     function  CompanyName_Specified(Index: Integer): boolean;
   public
     destructor Destroy; override;
   published
property AddressId: WideString Index (IS_OPTN) read FAddressId write SetAddressId stored AddressId_Specified; property CompanyName: WideString Index (IS_OPTN) read FCompanyName write SetCompanyName stored CompanyName_Specified;
     property Address: Address read FAddress write FAddress;
   end;
...
...
Array_Of_AddressToValidate = array of AddressToValidate; { "http://fedex.com/ws/addressvalidation/v2"[GblUbnd] }


// ************************************************************************ //
   // XML : AddressValidationRequest, global, <complexType>    // Namespace : http://fedex.com/ws/addressvalidation/v2
   // Serializtn: [xoLiteralParam]
   // Info      : Wrapper
// ************************************************************************ //
   AddressValidationRequest = class(TRemotable)
   private
     FWebAuthenticationDetail: WebAuthenticationDetail;
     FClientDetail: ClientDetail;
     FTransactionDetail: TransactionDetail;
     FTransactionDetail_Specified: boolean;
     FVersion: VersionId;
     FRequestTimestamp: TXSDateTime;
     FOptions: AddressValidationOptions;
     FAddressesToValidate: Array_Of_AddressToValidate;
procedure SetTransactionDetail(Index: Integer; const ATransactionDetail: TransactionDetail);
     function TransactionDetail_Specified(Index: Integer): boolean;
   public
     constructor Create; override;
     destructor Destroy; override;
   published
property WebAuthenticationDetail: WebAuthenticationDetail read FWebAuthenticationDetail write FWebAuthenticationDetail; property ClientDetail: ClientDetail read FClientDetail write FClientDetail; property TransactionDetail: TransactionDetail Index (IS_OPTN) read FTransactionDetail write SetTransactionDetail stored TransactionDetail_Specified; property Version: VersionId read FVersion write FVersion; property RequestTimestamp: TXSDateTime read FRequestTimestamp write FRequestTimestamp; property Options: AddressValidationOptions read FOptions write FOptions; property AddressesToValidate: Array_Of_AddressToValidate Index (IS_UNBD) read FAddressesToValidate write FAddressesToValidate;
   end;
...
...
...
Array_Of_string = array of WideString; { "http://www.w3.org/2001/XMLSchema"[GblUbnd] }


// ************************************************************************ //
   // XML       : Address, global, <complexType>
   // Namespace : http://fedex.com/ws/addressvalidation/v2
// ************************************************************************ //
   Address = class(TRemotable)
   private
     FStreetLines: Array_Of_string;
     FStreetLines_Specified: boolean;
     FCity: WideString;
     FCity_Specified: boolean;
     FStateOrProvinceCode: WideString;
     FStateOrProvinceCode_Specified: boolean;
     FPostalCode: WideString;
     FPostalCode_Specified: boolean;
     FUrbanizationCode: WideString;
     FUrbanizationCode_Specified: boolean;
     FCountryCode: WideString;
     FCountryCode_Specified: boolean;
     FResidential: Boolean;
     FResidential_Specified: boolean;
procedure SetStreetLines(Index: Integer; const AArray_Of_string: Array_Of_string);
     function StreetLines_Specified(Index: Integer): boolean;      procedure SetCity(Index: Integer; const AWideString: WideString);
     function  City_Specified(Index: Integer): boolean;
procedure SetStateOrProvinceCode(Index: Integer; const AWideString: WideString);
     function StateOrProvinceCode_Specified(Index: Integer): boolean;      procedure SetPostalCode(Index: Integer; const AWideString: WideString);      function PostalCode_Specified(Index: Integer): boolean;
procedure SetUrbanizationCode(Index: Integer; const AWideString: WideString);
     function UrbanizationCode_Specified(Index: Integer): boolean;      procedure SetCountryCode(Index: Integer; const AWideString: WideString);      function CountryCode_Specified(Index: Integer): boolean;      procedure SetResidential(Index: Integer; const ABoolean: Boolean);      function Residential_Specified(Index: Integer): boolean;
   published
property StreetLines: Array_Of_string Index (IS_OPTN or IS_UNBD) read FStreetLines write SetStreetLines stored StreetLines_Specified; property City: WideString Index (IS_OPTN) read FCity write SetCity stored City_Specified; property StateOrProvinceCode: WideString Index (IS_OPTN) read FStateOrProvinceCode write SetStateOrProvinceCode stored StateOrProvinceCode_Specified; property PostalCode: WideString Index (IS_OPTN) read FPostalCode write SetPostalCode stored PostalCode_Specified; property UrbanizationCode: WideString Index (IS_OPTN) read FUrbanizationCode write SetUrbanizationCode stored UrbanizationCode_Specified; property CountryCode: WideString Index (IS_OPTN) read FCountryCode write SetCountryCode stored CountryCode_Specified; property Residential: Boolean Index (IS_OPTN) read FResidential write SetResidential stored Residential_Specified;
   end;
...
...
initialization
InvRegistry.RegisterInterface(TypeInfo(AddressValidationPortType), 'http://fedex.com/ws/addressvalidation/v2', 'UTF-8'); InvRegistry.RegisterDefaultSOAPAction(TypeInfo(AddressValidationPortType), 'addressValidation'); InvRegistry.RegisterInvokeOptions(TypeInfo(AddressValidationPortType), ioDocument); InvRegistry.RegisterInvokeOptions(TypeInfo(AddressValidationPortType), ioLiteral);
...
RemClassRegistry.RegisterXSClass(AddressToValidate, 'http://fedex.com/ws/addressvalidation/v2', 'AddressToValidate');
...
RemClassRegistry.RegisterXSInfo(TypeInfo(Array_Of_AddressToValidate), 'http://fedex.com/ws/addressvalidation/v2', 'Array_Of_AddressToValidate'); RemClassRegistry.RegisterXSClass(AddressValidationRequest, 'http://fedex.com/ws/addressvalidation/v2', 'AddressValidationRequest'); RemClassRegistry.RegisterSerializeOptions(AddressValidationRequest, [xoLiteralParam]); RemClassRegistry.RegisterXSClass(AddressValidationRequest2, 'http://fedex.com/ws/addressvalidation/v2', 'AddressValidationRequest2', 'AddressValidationRequest');
...
RemClassRegistry.RegisterXSInfo(TypeInfo(Array_Of_string), 'http://www.w3.org/2001/XMLSchema', 'Array_Of_string'); RemClassRegistry.RegisterXSClass(Address, 'http://fedex.com/ws/addressvalidation/v2', 'Address');


My Questions are:

1) I can see why the extra elements in the SOAP packet are generated the way they are from Delphi code. Is the code generated by WSDLImp wrong in this case? Is there an option I should have specified to get the 'correct' Delphi code?
2) Why is the 'Residential' element showing up as an attribute to the <Address> element when I do not assign it a value in code? Do I have to assign it a value of Nil instead?
3) While testing this, I tried to modify the outgoing packet before it was sent to Fedex by removing the extra elements. The SOAP packet in this case never even made it to Fedex. It appears that the outgoing packet is being validated against the WSDL (generated code) before it gets sent and I was getting the following error.
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">    <soapenv:Header/>    <soapenv:Body>      <soapenv:Fault>        <faultcode>soapenv:Client</faultcode>
<faultstring>Failure while unmarshalling message: Failed to parse XML text</faultstring>
       <detail>
         <con:fault xmlns:con="http://www.bea.com/wli/sb/context">
           <con:errorCode>9999</con:errorCode>
<con:reason>Failure while unmarshalling message: Failed to parse XML text</con:reason>
         </con:fault>
       </detail>
     </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

What is generating this response (it did not seem to be Fedex)? Is there a way to turn off this 'validation' so that my modified SOAP packet can get to Fedex?
Thanks in advance to anyone that can help me with this. I haven't even got to the response packets from this which have a lot of these same 'Array' structures in it.
David Plock
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Thu, 28 Mar 2024 10:23:54 UTC
Copyright © 2009-2024
HREF Tools Corp.