12

WSDL and DISCO

 

DISCO

 

The discovery tool disco accepts the name of the asmx file. On executing the command, it creates three files in the folder, viz. a.disco, a.wsdl and results.discomap.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod()]

public string abc(string i , string  j)

{

return i+j;

}

}

 

>disco http://localhost/a.asmx

Microsoft (R) Web Services Discovery Utility

[Microsoft (R) .NET Framework, Version 1.0.2914.16]

Copyright (C) Microsoft Corp. 1998-2001. All rights reserved.

 

Disco found documents at the following URLs:

http://localhost/a.asmx?disco

http://localhost/a.asmx?wsdl

 

The following files hold the content found at the corresponding URLs:

  .\a.disco <- http://localhost/a.asmx?disco

  .\a.wsdl <- http://localhost/a.asmx?wsdl

The file .\results.discomap holds links to each of these files.

 

The a.wsdl file is fairly wieldy and has already been dealt with in one of the preceding chapters. Hence, we have not displayed it here. Alternatively, a .disco file can also be generated by specifying the URL of http://localhost/a.asmx?disco in the browser.

 

a.disco

<?xml version="1.0" encoding="utf-8"?>

<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns=" http://schemas.xmlsoap.org/disco/ ">

  <contractRef ref="http://localhost/a.asmx?wsdl" docRef="http://localhost/a.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />

  <soap address="http://localhost/a.asmx" xmlns:q1="http://tempuri.org/" binding="q1:zzzSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />

</discovery>

 

results.discomap

<?xml version="1.0" encoding="utf-8"?>

<DiscoveryClientResultsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <Results>

    < DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/a.asmx?wsdl" filename="a.wsdl" />

    <DiscoveryClientResult referenceType="System.Web.Services.Discovery.DiscoveryDocumentReference" url="http://localhost:8080/a.asmx?disco" filename="a.disco" />

  </Results>

</DiscoveryClientResultsFile>

 

The disco file is an XML document, which starts with a root element of discovery. The URI from where all the elements originate is http://schemas.xmlsoap.org/disco/. The contactRef element, along with its attributes, is of vital significance here. The ref attribute refers to the WSDL file, while the docRef attribute refers to the asmx file. The default namespace mutates to http://schemas.xmlsoap.org/disco/scl/.

 

The next element is soap, where the address attribute refers to the a.asmx file on the server, and the binding refers to zzzSoap. Using this binding, the WebService is located from within the WSDL file. The results.discomap file is also an XML document. Here, the root element is DiscoveryClientResultsFile, which is followed by the Results element. This is followed by two DiscoveryClientResult elements, which refer to the two files named a.wsdl and a.disco, which have been created by the DISCO program. The url attribute contains the url that creates these files.

 

This chapter shall now dissect the details of the WSDL specification thoroughly, which have not been touched upon, so far.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod()]

public string abc(string i , string  j)

{

return i+j;

}

}

 

aa.wsdl

<?xml version="1.0" encoding="utf-8"?>

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

<s:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/">

<s:element name="abc">

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="i" nillable="true" type="s:string" />

<s:element minOccurs="1" maxOccurs="1" name="j" nillable="true" type="s:string" />

</s:sequence>

</s:complexType>

</s:element>

<s:element name="string" nillable="true" type="s:string" />

</s:schema>

</types>

<message name="abcHttpPostIn">

<part name="i" type="s:string" />

<part name="j" type="s:string" />

</message>

<message name="abcHttpPostOut">

<part name="Body" element="s0:string" />

</message>

<portType name="zzzHttpPost">

<operation name="abc">

<input message="s0:abcHttpPostIn" />

<output message="s0:abcHttpPostOut" />

</operation>

</portType>

<binding name="zzzHttpPost" type="s0:zzzHttpPost">

<http:binding verb="POST" />

<operation name="abc">

<http:operation location="/abc" />

<input>

<mime:content type="application/x-www-form-urlencoded"/>

</input>

<output>

<mime:mimeXml part="Body" />

</output>

</operation>

</binding>

<service name="zzz">

<port binding="s0:zzzHttpPost">

