Peter
Peter

Reputation: 1796

create WSDL for specific SOAP request

I have to create a certain SOAP request message based on a WSDL file. I am using SOAP UI to create the SOAP request from the WSDL.

The SOAP request should look like this:

<?xml version="1.0"?>
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/"> 
<SOAP-ENV:Header>
    <username>xxxx</username>
    <password>xxxx</password>
    <MaxOrders>1</MaxOrders>
    <xmlVers>1</xmlVers>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
    <m:getNewOrders xmlns:m= "urn:https://xxx.yyy.co.uk/b2b/soap/soap:getNewOrders/">
    </m:getNewOrders>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I have the following WSDL:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions 
xmlns:m="https://xxx.yyy.co.uk/b2b/" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
name="xxxOrders" 
targetNamespace="https://xxx.yyy.co.uk/b2b/">
 <wsdl:types>
<xsd:schema targetNamespace="https://xxx.yyy.co.uk/b2b/">
  <xsd:element name="Envelope">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Header"/>
        <xsd:element name="Body"/>
      </xsd:sequence>
      <xsd:attribute name="encodingstyle" type="xsd:anyURI" form="qualified" use="required" />
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Header">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="username" type="xsd:NCName" form="unqualified" />
        <xsd:element name="password" type="xsd:integer" form="unqualified" />
        <xsd:element name="MaxOrders" type="xsd:integer" form="unqualified" />
        <xsd:element name="xmlVers" type="xsd:integer" form="unqualified" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Body">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="m:getNewOrders" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="getNewOrders">
    <xsd:complexType />
  </xsd:element>
</xsd:schema>
  </wsdl:types>

  <wsdl:message name="getNewOrders">
    <wsdl:part element="m:getNewOrders" name="parameters"/>
  </wsdl:message>


  <wsdl:portType name="xxxOrders">
    <wsdl:operation name="getNewOrders">
      <wsdl:input message="m:getNewOrders"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="xxxOrdersSOAP" type="m:xxxOrders">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getNewOrders">
      <soap:operation soapAction="urn:https://xxx.yyy.co.uk/b2b/soap/soap:getNewOrders/"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

  <wsdl:service name="xxxOrders">
    <wsdl:port binding="m:xxxOrdersSOAP" name="xxxOrdersSOAP">
      <soap:address location="https://xxx.yyy.co.uk/b2b/soap/soap_orders.asp"/>
    </wsdl:port>
  </wsdl:service>
 </wsdl:definitions>

But when I take that WSDL and import it in SOAP UI, the SOAP request message looks different from what I expect:

<soapenv:Envelope 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:b2b="https://xxx.yyy.co.uk/b2b/">
   <soapenv:Header/>
   <soapenv:Body>
      <b2b:getNewOrders/>
   </soapenv:Body>
</soapenv:Envelope>

My Header element is empty for example. The getNewOrders I think is okay because it is bound to xmlns:b2b so I do not need the namespace in the element getNewOrders. Am I correct?

Can please someone point out what I have to fix in the WSDL? I am lost.

Upvotes: 2

Views: 8177

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21638

You're ok with namespaces, the problem is that you didn't define the header part. Now, even if you do it, I wouldn't know if your tool will take into account... but definitely, in terms of interface definition this is what you must do.

Searching for "wsdl soap header example" or alike should yield many hits, such as this one.

The key points are:

  • your input part should define the part that is related to the header.
 <wsdl:message name="getNewOrders">
     <wsdl:part element="m:getNewOrders" name="parameters"/>
     <wsdl:part element="m:Header" name="header"/>
 </wsdl:message>
  • you need to bind that header part to the SOAP header
<wsdl:operation name="getNewOrders">
  <soap:operation soapAction="urn:https://xxx.yyy.co.uk/b2b/soap/soap:getNewOrders/"/>
 <wsdl:input name="getNewOrders">
   <wsdlsoap:header message="getNewOrders" part="header" use="literal"/>
   <wsdlsoap:body use="literal" parts="parameters"/>
 </wsdl:input>
  <wsdl:output>
    <soap:body use="literal"/>
  </wsdl:output>
</wsdl:operation>

Now, I haven't checked the prefixes (you should have a default namespace matching the targetNamespace of your WSDL for the above to work without prefixes, etc.) nor tried to rewrite the WSDL for you... but this is fundamentally how you specify the header: your input has multiple parts, which in SOAP one goes in the header, and the other in the body.

Upvotes: 2

Related Questions