Web Services Practical Examples

Inria

Understanding Web Services with real world examples.

Web Services in action

Go to http://www.webservicex.net/

Name some Web Services available.

Go to the Stock Quote service.

What is the endpoint of this service ?

Go to the endpoint if the Stock Quote service.

How many operation are managed by this service ?

There is a single operation managed by the service, actually the GetQuote operation.

Check the operation in the WSDL service description.

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.webserviceX.NET/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.webserviceX.NET/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://www.webserviceX.NET/">
      <s:element name="GetQuote">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="symbol" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="GetQuoteResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="GetQuoteResult" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="string" nillable="true" type="s:string" />
    </s:schema>
  </wsdl:types>
  <wsdl:message name="GetQuoteSoapIn">
    <wsdl:part name="parameters" element="tns:GetQuote" />
  </wsdl:message>
  <wsdl:message name="GetQuoteSoapOut">
    <wsdl:part name="parameters" element="tns:GetQuoteResponse" />
  </wsdl:message>
  <wsdl:message name="GetQuoteHttpGetIn">
    <wsdl:part name="symbol" type="s:string" />
  </wsdl:message>
  <wsdl:message name="GetQuoteHttpGetOut">
    <wsdl:part name="Body" element="tns:string" />
  </wsdl:message>
  <wsdl:message name="GetQuoteHttpPostIn">
    <wsdl:part name="symbol" type="s:string" />
  </wsdl:message>
  <wsdl:message name="GetQuoteHttpPostOut">
    <wsdl:part name="Body" element="tns:string" />
  </wsdl:message>
  <wsdl:portType name="StockQuoteSoap">
    <wsdl:operation name="GetQuote">
      <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation>
      <wsdl:input message="tns:GetQuoteSoapIn" />
      <wsdl:output message="tns:GetQuoteSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:portType name="StockQuoteHttpGet">
    <wsdl:operation name="GetQuote">
      <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation>
      <wsdl:input message="tns:GetQuoteHttpGetIn" />
      <wsdl:output message="tns:GetQuoteHttpGetOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:portType name="StockQuoteHttpPost">
    <wsdl:operation name="GetQuote">
      <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation>
      <wsdl:input message="tns:GetQuoteHttpPostIn" />
      <wsdl:output message="tns:GetQuoteHttpPostOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="StockQuoteSoap" type="tns:StockQuoteSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="GetQuote">
      <soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="StockQuoteSoap12" type="tns:StockQuoteSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="GetQuote">
      <soap12:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="StockQuoteHttpGet" type="tns:StockQuoteHttpGet">
    <http:binding verb="GET" />
    <wsdl:operation name="GetQuote">
      <http:operation location="/GetQuote" />
      <wsdl:input>
        <http:urlEncoded />
      </wsdl:input>
      <wsdl:output>
        <mime:mimeXml part="Body" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="StockQuoteHttpPost" type="tns:StockQuoteHttpPost">
    <http:binding verb="POST" />
    <wsdl:operation name="GetQuote">
      <http:operation location="/GetQuote" />
      <wsdl:input>
        <mime:content type="application/x-www-form-urlencoded" />
      </wsdl:input>
      <wsdl:output>
        <mime:mimeXml part="Body" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="StockQuote">
    <wsdl:port name="StockQuoteSoap" binding="tns:StockQuoteSoap">
      <soap:address location="http://www.webservicex.net/stockquote.asmx" />
    </wsdl:port>
    <wsdl:port name="StockQuoteSoap12" binding="tns:StockQuoteSoap12">
      <soap12:address location="http://www.webservicex.net/stockquote.asmx" />
    </wsdl:port>
    <wsdl:port name="StockQuoteHttpGet" binding="tns:StockQuoteHttpGet">
      <http:address location="http://www.webservicex.net/stockquote.asmx" />
    </wsdl:port>
    <wsdl:port name="StockQuoteHttpPost" binding="tns:StockQuoteHttpPost">
      <http:address location="http://www.webservicex.net/stockquote.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

What are the available access method to this operation ?

This is defined in the <wsdl:binding> elements :

  1. SOAP over HTTP
  2. SOAP12 over HTTP
  3. HTTP GET
  4. HTTP POST

Do we have the same information when we examine the elements within the wsdl:service element ?