<http:address location="http://localhost:8080/a.asmx" />

</port>

</service>

</definitions>

 

zzz.cs

using System.Diagnostics;

using System.Xml.Serialization;

using System;

using System.Web.Services.Protocols;

using System.Web.Services;

public class zzz :

System.Web.Services.Protocols.HttpPostClientProtocol

{

public zzz()

{

Url = "http://localhost:8080/a.asmx";

}

[System.Web.Services.P

rotocols.HttpMethodAttribute(typeof(System.Web.

Services.Protocols.XmlReturnReader), typeof(System.Web.Services.Protocols.HtmlFormParameterWriter))]

[return: System.Xml.Serialization.XmlRootAttribute("string", Namespace="http://tempuri.org/", IsNullable=true)]

public string abc(string i, string j)

{

return ((string)(this.Invoke("abc", (this.Url + "/abc"), new object[] {i,j})));

}

}

 

b.cs

public class aaa

{

public static void Main()

{

zzz a = new zzz();

string b = a.abc("hi","bye");

System.Console.WriteLine(b);

}

}

 

a.bat

WSDL /protocol:HttpPost aa.wsdl

Csc /t:library zzz.cs

Csc b.cs /r:zzz.dll

b

 

Formatted Trace

SOAP request

i=hi&j=bye

 

SOAP response

<?xml version="1.0" encoding="utf-8" ?>

<string xmlns="http://tempuri.org/">hibye</string>

 

Unformatted Trace

SOAP request

POST /a.asmx/abc HTTP/1.1

 

i=hi&j=bye

 

Output

Hibye

 

The asmx file has a function named abc, which takes two strings and returns a single string. Then, in the browser, we specify the URL as http://localhost/a.asmx?WSDL, which results in the generation of a wsdl file.

 

In the wsdl file seen above, we will lay emphasis only that portion which deals with a POST request. A POST request is different from a GET in one significant way. The parameters to a GET are passed in the URL, whereas in a POST, they are dispatched in a separate packet, after the headers have been sent across.

 

As always, the wsdl file begins with the definitions root tag.  This is followed by the element abc that is made up of two elements viz. i and j, which are the parameters to the function abc. The message abcHttpPostIn comprises of two parts, one each for the variables named i and j. The message abcHttpPostOut contains a single part called Body. The port type determines the messages that will be used for input and output.

 

In the binding, the verb in focus is POST, and not GET. The input element uses the content element from the mime namespace, which ensures that the parameters are sent across as URLencoded. The output element uses the mimeXml element, with Body as its part. The service element remains unaltered.

 

The client program is generated by running the wsdl program as:

 

WSDL /protocol:HttpPost aa.wsdl

 

Since we have opted for HttpPost, it is the class zzz that is now derived from the class HttpPostClientProtocol, instead of the default protocol option of SOAP.

 

The HttpMethodAttribute has two types: 

     XmlReturnReader

     HtmlFormParameterWriter.

 

These types establish the method by which, the data is received and dispatched. When data is sent over, the class or type of HtmlFormParameterWriter is used, whereas, it is the type of XmlReturnReader that is utilized, when the data is received. As usual, there is no help available on these classes.

 

The return: specifies that the return value will be encoded in the form of a simple string. Thus, if you examine the output, you will realize that it is a simple XML document, where the return value is enclosed within a string element. The request too is sent as a separate packet, since the verb is set to POST. Thus, we have divulged both, the formatted and unformatted outputs to you.

 

The wsdl program can generate a client for SOAP, GET and POST. By using the GET and POST verbs, any device other than a browser, can also be used to communicate with a web server, with the help of WSDL.

In the operation element, the location has to be a relative URI, since this value is merged with the location attribute of the address element. If we change a single line in the output element to the following:

 

<mime:content type="text/xml" />

 

an exception is thrown. This is due to the fact that the system does not anticipate the inclusion of an element string in the return packet. The content tag is employed to avoid defining a new element for every MIME format. This element is used in a situation where there is nothing more to convey about the format, except the MIME type.

 

