2

Web Services Description Language (WSDL)

 

A WSDL file enjoys the look and feel of an XML document, since it actually is an XML document. Therefore, all the rules of XML apply to it too.

 

This chapter is an extension of the previous chapter. Hence, the asmx file remains the same. We have displayed the asmx file below. All that the file contains is, a single function named abc.

 

a.asmx

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

using System.Web.Services;

public class zzz

{

[WebMethod]

public int abc(int i, int j)

{

return i + j;

}

}

 

Create a new folder named aaa, and run the following command in it :

 

>Wsdl http://localhost/a.asmx?WSDL

This creates a file called zzz.cs. Compile the C# file to a dll, using the following csc command:

 

Csc /t:library zzz.cs

 

Next, create one more program called a.cs, in the folder aaa.

 

a.cs

public class aaa

{

public static void Main()

{

zzz a = new zzz();

int b;

b = a.abc(10,21);

System.Console.WriteLine(b);

}

}

 

Compile it using Csc a.cs /r:zzz.dll . On running the exe file a, an output of 31 is obtained. In a single stroke, the WSDL program has effortlessly replicated all that we had achieved with so much hard work in the previous chapter. In the zzz.cs file, it creates a class named zzz, which includes one function called abc. This function contains code, which calls the abc function from the file a.asmx.

 

Let us take a sneak preview of the code generated by the WSDL program, and discover  what goes on behind the scenes.

 

zzz.cs

//------------------------------------------------------------------------------

// <autogenerated>

// This code was generated by a tool.

// Runtime Version: 1.0.2914.16

//

// Changes to this file may cause incorrect behavior and will be lost if

// the code is regenerated.

// </autogenerated>

//------------------------------------------------------------------------------

 

//

// This source code was auto-generated by wsdl, Version=1.0.2914.16.

//

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 class zzz : System.Web.Services.Protocols.SoapHttpClientProtocol {

[System.Diagnostics.DebuggerStepThroughAttribute()]

public zzz() {

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

}

[System.Diagnostics.DebuggerStepThroughAttribute()]

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

 public int abc(int i, int j) {

object[] results = this.Invoke("abc", new object[] {

i, j});

return ((int)(results[0]));

}

 

[System.Diagnostics.DebuggerStepThroughAttribute()]

public System.IAsyncResult Beginabc(int i, int j, System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("abc", new object[] {

i,j}, callback, asyncState);

}

 

[System.Diagnostics.DebuggerStepThroughAttribute()]

public int Endabc(System.IAsyncResult asyncResult) {

object[] results = this.EndInvoke(asyncResult);

return ((int)(results[0]));

}

}

 

The cat is out of the bag! While attempting to learn about web services, we had made use of this approach. After understanding the process of calling code from a remote server, we have displaced the irrelevant parts from the program, thus, condensing and simplifying it, before finally presenting it to you. The code that is displayed above, was used in the previous chapter, while elucidating the basics of web services.

 

Let us probe a little deeper to figure out the program generated by the WSDL program. The parameter supplied to the WSDL command is http://localhost/a.asmx?WSDL.

 

There is an unyielding rule that whenever any program generates a file, the opening lines in the file, must be a set of comments. So, the file zzz.cs hits the road with these mandatory comments. Its the 'using' statements for the namespaces, which follow these comments.

The class zzz has the attribute of WebServiceBindingAttribute, which we encounter for the first time. The responsibility of this attribute is to denote a class containing one or more WebService methods. The 'name' property in the attribute is the name of the binding given in the format of a colon, followed by the name of the class, and finally, followed by the word 'soap'. However, this is only optional.

 

The class zzz is derived from the SoapHttpClientProtocol class. The class is known as zzz, since the file is named zzz.cs; furthermore, the file is named zzz.cs, because the WebService directive in the asmx file is initialized to zzz.

 

All the functions, together with the constructor, contain the attribute named DebuggerStepThroughAttribute. This attribute, as the name itself suggests, is brought into play for diagnostics or for the purpose of debugging. It is also optional. In the constructor, the Url property is initialized to the asmx file, accompanied by the server name on which it is located.

 

Not only does the function abc in zzz.cs, have the same return value as the function in the asmx file, but also has the same parameter names. The Invoke function is called in the same manner, as was done previously.

 