No, we can only see that 4 accesses are available :

  1. SOAP
  2. SOAP12
  3. HTTP for the 2 last ; we can infer from the names that the former is related to the GET method and the latter to the POST method but an engine can't.

Go to the GetQuote operation interface. Type "IBM" as symbol input. Check the XML result.

How is the content of the <string> element, XML or text content ?

It's text content, not XML although it looks like : all the content is escaped. However the entire string could be parsed to get a standalone XML document.

Explain why after submitting the previous form we didn't get a <soap:Envelope ? (displaying the HTML source of the form will help)

By editing the HTML source :

<form action='http://www.webservicex.net/stockquote.asmx/GetQuote' method="POST">
    <input type="text" size="50" name="symbol">
    <input type="submit" value="Invoke" class="button">
</form>

...we can see that the HTTP request that will be forged by the form will look like :

POST /stockquote.asmx/GetQuote HTTP/1.1
Host: www.webservicex.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

symbol=IBM

...which is bound to the HTTP POST binding :

<wsdl:binding name="StockQuoteHttpPost" type="tns:StockQuoteHttpPost">
    <http:binding verb="POST"/>
    <wsdl:operation name="GetQuote">
        <http:operation location="/GetQuote"/>
        <wsdl:input>
            <mime:content type="application/x-www-form-urlencoded"/>
        </wsdl:input>
        <wsdl:output>
            <mime:mimeXml part="Body"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

...that states that the payload is in the Body element, which is defined in the response message as a tns:string :

<wsdl:message name="GetQuoteHttpPostOut">
    <wsdl:part xmlns:tns="http://www.webserviceX.NET"
         name="Body" element="tns:string"/>
</wsdl:message>

...where this type is defined as an xsd:string

<xsd:schema elementFormDefault="qualified" targetNamespace="http://www.webserviceX.NET/">
    ...
    <xsd:element name="string" nillable="true" type="xsd:string"/>

(rewritten here for convenience)

Forge a SOAP query and submit it with telnet

$ telnet www.webservicex.net 80
Trying 173.201.44.188...
Connected to webservicex.net.
Escape character is '^]'.
POST /stockquote.asmx HTTP/1.1
Host: www.webservicex.net
Content-Type: text/xml; charset=utf-8
Content-Length: 260
SOAPAction: "http://www.webserviceX.NET/GetQuote"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>IBM</symbol>
    </GetQuote>
  </soap:Body>
</soap:Envelope>

Result :

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 997
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/7.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 09 Dec 2012 22:15:25 GMT

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetQuoteResponse xmlns="http://www.webserviceX.NET/">
            <GetQuoteResult>&lt;StockQuotes&gt;
                              &lt;Stock&gt;
                                &lt;Symbol&gt;IBM&lt;/Symbol&gt;
                                &lt;Last&gt;191.95&lt;/Last&gt;
                                &lt;Date&gt;12/7/2012&lt;/Date&gt;
                                &lt;Time&gt;4:00pm&lt;/Time&gt;
                                &lt;Change&gt;+2.25&lt;/Change&gt;
                                &lt;Open&gt;190.14&lt;/Open&gt;
                                &lt;High&gt;192.20&lt;/High&gt;
                                &lt;Low&gt;190.11&lt;/Low&gt;
                                &lt;Volume&gt;4091940&lt;/Volume&gt;
                                &lt;MktCap&gt;216.9B&lt;/MktCap&gt;
                                &lt;PreviousClose&gt;189.70&lt;/PreviousClose&gt;
                                &lt;PercentageChange&gt;+1.19%&lt;/PercentageChange&gt;
                                &lt;AnnRange&gt;177.35 - 211.79&lt;/AnnRange&gt;
                                &lt;Earns&gt;13.913&lt;/Earns&gt;
                                &lt;P-E&gt;13.63&lt;/P-E&gt;
                                &lt;Name&gt;International Bus&lt;/Name&gt;
                              &lt;/Stock&gt;
                            &lt;/StockQuotes&gt;
            </GetQuoteResult>
        </GetQuoteResponse>
    </soap:Body>
</soap:Envelope>

Help Troubleshooting

Got a HTTP/1.1 400 Bad Request with a body like this ?

<BODY><h2>Bad Request - Invalid Verb</h2>
<hr><p>HTTP Error 400. The request verb is invalid.</p>
</BODY>

This will occur if the Content-Length: 260 is wrong ; increase the value and fill the end of the request with then necessary blanks.