Since only a single part is present, the part attribute is optional. A MIME type string has two portions, which are separated by a / symbol, such as- text/xml, image/gif. If no MIME type has been specified, it is an indication that we are contented and at ease with all of them. The mimeXml element is used, when the XML payload is not SOAP compliant. To be SOAP compliant, the root element must be Envelope. The payload that we receive, does not begin with the envelope tag. Hence, the element is indispensable.

 

The request received in the above POST has a schema, which is specified by the mimeXml element. The part attribute refers to a part called Body, which is created in the message element, and comprises of a simple string. The part attribute can be sidestepped completely, since only one part is present.

 

wsdl /server aa.wsdl

 

zzz.cs

using System.Diagnostics;

using System.Xml.Serialization;

using System;

using System.Web.Services.Protocols;

using System.Web.Services;

[System.Web.Services.WebServiceBindingAttribute(Name="zzzSoap", Namespace="http://tempuri.org/")]

public abstract class zzz : System.Web.Services.WebService

{

[System.Web.Services.WebMethodAttribute()]

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/abc", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public abstract string abc(string i, string j);

}

 

The last option of wsdl is server. It takes a wsdl file and generates an abstract class. This class is derived from WebService. As there is no code present in a WSDL file, the function abc is marked as abstract, in the zzz class.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod()]

public void abc()

{

}

}

 

After having removed the lines that are not required, aa.wsdl file looks like shown below.

 

aa.wsdl

<?xml version="1.0" encoding="utf-8"?>

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

<message name="m" />

<portType name="pt">

<operation name="abc">

<input message="s0:m" />

<output message="s0:m" />

</operation>

</portType>

<binding name="b1" type="s0:pt">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

<operation name="abc">

<soap:operation soapAction="http://tempuri.org/abc" />

<input>

<soap:body />

</input>

<output>

<soap:body/>

</output>

</operation>

</binding>

<service name="zzz">

<port binding="s0:b1">

<soap:address location="http://localhost:8080/a.asmx" />

</port>

</service>

</definitions>

 

b.cs

public class aaa

{

public static void Main()

{

zzz a = new zzz();

a.abc();

}

}

 

a.bat

del *.dll

del *.exe

wsdl aa.wsdl

csc /t:library zzz.cs

csc b.cs /r:zzz.dll

b

 

SOAP request

<soap:Body />

 

SOAP response

<soap:Body>

<abcResponse xmlns="http://tempuri.org/" />

</soap:Body>

 

Here, we encounter the smallest possible WSDL file, which neither sends nor receives any data from the server. Let us now tread over familiar territory, which we have covered in the past. We would also be scrutinizing the WSDL specifications exhaustively.

 

At the bottom of the aa.wsdl file, exists a service element named zzz. The address element from the soap namespace is optional. However, if it is omitted, the Url property does not get initialized. As a result, the client is unable to connect to any Web Service. If we remove the port element, the class in the .cs file assumes the name of b1, which is the name of the binding.

 

Also, the Url property does not get initialized. The binding contains all the essential information for WSDL. The service is merely one step ahead of the binding.

 

aa.wsdl

<service name="aaa">

<port binding="s0:b1">

<soap:address location="http://localhost:8080/a.asmx" />

</port>

</service>

</definitions>

 

zzz.cs