As was pointed out earlier, the code in the previous chapter was cut, copied and pasted from the proxy generated by the WSDL program.

 

There are two more functions in the .cs file named Beginabc and Endabc. These two functions were not encountered earlier, since they are utilized only when the abc function is to be executed in an asynchronous manner.

 

When the call is synchronous, as was the case in the previous chapter, the program execution pauses and ceases until the call ends. On the other hand, in an asynchronous execution, the function gets executed and there is a wait, but when it is all done with, the Endabc function gets called. The mechanism of the asynchronous execution shall be touched upon a little later in the book. You would appreciate that the program-generated code can never look appealing!!

 

Let us now understand the parameter passed to the WSDL program. Enter the same url of  http://localhost/a.asmx?WSDL in a browser.

 

On doing so, an XML file gets displayed in the browser window.  Create a new folder wsdl and save the contents to a text file named aa.wsdl within it. Then, enter the following command:

 

Wsdl aa.wsdl

 

The command generates the same zzz.cs file, which when compiled to a dll, generates the same output. Let us now unveil the magic of the aa.wsdl file.

 

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" type="s:int" />

<s:element minOccurs="1" maxOccurs="1" name="j" type="s:int" />

</s:sequence>

</s:complexType>

</s:element>

<s:element name="abcResponse">

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="abcResult" type="s:int" />

</s:sequence>

</s:complexType>

</s:element>

<s:element name="int" type="s:int" />

</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="abcHttpGetIn">

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

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

</message>

<message name="abcHttpGetOut">

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

</message>

<message name="abcHttpPostIn">

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

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

</message>

<message name="abcHttpPostOut">

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

</message>

<portType name="zzzSoap">

<operation name="abc">

<input message="s0:abcSoapIn" />

<output message="s0:abcSoapOut" />

</operation>

</portType>

<portType name="zzzHttpGet">

<operation name="abc">

<input message="s0:abcHttpGetIn" />

<output message="s0:abcHttpGetOut" />

</operation>

</portType>

<portType name="zzzHttpPost">

<operation name="abc">

<input message="s0:abcHttpPostIn" />

<output message="s0:abcHttpPostOut" />

</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>

</binding>

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

<http:binding verb="GET" />

<operation name="abc">

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

<input>

<http:urlEncoded />

</input>

<output>

<mime:mimeXml part="Body" />

</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>

<mime:mimeXml part="Body" />

</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>

 

The hitch that occurs while attempting to comprehend the above xml file, can be attributed to the gargantuan size of the file. So, we have stripped it of all superfluous portions, and arrived at a compact file, as is revealed below:

 

aa.wsdl

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

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema" 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" type="s:int" />

<s:element minOccurs="1" maxOccurs="1" name="j" type="s:int" />

</s:sequence>

</s:complexType>

</s:element>

<s:element name="abcResponse">

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="abcResult" type="s:int" />

</s:sequence>

</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>

<portType name="zzzSoap">

<operation name="abc">

<input message="s0:abcSoapIn" />

<output message="s0:abcSoapOut" />

</operation>

</portType>

<binding name="zzzSoap1" 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>

</binding>

<service name="zzz">

<port name="zzzSoap2" binding="s0:zzzSoap1">

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

</port>

</service>

</definitions>

 

Akin to an XML document, which mandates the presence of an xml declaration with the version attribute on the first line, the WSDL file too has the need for the same. However, the encoding attribute is optional. Since every XML document has to have a root element or a starting tag, the WSDL also has one. The tag is called 'definitions'.

 

The tag named 'definitions' cannot be altered to anything else. Moreover, there cannot be more than one occurrence of it, since there can only be just one, and only one root tag. The root element can possess a large number of namespace declarations, with the use of the attribute of xmlns.

 

People have penned down volumes on the topic of 'namespaces', right from the time that programming came into vogue. However at the end of the day, all that a namespace is worthy of is that, it ensures that tags created by one, do not clash with the tags created by the other. That is all there is to namespaces, i.e. providing each tag with its own space, by prefacing each of them with its namespace name.  Altogether, five namespaces are created in the root tag.

 

<definitions xmlns:s="http://www.w3.org/2001/XMLSchema" 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/">

 