public class b1 : System.Web.Services.Protocols.SoapHttpClientProtocol {

 

public class b11 : System.Web.Services.Protocols.SoapHttpClientProtocol {

 

We now add one more service called aaa, to the end of the wsdl file. Multiple service elements are permissible in the WSDL file. This results in two classes in the client proxy, viz. b1 and b11. If we add one more service called bbb, the class b12 will get freshly added.

 

Each service element becomes a class in the proxy. However, the name of the service no more decides on the name of the class but the name of the binding.

 

aa.wsdl

<service name="zzz">

<port name="p1" binding="s0:b1">

<soap:address location="http://localhost:8080/a.asmx" />

</port>

<port name="p2" binding="s0:b1">

<soap:address location="http://localhost:8080/a.asmx" />

</port>

</service>

 

So far, we have been screaming hoarse from rooftops, that the service name determines the name of the class in the client proxy. However, in the case of multiple services, it is the name of the binding that determines the class name, irrespective of the fact that two ports exist within the same service, with both using the same binding. Legally, it is permissible to have different port names, such as p1 and p2. However, the two classes that get created in the zzz.cs file, would be b1 and b11. Thus, the real meat of the matter lies in the ports, and not in the service element.

 

Let us now attend to some general issues relating to WSDL. First of all, WSDL offers a binding for SOAP 1.1 endpoints. This is because, a major part of the WSDL specifications converges around SOAP. In a sense, the specifications of both, SOAP and WSDL, were developed simultaneously.

 

You would notice that a large number of elements in WSDL originate from the soap namespace. Therefore, there is a need to specify the address for a SOAP endpoint, as well as, the URI for the SOAPAction HTTP header.

 

The WSDL is required to betoken the fact that the binding that shall be used, would be the SOAP 1.1 protocol. The binding grammar is not exhaustive, since the SOAP specifications keep evolving on a continuous basis, thereby, resulting in amendments and enhancements to the WSDL specifications.

Let us now veer our focus on to the binding attribute from the soap namespace. It is mandatory for the element soap:binding to be present in the binding element, when a SOAP payload is sent across the wire. The duty of this element is to enforce the rules of the SOAP protocol, when the binding is created. In other words, the payload should contain the following : an Envelope, an optional Header and a Body.

 

The binding element is indifferent to the encoding or format types being used. It only accepts two attributes:

     Transport, which is a URI.

     Style, which is either document or rpc. The default is document.

 

The transport attribute establishes the transport protocol that would be used to carry the SOAP packet across. To this point, the http protocol was being used to serve this purpose. However, we can use the other transports, such as- the Simple Mail Transfer Protocol SMTP, or the File Transfer Protocol FTP. In the beta copy, if we replace http with ftp, WSDL reports an error. The client proxy projects the class as being derived from SoapHttpClientProtocol; thus, giving the impression that all is hunky-dory.

 

The operation element is akin to the binding element, wherein the same element name appears in both, in the wsdl space, as well as, in the soap space. This element refers to the soap operation as a complete entity. It has to be a child element within the operation element, and it accepts two attributes, viz. soapAction and style.

 

The soapAction attribute is the most important attribute, since the SOAPAction HTTP header derives its value from it. The value that is entered in this URI must be an absolute URI. This value is used as the first parameter to the attribute SoapDocumentMethodAttribute.

 

WSDL generates no errors at all, even in the eventuality of no value being supplied; instead, the value of the parameter to the attribute is set to 'null'. However, when we finally run the program, an exception is thrown, since the server fails to recognize the value of the header named SoapAction. Thus, a valid URI must be specified.

 

For SOAP protocol bindings other than HTTP, such as SMTP, a value cannot be specified. Hence, the operation element is optional.

 

Let us now progress onto the body element. This element is used twice, i.e. once each in the input and output elements. The body element specifies the appearance of the message parts inside the SOAP Body element. In all, four attributes can be used with it:

     Parts

     Use

     EncodingStyle

     Namespace

 

These attributes, along with the style attribute, will be analysed a little later in the chapter.

 

The last soap element is the address element. This element is employed to assign an address or a URI to a port. We cannot assign more than one address to the port that we wish to bind to. Moreover, the value or the address specified here, must correspond to the transport protocol that is in use. For example, if we are using the SMTP transport, the location should be an e-mail address.

 

After having dealt with the soap namespace elements, let us revert back to the smallest WSDL file again. A service merely groups the ports together. The name attribute is optional. If it is present, it determines the name of the class and the file. If it is absent, the name of the class becomes Item, while the name of the file becomes output.cs.

 

We cannot have more than one service, each without a name. Also, as reiterated earlier, multiple services can have multiple bindings, and each service can have multiple ports, subject to the port names being unique. The names of the bindings determine the names of the classes. The first service name is used for the name of the file. Multiple ports are permitted in a service, but these ports do not communicate with each other. Thus, we cannot state that the output of a port should become the input to another port.

 

 

If a service has ports that do not share a port type, and at the same time, they use different bindings or addresses, these ports are to be used as alternatives.

 

Once again, compared to the binding, the service and the port appear insignificant. This is because, the port defines an endpoint by stating a single address for the binding. The port element contains the attributes of name and binding. If there is only one port, then the name is optional, but the binding attribute is obligatory.  As per the WSDL specifications, a port cannot specify more than one address. However, if we do hold two address elements, only the first element that is encountered is put to use, and a warning is displayed. The only binding information that must be associated with a port is, an address or a URL. All the rest results in an error.

 

In our opinion, the binding element is one of the most crucial elements. The binding derives from a port type, and it specifies a protocol for transport. We can have more than one binding, derived from the same port type. Then, an operation is defined with the SoapAction header. This is followed by the actual input and output section.

 

A binding coalesces the message formats and the protocol for operations. All the above elements are inevitable and inescapable for a binding.

 

The binding element has a name, which is used by a service. It also has a type, which specifies a port type. If the name is omitted, the same set of rules that we explicated earlier, would be applicable. The type attribute is mandatory, since it introduces the port type details. The binding may also contain a fault element, which deals with faults, as the name itself suggests.

 

The element 'operation' that we place within a binding, specifies the binding information for an operation. The name assigned here must be the same, as the one specified for the operation that is created in the port type. It is incorrect to use different names for the operation in the binding and the port type. If more than one protocol is specified, a warning is issued.

 

Further, a binding is not authorised to specify any address information, since this is the sole prerogative of the port element.

 

A port type is arguably the key to unlocking the mysteries of WSDL. A binding derives from the port type. To define a port type in formal terms, it is a compendium of abstract collections and messages. The port type is normally assigned a name, since it can then be used in the binding element. The lone element that is worthy of being placed within the portType is, the operation element.

 

The operation element name must match with the name in the bindings element. Resorting to different names in each of the operation elements may result in whopping errors, as an outcome of which, the zzz.cs file may refuse to be written at all!

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod()]

public void abc()

{

}

[WebMethod()]

public void pqr()

{

}

}

 

aa.wsdl

<?xml version="1.0" encoding="utf-8"?>

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

<s:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/">

<s:element name="abc">

<s:complexType />

</s:element>

<s:element name="abcResponse">

<s:complexType />

</s:element>

<s:element name="pqr">

<s:complexType />

</s:element>

<s:element name="pqrResponse">

<s:complexType />

</s:element>

</s:schema>

</types>

<message name="abcSoapIn">

<part name="parameters" element="s0:abc" />

</message>

<message name="abcSoapOut">

<part name="parameters" element="s0:abcResponse" />

</message>

<message name="pqrSoapIn">

<part name="parameters" element="s0:pqr" />

</message>

<message name="pqrSoapOut">

<part name="parameters" element="s0:pqrResponse" />

</message>

<message name="abcHttpGetIn" />

<message name="abcHttpGetOut" />

<message name="pqrHttpGetIn" />

<message name="pqrHttpGetOut" />

<message name="abcHttpPostIn" />

<message name="abcHttpPostOut" />

<message name="pqrHttpPostIn" />

<message name="pqrHttpPostOut" />

<portType name="zzzSoap">

<operation name="abc">

<input message="s0:abcSoapIn" />

<output message="s0:abcSoapOut" />

</operation>

<operation name="pqr">

<input message="s0:pqrSoapIn" />

<output message="s0:pqrSoapOut" />

</operation>

</portType>

<portType name="zzzHttpGet">

<operation name="abc">

<input message="s0:abcHttpGetIn" />

<output message="s0:abcHttpGetOut" />

</operation>

<operation name="pqr">

<input message="s0:pqrHttpGetIn" />

<output message="s0:pqrHttpGetOut" />

</operation>

</portType>

<portType name="zzzHttpPost">

<operation name="abc">

<input message="s0:abcHttpPostIn" />

<output message="s0:abcHttpPostOut" />

</operation>

<operation name="pqr">

<input message="s0:pqrHttpPostIn" />

<output message="s0:pqrHttpPostOut" />