The first namespace is named as s. It points to a URI that represents XML Schemas. XML Schemas are merely XML specifications that ascertain whether the XML document follows the laid down specifications or not. There is more to it than just specifications, but for the moment, it would suffice to say that the rules are prescribed in the specifications. Thus, any element that starts with the namespace 's' followed by a colon, belongs to the XML Schema namespace. Normally, the namespace prefix used is 'xsd', but the name of the prefix is not as significant as its value.

 

The elements beginning with 'soap' and 'soapenc' belong to the SOAP namespace. Here, s0 is the namespace used for the entities, which are created to represent our asmx file. One essential point to be taken into account is that, the wsdl file is created by IIS from the asmx file. Therefore, everything in this file represents the asmx file. Also, it is the wsdl file and not the asmx file, which is used by the WSDL program to create the proxy. The targetNamespace also points to the soap world. The default namespace specified by the xmlns attribute, applies to all those elements that are without a namespace prefix.

 

The root tag of 'definitions' contains six different types of child elements. On the top of the list is 'types', which renders assistance in creating types and elements. A 'type' is akin to a data type, while an 'element' is analogous to a tag. In the SOAP payload, you may have noticed the use of elements, such as abc and abcResponse. Now, someone somewhere has to create these elements. The WSDL file is designated to accomplish this task.

 

The child element of 'types' begins with the schema element from the XML Schema namespace, as it is prefaced with the namespace prefix s. This schema element is the root tag for any schema file. The targetNamespace attribute is also mentioned in the definitions element.

 

<types>

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

 

All elements in this schema belong to the targetNamespace URI, which is tempuri.org. The elementFormDefault attribute can have only two values, viz. qualified and unqualified, with the default value being 'unqualified'. The value qualified merely signifies that all elements from the targetNamespace must be qualified with the namespace prefix. The attributeFormDefault endorses a concept similar to that of the attributes. What follows thereafter, upto the closing schema element, is merely an XML Schema document.

 

To all those of you who have perused our book on XML Schemas, some of these explanations may appear monotonously reiterative, but a second explanation would surely not peeve anyone. For those of you who find it challenging to grapple with XML Schemas, there is a silver lining, as we shall endeavor to bring in the entire update to you shortly.

 

The SOAP payload reflects an element called abc. Let us perceive as to how and where the element has been created in the file.

 

To create an element, the 'name' attribute is used, and then assigned a value. Once the element is created, a type is specified for it.

 

<s:element name="abc">

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="i" type="s:int" />

<s:element minOccurs="1" maxOccurs="1" name="j" type="s:int" />

</s:sequence>

</s:complexType>

</s:element>

 

The trouble with an element is that, it can either contain other elements or only content and attributes. This element has been assigned a complexType, but if it were a simple element, we could have used simpleType in lieu. The next task is to define the complexity of the type. There is a sequence tag that maintains an order. This tag in turn, defines two more elements named i and j.

 

The elements i and j are child elements within the abc element. A great deal of significance is attached to the order in which they are placed.

 

The minOccurs in the element signifies the minimum number of times that the element can occur, whereas, maxOccurs refers to the maximum number of occurrences. Since both these attributes have the value of 1, it indicates that the element should be used only once.

 

Had the maxOccurs attribute been assigned a value of 3, and the minOccurs attribute was assigned the value of 1, the element then could have been used, only upto a maximum of three times.

 

There is a newly introduced attribute of 'type' with the element, which was not to be seen with the abc element. In the case of the type of the element being simple (as is the case with a predefined type of the XML Schema world, like int or string), you need to use the type attribute instead.  Thus, the parameters i and j of the function, belong to the type int. The variables do not need the complexType element. All parameters supplied to the abc function shall be placed here.

 

The second element created in the file is the abcResponse element. This element is visible in the SOAP response. There is only a single child element called abcResult of type of int, since the return value is an int.

 

This wraps up the elucidation of schema and types elements, as there are only two elements presently available in the SOAP payload. The information has been gleaned from the function prototype. Therefore, the code of the functions is of no significance here. Had you even attempted to add or subtract code from the asmx file, the WSDL file would still remain unaltered.

 

The message element, in a very abstract sense, refers to the content of the messages that are to be sent. Normally, an entity is assigned a name, if it is to be reused.

 