</operation>

</portType>

<binding name="zzzSoap" type="s0:zzzSoap">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

<operation name="abc">

<soap:operation soapAction="http://tempuri.org/abc" style="document" />

<input>

<soap:body use="literal" />

</input>

<output>

<soap:body use="literal" />

</output>

</operation>

<operation name="pqr">

<soap:operation soapAction="http://tempuri.org/pqr" style="document" />

<input>

<soap:body use="literal" />

</input>

<output>

<soap:body use="literal" />

</output>

</operation>

</binding>

<binding name="zzzHttpGet" type="s0:zzzHttpGet">

<http:binding verb="GET" />

<operation name="abc">

<http:operation location="/abc" />

<input>

<http:urlEncoded />

</input>

<output />

</operation>

<operation name="pqr">

<http:operation location="/pqr" />

<input>

<http:urlEncoded />

</input>

<output />

</operation>

</binding>

<binding name="zzzHttpPost" type="s0:zzzHttpPost">

<http:binding verb="POST" />

<operation name="abc">

<http:operation location="/abc" />

<input>

<mime:content type="application/x-www-form-urlencoded" />

</input>

<output />

</operation>

<operation name="pqr">

<http:operation location="/pqr" />

<input>

<mime:content type="application/x-www-form-urlencoded" />

</input>

<output />

</operation>

</binding>

<service name="zzz">

<port name="zzzSoap" binding="s0:zzzSoap">

<soap:address location="http://localhost/a.asmx" />

</port>

<port name="zzzHttpGet" binding="s0:zzzHttpGet">

<http:address location="http://localhost/a.asmx" />

</port>

<port name="zzzHttpPost" binding="s0:zzzHttpPost">

<http:address location="http://localhost/a.asmx" />

</port>

</service>

</definitions>

 

We now display two functions through our web service, in the asmx file. Let us cast the spotlight on the wsdl file, which is displayed exclusive of any modifications, to facilitate ameliorated understanding of it.

 

There are three different verbs that a wsdl file supports, viz. GET, POST and SOAP. We shall be expounding each one of the three verbs now.

 

First, we commence with the SOAP part of the WSDL file. The WSDL file has a 'types' section, which is independent of the method of access. These types may be employed by any of the verbs, and hence, are common to all. The types element is merely an XML schema, where different types are created, and which can be referred to by the elements. Since there are two functions in the asmx file, namely, abc and pqr, an element is also defined for every function that has been created. The element represents the parameters passed to the function. In our case, since the functions take no parameters, the elements are empty.

 

Functions return values. Therefore, an element that contains the name of function, followed by the word 'Response' is distinctly perceptible. This covers the explanation of the elements abcResponse and pqrResponse.

 

The service name is insouciant towards the number of functions. Hence, it refuses to change in any way. The binding now has two operations, named abc and pqr, with each representing the individual functions. Thus, a wsdl file can have a variety of operations, but the portType remains the same. Here, two operations called abc and pqr, are posited.

 

Like before, every operation consists of an input and output section. However, the difference here rests in the fact that, these input and output elements represent the parameters that are being sent and received, respectively. The input and output elements utilize the messages that are created in the file. This is for the reason that, the parameters and return values of each function vary.

 

In the case of a message, it is formed by utilising the individual elements, which are created in the file. This explicates the concept that forms the basis of the implementation of multiple functions in SOAP.

 

In the service element, there exist three individual port names that use a different binding, but share the same address element. The SOAP port uses the address element from the soap namespace, while GET and POST use it from the http namespace. This is where the concept of a service comes to prominence.

 

The same class zzz is generated, but it is derived from a different class. Hence, it uses a different binding. The binding for the verb POST, which is akin to SOAP, consists of two operations for the two functions, named abc and pqr. The rules of URL encoding are specified in the input, and since there is no output, the output element is bereft of all content.

 

The GET verb is similar to the POST verb. The only variation lies in the input, where it utilises the urlEncoded element, since the parameters in a GET are passed as part of the URL. However, they are encoded in much the same way, as is done in the POST.

 

The output element is empty, just like a POST. The port type structure is the same for GET and POST; but unlike SOAP, this element does not provide any useful information. This happens because, the messages that form its basis, are all empty. Thus, the message concept is more germane to the SOAP protocol, rather than to the GET or POST verbs.

 

Reverting back to the port type, a name attribute has to be specified here, since many ports will be created in the WSDL file. Each of these has to be uniquely identified.

 

For the next program, remove the pqr function and give a return value of 100 for the abc function.

 

a.asmx

public int abc() {

return 100;

}

 

The wsdl file has been created manually and represents a One-way operation. If you examine the file minutely, you would be able to discern the fact that there is no output element visible in either the port type, or in the binding.

 

aa.wsdl

<?xml version="1.0" encoding="utf-8"?>

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

<message name="m" />

<portType name="pt">

<operation name="abc">

<input message="s0:m" />

</operation>

</portType>

<binding name="b1" type="s0:pt">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

<operation name="abc">

<soap:operation soapAction="http://tempuri.org/abc" />

<input>

<soap:body />

</input>

</operation>

</binding>

<service name="zzz">

<port binding="s0:b1">

<soap:address location="http://localhost:8080/a.asmx" />

</port>

</service>

</definitions>

 

SOAP response

<abcResult>100</abcResult>

 

This is perfectly legal, as it signifies that a SOAP request is being sent over, although there would be no response at all. The server being privy to this manipulation, merrily sends back an answer. But, since it is a One-Way operation, the Invoke function disregards it completely.

 

The second operation is called a request-response operation. This is the most commonly used one, and it serves as a very vital foundation to a significant number of our programs in this book. This operation takes an input and an output element, along with the 'fault' element that is optional.

 

The fault element is used to specify a message format, over and above the protocol specifications. The request-response paradigm is implemented by the binding. The payload may be dispatched, either in a single communication, or in two independent ones.

 

There are two more transmission primitives that an endpoint can support:

     Solicit response, where the endpoint sends a message and then receives a message. This is different from a request response, where the endpoint receives a message and then sends a message.

     Notification, where the endpoint only sends a message. This is the reverse of the One-Way, where the end point just receives a message.

 

 

These primitives are called operations. The WSDL specification only defines One-Way and request-response primitives. Thus, we cannot demonstrate examples of the other two.

 

Now let us delve upon the concept of 'types', before moving on to the last major element named 'messages'. By using the 'types element', we can create our own custom made types and elements. Also, when parameters are passed to a function with return values, two elements get created.

 

The XSD or XML Schema type system is referred to, when 'types' are defined. They are eventually used in messages, irrespective of whether the payload is XML or not. Everything in the WSDL world can be extended, as a result of which, other type systems can be added.

 

As you would have realised, a WSDL file is capable of taking gargantuan dimensions. Hence, the specifications recommend that we break this file up into smaller documents. Thereafter, these smaller files can be coalesced into one large file, by using the import statement. The documentation element is used to add comments to the code in the WSDL file.

 

The first entity that we build in WSDL is a 'message' element. A message can consist of zero or more parts. A part is created from the 'type', which in itself is created in the 'types' section. The 'type', in turn, represents the parameters and return values. We may use either the 'element' or the 'type' attribute, to refer to elements or types created in the type section. Every message is assigned a name, since it would be referred to, in the port Type element.

 

The part element that describes the logical and abstract content of a message, can make an appearance more than once in a message. If we so desire, we may create a complexType in place of an element, and may even use the type in lieu of the element attribute.

 

A Message is an abstract definition of a message content. Finally, the message binding converts the abstract entity into something concrete.

 

Now, we shall acquaint you with various methods available for controlling the format of the SOAP messages, sent by a SOAP client to a server, and vise-versa.

 

The SOAP specification yearns simply for the SOAP message to be a valid XML document. However, it does not specify the encoding style that should be used. Thus, ASP.Net concedes to the use of different encoding styles, by providing a set of attributes. These attributes are then used to control the SOAP payload, by facilitating customization of every byte that is sent across.

 

Next, we zero in on customizing the SOAP packet sent by a Client. Subsequently, we shall be attending to the server end too.

 