<message name="abcSoapIn">

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

</message>

<message name="abcSoapOut">

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

</message>

 

Two messages called abcSoapIn and abcSoapOut are created in the file. These names have been formed using a simple algorithm:

     It begins with the function name.

     It is followed by the reserved word 'soap'.

     Then, depending upon whether it is a request or a response packet, the words 'In' or 'Out' are used, respectively.

 

The content for the message is specified using the 'part' child element. The name 'parameters' has been assigned, since we are dealing with the parameters passed to a function. In any case, no other name is permitted.

 

The element attribute defines the type of the message. Specifying s0:abc as the value, would result in the SOAP request format being assigned to the element.  Thus, the SOAP request will contain the element abc, having two children, i and j, which are the parameters that the function abc requires. This is how the elements created earlier in the file, are re-used. The same is true for the message named absSoapOut, which represents the SOAP response message.

 

Now, we move on to the third element called portType.

 

<portType name="zzzSoap">

<operation name="abc">

<input message="s0:abcSoapIn" />

<output message="s0:abcSoapOut" />

</operation>

</portType>

 

A portType consolidates the operations that are to be performed on the defined messages. Our portType is assigned the name of zzzSoap, which is formed by conjoining the name of the class as specified in the asmx file (i.e. zzz), and the word Soap.

 

The element 'operation' within the portType tag, has a name attribute initialized to 'abc'. Incidentally, 'abc' also happens to be the name of the function that we want to execute remotely.

 

An operation element embodies an input and an output message.  You may recall that we had recently encountered two messages called abcSoapIn and abcSoapOut, which are used as the request and response messages, respectively. The portType element classifies the messages that are created, as either input or output.

 

The next element is the binding element called zzzSoap1.

 

<binding name="zzzSoap1" 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>

</binding>

 

The original WSDL file is termed as the binding zzzSoap, but we modified it to zzzSoap1, since there already exists a portType named zzzSoap.

 

The type attribute is the name of a portType, zzzSoap. From what we have encountered so far, a binding specifies an operation abc, with the 'input' and the 'output' message types. The binding element that follows, originates from the soap namespace, and is different from the parent binding, which emanates from the default namespace.

 

The transport attribute in the binding element refers to the protocol that will carry the SOAP payload. We have opted for the http protocol as our transport. However, nothing earth-shaking would ensue if the protocol of FTP or SMTP were used instead. The 'style' attribute has been assigned a default value of 'document'. Therefore, the payload will be considered to be a document and not a Remote Procedure Call (RPC), where the return values and the parameters are encoded. The binding spells out only a single protocol, sans any addressing information.

The operation element surfaces again, with the name attribute having the value of abc. The soapAction attribute in the operation element from the soap namespace, displays the same value as seen in the HTTP header SOAPAction. Now, you can identify the fountainhead of all the values with effortless ease. The style attribute has already been explained above.

 

There exist two more child elements, input and output. Both these child elements possess the same content, i.e. an element body belonging to the soap namespace. It is the value assigned to this element, that determines how the message parts are to appear in the SOAP Body element. It follows the Envelope element in the SOAP payload.

 

The 'use' attribute can take either of the two values, 'encoded' or 'literal'. The 'encoded' value refers to an abstract type, whereas, the 'literal' value uses a schema definition created in the types element.

 

Finally, we arrive at the last element of service, which is assigned the name of zzz.

 

<service name="zzz">

<port name="zzzSoap2" binding="s0:zzzSoap1">

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

</port>

</service>

 

The value assigned to this service name determines the name of the cs file. More importantly, it decides the name of the class. If you change the name to zzz1, the C# program shall also be renamed as zzz1.cs, and it would contain a class named zzz1. This name is obtained from the WebService directive.

 

A port element child named as zzzSoap2, is used to steer clear of any confusion. We do not use this port name elsewhere. It is the port element that consolidates the bindings zzzSoap1 with the help of the 'binding' attribute.

 

The next element of 'address' from the soap namespace, has the location attribute initialized to the name of the asmx file, which contains the code of abc. You may recall that the same value had been used for the Url property in the proxy.

 

Meanwhile, this concludes an explanation of the WSDL file. Incidentally, we are not over and done with it yet. The specifications are pretty abstract, and we still have miles to go before we sleep!