Sections 5 and 7 of the SOAP specification, make a mention of two distinct encoding definitions. These give a detailed description of the manner in which the Body element should be formatted, and how the parameters within a method should be encoded. However, these encoding elements are not mandatory. The Asp.Net services support the requests and responses that ensue these two encodings.

 

Before we venture into creating our own web service, the one thing that needs circumspection is, the manner in which the XML within a SOAP request must be encoded, or formulated. The basic issue here is to decide whether the XML document should adhere to the XSD schema or to the rules of the SOAP specification. The advantage of using the encoding rules of the SOAP world is that they permit variations.

 

However, the server that handles the request, must also be equipped to handle all these variations. By employing an XSD schema, which is the default, we can be very explicit about what is being sent across.

 

The parameters and the return value form the bulk of a SOAP payload. The SOAP specifications subsist, mainly to define how the parameters and return values shall be sent across.

 

In the WSDL world, there are two encoding styles for parameters, viz. Encoded and Literal. Although we are aware of the fact that this has been discussed earlier, we are now toiling towards consolidating everything at one place. The style of Encoded encodes the parameters, using the SOAP specs, as stated in Section 5. On the other hand, Literal encodes the parameters using a predefined XSD schema. The Web Service must expect the parameters in the same format, as is sent by the client. Even if there is a very minor mismatch, the parameters shall not reach the final destination.

 

The enum of SoapBindingUse is used to specify an encoding, using the attribute SoapDocumentMethodAttribute.  Also, the parameters that dwell within the Body element, are encoded as self-containing XML documents, since they refer to an XSD schema. The Encoded parameter is specified by employing the same method, as has been outlined above. The encoding rules delineated in Section 5 are used here.  We are permitted to modify the overall formatting of the SOAP Body.

 

The WSDL standard describes two styles for operation. An operation is a Web Service method, which can be formatted within the Body element. This does not refer to the optional Header element. The two styles are RPC and Document, where Document is the default style. The Document style uses the XSD schema for encoding, whereas, the RPC style makes use of the SOAP specification.

 

In the RPC style, all the parameters are placed within a single element, after the name of the remoted function has been called. Each child element that is placed below the method name, is a parameter to the function with the same name. Alternatively, the Document style specifies or defines XSD schemas, using the WSDL file. The clients and servers expect the packets to cohere to these schemas. The actual code that represents these coding styles, has already been revealed earlier. The SoapRpcMethodAttribute is used for the Rpc encoding.

 

The parameters to a function can reside within the Body element in two ways. They can either reside within their own element, or they can be lodged within one element. The RPC style wraps the parameters within one element, whereas, the Document encoding is much more flexible. All the parameters can be wrapped within one element, and a default namespace can be created for these parameters.

The benefit of this is, the size of the SOAP payload contracts, since the XML files are always bulkier than the native data.

 

To accomplish this, the Parameter style is set to Wrapped, and the encoding is set to Literal. By changing the ParameterStyle to Bare, we can ensure that the parameters are directly beneath the Body element.

 

A namespace cannot be specified in an element that wraps parameters. Thus, each parameter must be specified individually, for all the parameters and return values.

 

To realize this, an XmlElementAttribute is added, and then, the Namespace property is set. The word 'return' that ends with a colon (as seen earlier), is of considerable significance here. The return value is the name of the web service, followed by the word 'Result'. The WebService method on the server must define an encoding style that corresponds to the client, by using the same attributes.

 

The System.Xml.Serialization namespace contains the attributes, which can be used to change the SOAP payload, which gets sent across. The XmlElementAttribute is used to amend the name of the parameter that goes across. However, if the RPC method is implemented, the SoapElement attribute has to be used.

 

In the WSDL specifications, the style attribute indicates whether the operation or function is RPC or document. In a RPC style, the messages contain parameters and return values; whereas, in the document style, the message contains documents. The soap:binding element determines the style, where the default is document, and the 'use' attribute specifies either 'encoded' or 'literal'. This value is then employed by WSDL, to determine the attributes that are to be used while generating the proxy.