Sie sind auf Seite 1von 274

244025452.

doc 1 od 274
XML WebServices and SOAP
Contents

Introduction

1.Introduction to Web Services

2.Web Services Description Language

3.Data Types in WSDL

4. DataSets

5. Webservices and Javascript

6. SOAP Headers

7. Soap Extensions

8. Encrypting and Decrypting Soap Data

9. Attributes

10. SOAP Faults

11. ASP.Net WebServices

244025452.doc 2 od 274
12. WSDL and DISCO

13.Remoting
Introduction
This book ofers you the most opportune moment to set sail on a voyage of discovery,
during which, you shall visit the topics of XML Web Services and the Simple Object
Access Protocol, SOAP. It proceeds according to a coherent roadmap, to ensure that
each topic builds up incrementally on its predecessor.

You should assimilate what has been presented in a specifc chapter, before venturing
on to the next one. We have essayed at quelling the general fear of learning a new
language by clearly explaining all the complex topics. We have re-visited some topics to
ensure that you have a lucid understanding of the intricate concepts, even though we
are aware that reiterations could result in ennui. We have included a vast array of
examples, which strip the sheen of complexity in which most concepts are generally
ensconced.

XML Web services are the fundamental building blocks in the transition towards
Distributed Computing on the Internet. XML Web Services are fast becoming the
standard for application interaction. An XML Web Service is a standard way of exposing
services to a large number of users.

An XML Web service is a function that is exposed, so that other applications on the Web
can exploit its inherent capabilities. By using XML Web services, application developers
can converge their creative energies on the unique value-added functions that they wish
to provide. XML Web services are modular and extensible. However, there are a number
of features that have been left to the developer for implementation.

SOAP, Simple Object Access Protocol, is described as a communications protocol. It is a
specifcation that defnes the XML format for messages. The SOAP specifcation defnes
the structure of an XML document, which can be used to exchange data between two
applications. It expounds a way to represent programming language specifc datatypes,
in XML.

The most compelling feature of SOAP is that, it has been implemented on many diferent
hardware and software platforms. This implies that SOAP can be used to link disparate
systems both, within and outside your organization. SOAP is primarily used to facilitate
communication between diferent programs. These programs may have been written in
diferent languages, and could be running on diferent platforms.

SOAP is extremely popular and has become the de facto industry standard, as it
facilitates interoperability between assorted environments, and it uses HTTP as the
transport mechanism.

You would acquiesce that our book titled 'XML Web Services and SOAP' is not meant for
the technically nave. The reader must have sufcient knowledge of C# and ASP.Net,
244025452.doc 3 od 274
before launching forth with this book. The primary assumption is that you have either
read our book on C#, ASP.NET, or any one of the other innumerable books on this topic,
strewn all over the market.

We have adopted a step-by-step approach wherein, we frst acquaint you with the
smallest Web Service. Once you are at ease with it and can create a webservice
efortlessly, we progress on to examining the packets that are sent across by the client
to the server, and vice-versa. We have based our theory on the packets that have been
trapped, using the Trace Utility from the Microsoft SOAP Toolkit, 2.0.

The XML Web Services are built on WSDL, SOAP, XML and UDDI specifcations. The
second chapter introduces us to WSDL. We have even endeavored to explicate the code
generated by the wsdl program. While doing so, we realized that we had to devote an
entire chapter to the diferent data types. We also had to analyze the changes that
occur, when data is sent across from client to server and vice-versa. This eventually
directed us on to the next chapter of DataSet, since a DataSet is a collection of
DataTable objects that embody data. Following this, we attempt to perceive how a web
service can be called, using Javascript in an html fle.
Then, we proceed on a sojourn to the SOAP packets, which are our next area of interest.
Here, we begin with the SOAP headers, and learn how to create custom attributes to
enhance the capabilities of the Web Service. Once these aspects have been elucidated,
we focus on security issues relating to SOAP. Here, we delve upon the processes of
encryption and decryption of data, as well as, on compression and decompression of
data.

Finally, all miscellaneous attributes relating to Web Services, which were not touched
upon earlier, are tackled in the remaining chapters. After discussing the SOAP faults,
we move on to an authentication program, where all the knowledge attained by us so
far, has been put to use. The topic of Disco has also been attended to, before going into
the details of a WSDL fle. We have concluded this book with the chapter on Remoting,
where our attention rivets around the data and the data types that get generated in the
SOAP packets, when functions are called with diferent types of parameters.

We are sure that if you read this book with earnest, you diligence will defnitely pay of.
We exhort you to make the most of this wonderful opportunity. Let the pursuit of
knowledge be your lodestar.

Requirements

The software requirements to successfully run all the programs in this book are

Operating System - Windows 2000
Microsoft IIS ver 5.0
SQLServer 2000 (Evaluation Edition)
Internet Explorer 5.5
.Net Framework SDK Beta 2 (111 MB)
Soap Toolkit 2.0

Internet Explorer 5.5 can be downloaded of the Microsoft site
http://www.microsoft.com/windows/ie/download/ie55sp1.htm
244025452.doc 4 od 274

Net Framework SDK Beta 2 can be downloaded of the Microsoft site

http://download.microsoft.com/download/VisualStudioNET/Trial/2.0/W982KMeXP/E
N-US/setup.exe

Alternatively, you can visit the download section at Microsoft
( http://msdn.microsoft.com/downloads/default.asp ) and download the .Net
framework SDK Beta 2 under the Software Development Kit option.

Soap Toolkit 2.0
The Soap Toolkit 2.0, approx. 1.44 mb, can be downloaded from the Microsoft site
http://download.microsoft.com/download/xml/soap/2.0/W98NT42KMe/EN-
US/SoapToolkit20.exe

SQLServer 2000
While installing the evaluation edition of SQLServer 2000, we have chosen the default
selected settings. The only modifcation made is in the Authentication Dialog Box.

You see two options
Windows Authentication mode
Mixed mode (Windows Authentication and SQL Server Mode)

The default option selected is Windows Authentication mode. We have instead selected
Mixed mode (Windows Authentication and SQL Server Mode). Once this option is
selected, the password text boxes for the 'sa' user gets activated. As we would prefer
using a blank password in our programs, we select Blank Password. On selecting this
option, the text boxes get disabled again.

Once the database server is installed and started, you will have to Install the .NET
Framework Samples Database. To do so, click on Start->Programs-> Microsoft .NET
Framework SDK-> Samples and QuickStart Tutorials. Follow the instructions given in
this html fle to install all the samples that come with the SDK.




Acknowledgements


The many individuals who have worked together to produce this great work of art and
motivated me all the way need a mention here. Their bright ideas, inspiration, support
has made me a lot more stronger and wiser.

First and foremost, thanks to Manish Jain, BPB Publications for publishing the book.

To my co-authors, Vikram and Sonal who have put in a lot of hard work to complete the
work assigned to them.
244025452.doc 5 od 274

To Tanuja Sodhi, an ex-Naval Ofcer from the frst batch of lady ofcers and an MBA
from Jamnalal Bajaj, for editing the book. She is presently freelancing as a creative
writer.

To Altaf Hemani and Kishore Rohra, for their creativity in designing the cover in a
given short time.

Thanks to Manish Purohit for putting in late hours while testing all the applications in
the book and then giving the book a good look and feel.

To Pradeep Mukhi and Shivanand Shetty, who have always been there, as a source of
inspiration and encouragement.

My Mother, Shana Aunty and a long list of friends need a mention here for their
patience and cooperation on this book while it was being written.


-Vijay Mukhi
1
Introduction to Web Services

We embark upon our subject of Web Services with the primary assumption that you
have read either our book on ASP.NET, or any one of the innumerable others, strewn all
over the market. So, we will not submerge ourselves into every microscopic detail about
either the C# programming language or ASP.NET. This book is fully dedicated to the
understanding and building of Web Services, since Microsoft has precluded all the other
options for building commercial applications for the Net. A Web Service is a piece of
program code placed on the Server, such that it can thereon be accessed or executed by
the entire world.

Create a fle named a.asmx in the folder c:\inetpub\wwwroot, with the contents laid
down below. IIS, the web server on our machine, makes this directory the root or home
directory.

a.asmx
public class zzz
{
public string abc()
{
return "vijay";
}
}

Enter the following URL in Internet Explorer:

http://localhost/a.asmx

On doing so, an error will be displayed with the following message:
244025452.doc 6 od 274

Output
Parser Error Message: !e page must !ave a "#$ webservice
class%&M'(amespace)M'Class& ))) #* directive)

Before we advance any further, a few fundamental concepts need to be addressed
immediately. Even though the fle has the extension of asmx, it has a striking
resemblance to a C# program. The error is a ftting testimony to the fact that the IIS
web server is capable of recognizing and handling fles that have the asmx extension.
Hence, it seeks out the WebService directive. This WebService directive provides
information to the web server about the class that represents the functioning of a
WebService. And, since every asmx fle must commence with this directive, we
incorporate this directive into the asmx fle.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
public class zzz
{
public string abc()
{
return "vijay";
}
}

In C#, all the code is encompassed in classes. The class named zzz contains a function
named abc, which returns a simple string of 'vijay'. On entering the URL of
http://localhost/a.asmx in Internet Explorer, a page bursting with information gets
displayed. However, there is no function by the name of abc for execution.

IIS is cognizant of the fact that an asmx fle encloses code that others may call remotely.
Therefore, on stumbling upon a fle with the extension of asmx, it displays the following
large html page:

244025452.doc 7 od 274
Screen 1.1

For IIS, the asmx extension denotes Web Services. The language attribute has the value
of C#. This indicates that the code is written using the C# programming language. The
value of C# can be replaced with any other .NET compatible language. The Class
attribute points to the class that contains the code, which is to be exposed to the world.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public string abc()
{
return "vijay";
}
}

The sole process of converting a normal function into a WebService is by augmenting it
with the WebMethod attribute. On introducing this attribute, you will observe the
browser screen change, as shown in Screen 1.2.

Screen 1.2

244025452.doc 8 od 274
Screen 1.3

Function abc is now a hyperlink. Clicking on it would lead to a display of another screen
containing a button labeled as 'invoke'.

Now, a click on this button will display the URL with the following address:
http://localhost/a.asmx/abc?. It would also display the following XML fle in the
browser:

Output
"+,ml version%&1)-& encoding%&ut./0& +*
"string ,mlns%&!ttp:11tempuri)org1&*vi2a'"1string*

This fle makes a debut with the xml directive, followed by the encoding used. The utf-8
encoding can be regarded as a technical term representing English-like statements. The
succeeding line embodies the return value of 'vijay' in a string tag. The namespace for
the string tag is specifed by employing the xmlns attribute, with the value of
tempuri.org.

The above program named a.asmx would be considered to be inefective, if it was
capable of being invoked only from the browser. This is due to the reason that, not
everyone would desire to access a WebService from a browser. Furthermore, on certain
occasions, the user may not be comfortable, using the user interface either. To
surmount these limitations, a program written in the C# programming language has
been provided, whose sole mission is to call the Web Service abc, of the server. Create a
subdirectory named www on C drive and enter the following program in a fle named
zzz.cs:

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
244025452.doc 9 od 274
{
zzz a " ne/ zzz();
string b;
b " a.abc();
ystem.#)ns)le.Write!ine(b);
}

&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public string abc()
{
2rl " "(ttp,33l)cal()st3a.asmx";
)bject&+ results " 4nv)5e("abc"6 ne/ )bject&7+);
return (string)results&7+;
}
}

*csc 333)cs
*333

Output
vi2a'

Compile the program, using the compiler command csc. This command creates an
executable fle, which can be executed to view the output of the program. On doing so,
the return value of the function i.e. 'vijay', gets displayed on our console.

In fle zzz.cs, class zzz derives from class SoapHttpClientProtocol, which in turn, has
been derived from the following classes:
HttpWebClientProtocol
WebClientProtocol
Component
MarshalByRefObject

The class SoapHttpClientProtocol has the essential infrastructure to call a Web Service
from the server.

To begin with, we create an instance 'a' of class zzz in the Main function. Then, we call
function abc from it. This function is defned in the same class, but with an attribute
called SoapDocumentMethodAttribute. The attribute is not passed any parameters.
However, this attribute infuences the mode of communication that is employed between
the Client and Server.

In abc, the value of the Url property is assigned the name of the server, which contains
the remoted code. Since the programs are being run on our local machine, the url is
specifed with 'localhost'. The fle containing the web service code is named a.asmx. The
Url property is not defned in the program, since it originates from the
WebClientProtocol class.

After defning the Url property, a function named 'Invoke' is called with two parameters.
The remote function is specifed as the frst parameter. An array of objects containing
the parameters to the remoted function, is furnished as the second parameter. Since
abc does not take any parameters, an array of objects of size zero, is supplied as the
second argument. Inexplicably, the Invoke function executes the abc function, which
dwells in class zzz within the a.asmx fle on the server.
244025452.doc 10 od 274

Although in our case, the client and server are located on the same machine, in real life,
they could be poles apart in terms of their geographical locations. On completing the
execution of its code, this function returns the string 'vijay' to the client. The return
value is stored in an array called 'results', having a datatype of 'objects'. Since 'vijay' is
the only value returned, it gets copied into the frst member of the array. The value is
type cast to a string, and thereafter, duly returned while quitting the function. This
value is stored in the string variable b, and then, displayed to the user.

All the activities that have been accomplished so far, are ensconced in the realm of
sheer magic. This is by the reason of the mystery that shrouds the mechanism of
communication between the client and the server.

One of the acronyms that you are sure to encounter very often in this book is SOAP,
which stands for the Simple Object Access Protocol. The client and the server talk to
each other by employing SOAP.

So, lets understand what SOAP is all about. We work under the assumption that you
have downloaded and installed the SOAP toolkit that is available on the Microsoft site.
This toolkit contains a Trace program, whose singular task is to display the data sent by
the Client to the Server.


Now, run the Trace Utility. Its output is shown in Screen 1.5.

Screen 1.4

244025452.doc 11 od 274
Screen 1.5

Screen 1.6

Click on the File-New-Formatted Trace menu option, as shown in Screen 1.6.

244025452.doc 12 od 274
Screen 1.7

On doing so, a dialog box appears, containing the number 8080, as shown in Screen
1.7. Since the given value seems acceptable, click on OK. The Screen 1.8 displays the
new window.

Screen 1.8

Now, let us carry out slight modifcations in the program, in order to include the
following code:

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
244025452.doc 13 od 274
{
zzz a " ne/ zzz();
string b;
b " a.abc();
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public string abc()
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject&+ results " 4nv)5e("abc"6 ne/ )bject&7+);
return (string)results&7+;
}
}

Only one minor modifcation has been efected to the zzz program. The number 8080
has been assigned after a colon, with the machine name, while assigning a value to the
Url property. On recompiling and executing the program, the output that is displayed, is
the same as was seen earlier. But now, we also see a + sign in the frst window of the
trace program, as depicted in Screen 1.9.

Screen 1.9

Clicking on the + sign displays Message 1. If you click on this node, the output in the
two panes undergoes transformation. This is refected below.

Client: SOAP 4e5uest
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*
"1soap:Envelope*

Server: SOAP 4esponse
244025452.doc 14 od 274
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*vi2a'"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

In the networking world, every packet that fows to and fro, passes through a number of
layers. The frst layer is the Internet Protocol (IP). It is frst followed by the TCP or
Transmission Control Protocol, and fnally, by the Application Layer. The Application
Layer may contain any of the following protocols:
HTTP for the World Wide Web
SMTP and POP3 for the E-Mail protocols
FTP for File Transmission, and so on.

The higher-level protocols could be any one of the vast array of protocols. Hence, there
is an inevitable requirement for a mechanism for identifying the protocol. This is
achieved as follows: When two computers talk to each other, the packets that are
created, are stamped with a number. In the TCP/IP world, this number is given the
nomenclature of 'port number'. Diferent protocols use distinctive port numbers as
given below:
HTTP protocol uses a port number 80. So, every packet on WWW that follows the
HTTP protocol, is stamped with this number.
Email packets that are sent, have the port number of 25.
Email packets that are received, have a port number of 110.
FTP packets have the port number of 21 marked on them.

As a consequence, a singular machine is capable of handling multiple applications,
since they run on diferent protocols. The frst 1024 protocols are reserved by the
Internet Standards Body called - the Internet Assigned Numbers Authority (IANA).

By default, every web server listens on port 80, which is indicative of the fact that, it
accepts packets that have the number 80 imprinted on them. There is no need to cite
the port number exclusively, since the default values are taken into consideration.
Alternatively, even if the url had been stipulated as http://localhost:80/a.asmx, events
would have occurred in the same manner. The http protocol imprints the port number
of 80 on every packet that it sends across.

After having altered the port number to 8080, the client packets shall now connect to
port 8080, rather than to port 80. At this port number, there is a Trace program from
Microsoft that waits to receive packets, instead of a Web server. The trace program
ferrets out whatever information is of any signifcance to it, and thereafter, it acts as a
client, in that, it sends the packet to the http or web server that is listening on port 80.
The return packet arrives back at the trace program. This is because, as far as the
server is concerned, the trace program is a client. The invoke function is the one that
generates the request packet and makes some sense out of the response packet.

244025452.doc 15 od 274
Before we proceed any further and delve upon what SOAP is all about, let us simulate
the working of the Trace program, i.e. we need to write a program that would be similar
in functionality to the Trace program and would also incorporate the workings of the
Invoke function.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz
{
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<7777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
ystem.#)ns)le.Write!ine(a<);
}
}

Write the program in a text fle named a.cs, within the folder proxy3, and compile it
using the command csc a.cs.

At the outset, run the program executable a.exe, which is located in the proxy3 folder.
Confrm that the trace program from the Soap Toolkit is turned of. Then, execute the
zzz program. If the client throws an exception, it can be safely ignored for the moment.
Our prime concern at the moment is the output in the proxy3 folder.

Output
POS 1a)asm, ;P11)1
<ser/Agent: Mo3illa1=)- >compatible? MSIE @)-? MS Web Services Client Protocol
1)-)7A1=)1@B
Content/'pe: te,t1,ml? c!arset%ut./0
SOAPAction: &!ttp:11tempuri)org1abc&
Content/9engt!: 7AA
E,pect: 1--/continue
Connection: Ceep/Alive
;ost: local!ost

"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*
"1soap:Envelope*

244025452.doc 16 od 274
If you have an eye for detail, you would probably have noticed that the second half of the
output is identical to the output of the Trace program. Well begun is half done! We have
successfully replicated partial functionality of the Trace program. The above output is
the outcome of the Invoke function, which is achieved when packets are sent to the web
server.

Initially, let us comprehend the above program, which for varied reasons, can be called
a Web Spy. A TcpListener object t is a class that encapsulates the tcp layer for a web
server. The int parameter 8080 signifes the specifc port number on which, the server
shall keep a listening watch. The presence of this class makes writing of servers a
breeze and a pleasure. This is for the reason that, had we used 80 in lieu of 8080, we
would have witnessed the makings of a web server.

The constructor merely stores this number for its internal reference. It is the Start
function that actually kick-starts the server. The AcceptSocket function arrests the
execution of the program while it awaits a connection. However, if no client connects to
the server, the wait may turn out to be frustratingly indefnite. To substantiate our
claim, you may place some WriteLine functions before and after the AcceptSocket
function. The ones that you place after the AcceptSocket functions, shall not be
displayed in the output.

The AcceptSocket function waits for a connection on port 8080. The zzz program that
simulates the working of a client, calls the Invoke function, whose sole mission is to
dispatch some bytes to the server. As it connects to the server on port 8080, the
AcceptSocket function in the server moves out of its 'blocking' state, and returns an
object of type Socket. A Socket represents the two endpoints of the connection. It is
primarily employed to dispatch or receive data.

A byte data type represents an ASCII character or a number ranging between 0 and
255. The char data type is used only for UNICODE characters. A string is a separate
data type altogether. An array of bytes b, which has a size of 1000, is created and used
along with the Receive function, to pick up the data sent by the client to the server. This
network programming is also called TCP/IP programming or Sockets programming. The
Receive function, like the AcceptSocket function, is a blocking function. Thus, it should
be employed only when you are completely convinced that there is some data waiting at
the socket. The AcceptSocket function is the most vital function, since it provides a
Socket object or a channel, by means of which, it facilitates communication between the
server and the client.

In order to display the data that is sent by the Client, we use the WriteLine function.
The data stored in array b is of type byte array, and not a String. Since the WriteLine
function is not competent enough to display an array of bytes, the GetString function
belonging to the Encoding class, is used. This function accepts an array of bytes and
returns a string.

The client dispatches the data in two consecutive packets. Therefore, the Receive
function is used twice. The function stores the data in two byte arrays named b and c. It
also returns the number of bytes that it has placed in the array. The values stored in
variables h1 and h2 can be printed, by bringing the WriteLine function into play.
244025452.doc 17 od 274

Let us now come to terms with the bytes that are sent by a call to the Invoke function.
This function is very signifcant, since commenting out this function will lead to nothing
being displayed in the server dos box.

The RFC for the HTTP protocol runs into reams of paper. However, it states that the frst
set of words sent by the client to server, should contain either of the words, such as-
GET, POST or HEAD. The words GET and POST are always accompanied by a flename.
The diference in functionality between the two of them, is largely on account of the
manner in which the parameters are transmitted.
In a GET situation, the parameters are dispatched along with the command in a single
packet. Moreover, they are legible and distinctly discernible. In the case of POST, the
data gets sent across in a separate packet.

Since the method employed here is POST, two packets are sent to the server; one for the
headers and the other for the data. The URI of /a.asmx follows the POST, as this is the
fle that was requested for, by the client. As the fle extension is .asmx, it will be
executed on the server, and thereafter, the output of the fle shall be sent across to the
client.

Close on the heels of the HTTP command, is the HTTP version number. The version of
1.1 is not very recent. Nonetheless, it is commonly used in an HTTP packet. Any word
that ends with a colon, is termed as a header variable. This defnition qualifes User-
Agent to be a header variable. The value assigned to this variable is the word specifed
after the colon. User-Agent contains the name of the browser, i.e. Mozilla/4.0.

It is with the means of this mechanism, that a web site identifes the browser that has
been utilized to visit it. It could either be Netscape Navigator or Internet Explorer or a
mobile phone browser, or any other browser for that matter. The developers of Netscape
Navigator, the world's second browser, surely weren't defcient in humour department.
This explains why they chose to call their browser Mozilla. Internet Explorer was quick
to follow suit, and christened itself as Mozilla, but appended its own identifcation in
brackets. The real name and the version number of IE are specifed within the brackets.
In our case, since we are working with a .NET product, this aspect is also given a
mention.

All SOAP packets have the header of Content-Type initialized to text/xml, which is
indicative of the fact that the content is XML based. Content-Type is also known as the
MIME type, since it describes the type of data or document that follows. A few examples
of the MIME types are:
text/html represents an html fle.
text/plain represents a plain text fle.
img/jpg represents a picture fle, i.e. a jpg fle.
img/bmp represents a BMP fle.

charset represents the language used and utf-8 represents our good old English.

The value assigned to EXPECT, determines whether there is more data on the way or
not. Since the value contains the word 'Continue', it implies that there is more data
expected. The Content-Length header is the size of the data packet that follows the
244025452.doc 18 od 274
header packet. In our case, it is 299 bytes. This data packet is also termed as the SOAP
payload.

In the normal course, once the data has been received, the HTTP protocol sends a 'close
connection' packet, in order to close the connection. The Connection header is passed a
value that asks the server to close its connection to the browser. Once this has been
accomplished, and in the event of more interaction being required with the other side,
the connection needs to be re-established all over again. This not only slows down the
transfer, but also is a tedious and time-consuming process. Thus, to circumvent this
protracted process, the client on many occasions, requests the server to keep the
connection alive.

The Host identifes the machine from where the fle a.asmx has to be executed. Since
the destination computer is the localhost, the value assigned to this variable is
localhost. An extra blank line at the end, marks the termination of the header packet.

We have deliberately precluded one of the headers called SOAPAction, as it does not
form a part of the HTTP specifcation. It has been explicitly added by the SOAP
standard. The client launches this header, to convey the specifcation or objectives of
the packet to the server.

The value assigned to this header is a URI that identifes a resource on the Internet,
and not a URL that points to a particular location. The SOAP standard demands the
presence of this header in the packet, but it is more accommodating about the content
or the value assigned to it. This implies that the URI that has been stipulated, may not
be a resolvable one. Anyway, this is nobody's business. SOAP imposes absolutely no
restrictions on the format of the URI.

A signifcant number of servers may not be able to appreciate this URI. Therefore, there
is a possibility that the packet may be dropped, and may remain unaccounted for.
Furthermore, depending upon the frewall installed, the packet may either be allowed to
pass through, or it may be fltered out from the HTTP packets.

This feld may also be initialized to an empty string, which would indicate that no URI is
to be specifed. In our specifc case, it has been assigned a reserved value of
http://tempuri.org, followed by the name of the function that we require it to execute.
Despite our not having mentioned 'tempuri.org' explicitly anywhere in the fle, it has got
picked up by default. Note that it is the URI, and not the URL, which is of prime
importance.

Next in line is the actual SOAP payload, which is sent across as an XML document. We
shall not dwell on the in-depth account or explanation of what an XML document looks
like, since there are plethora of books available on XML, which expound the same. One
of the books that we are working on, have an indepth study on this topic.

Every XML document starts of with a root or a document tag. In the case of a SOAP
document, this root tag is called the Envelope. If a tag is merely a tag, then a tag
created by one, would eventually clash with the tag created by the other. Thus, there is
a need to segregate tags created by diferent sources. This is achieved by placing them
244025452.doc 19 od 274
in diferent namespaces. A tag is specifed in the format of a namespace prefx, followed
by a colon and then, the actual name of the tag.

The tags seen in the output have a namespace prefx of 'soap'. Every namespace prefx
is assigned the value of a URI. So, an attribute named soap is frst created in the xmlns
namespace, which in turn, represents a URI of
http://schemas.xmlsoap.org/soap/envelope/. The reserved xmlns namespace is used
exclusively for namespace prefxes.

The SOAP standard specifes the URI of http://schemas.xmlsoap.org/soap/envelope/,
since there is no pressing need for it to incorporate anything. On specifying the above
URL in the browser, an XML fle, or to be more precise, an XML schema fle gets
displayed.

An XML schema fle represents a series of error checks that can be performed on an
XML document. This is to ascertain whether the document follows certain rules. One of
the rules that we have just touched upon is, the presence of the root or document tag
as 'envelope'. Rules are always sited in an XML schema fle.

The SQL language of the database world is now being replaced by XML. This is a
pellucid indication of the predominance of XML in the software industry. The DTD's
have already been converted to XML, thereby, simplifying the specifcation of a
document structure. However, as was stated earlier, a URI is indicative only of a name,
and anything else that may be mentioned, is a bonus. Thus, any system can use the
above schema at the specifed URL and verify if the SOAP document satisfes the rules
of SOAP.

URIs are also created for namespaces such as - xsi and xsd in the Schema world. Thus
all in all, there are three namespace prefxes defned in the output. We could easily use
any name other than the namespace prefx 'soap', as long as it is set to the right value.
There are no attributes mentioned in the fle. In other words, a URI is like beauty, which
lies solely in the eyes of the beholder.

The Envelope tag is followed by a Body tag, which actually contains the SOAP message.
The name of the function that is to be executed is 'abc'. Therefore, there is a tag present
with the same name. In order to thwart the possibility of name clashing, wherein
someone somewhere else may also want to execute a function named abc, the
namespace for the abc element is changed to tempuri.org, using the xmlns attribute.
Thus, the abc tag now becomes 'sui generis', which is unique across the seven seas. The
function accepts no parameters. So, the abc element has no content whatsoever. This
completes the explanation of the SOAP payload, sent by the client to the server.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz
{
public static v)i* 'ain()
244025452.doc 20 od 274
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<7777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
ystem.#)ns)le.Write!ine(a<);
:cp#lient t< " ne/ :cp#lient();
t<.#)nnect("<@A.7.7.<"6 87);
9et/)r5tream s< " t<.?ettream();
s<.Write(b676(<);
s<.Write(c6 76(@ );
byte &+ * " ne/ byte&<777+;
int (B "7;
string a@ """;
/(ile (s<.0ata1vailable)
{
(B " s<.=ea*(*676<777);
a@ " a@C>nc)*ing.1#44.?ettring(*);
}
ystem.#)ns)le.Write!ine(a@);
s.en*(*6(B6)c5etDlags.9)ne);
}
}

Output o. pro,'
;P11)1 1-- Continue
Server: Microso.t/IIS1D)-
Eate: WedF -7 Gan 7--7 -1:=-:DA HM

;P11)1 7-- OC
Server: Microso.t/IIS1D)-
Eate: WedF -7 Gan 7--7 -1:=-:DA HM
Cac!e/Control: privateF ma,/age%-
Content/'pe: te,t1,ml? c!arset%ut./0
Content/9engt!: 6@1

"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& ,mlns:,si%
&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M
9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*vi2a'"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

There are a few more lines displayed on the spy console. We have not redisplayed the
data that was shown earlier, since we see no rationale behind reiterating issues time
and again. The output shown here is the SOAP message that the server sends to the
client.

244025452.doc 21 od 274
Every HTTP request starts with the version number HTTP/1.1, followed by a number
that ascertains whether the request was successfully met or not. For example, the
number 200 OK signifes that the request terms have been met, whereas, the code of
404 stands for a 'fle not found' on the server. These are pre-defned numbers stipulated
in the HTTP protocol specifcation.

Following the error-code, a description of the error or the error message is specifed
without fail. Thereafter, the headers follow. The value assigned to Content-Type header
as usually is the case, indicates the type of the data, i.e. SOAP message that follows.
The server name, IIS in our case, is specifed along with the Server header, and the
Content-Length is assigned the length of the SOAP response packet.
The SOAP payload starts with the Envelope root, together with all the namespace
defnitions. The Body tag following the Envelope tag has the Response of the abc
function. Therefore, the tag is abcResponse, with the default namespace of tempuri.org.
The return value can only be of the string type, since there is no concept of data types
in XML. Here, we have a tag named abcResult, which contains the return value of
'vijay'.

After having interpreted the process wherein values are returned, we shift the spotlight
onto the spy program. We have added a considerable amount of code to the earlier
program, because the spy now represents both, the server as well as the client. The
server portion has two Receive functions, one each for the HTTP header and the SOAP
payload. This data will now be dispatched to the actual server running on port 80. In a
sense, the spy program conducts itself like a client communicating to a server on port
80.

The trace program begins as a server listening on port 8080, and waits at the
AcceptSocket function, since its sole responsibility is to await a connection. When the
zzz program in the other dos box is executed, it connects to this server running on port
8080, thereby, releasing the AcceptSocket function from its 'wait' mode. Subsequently,
the two byte arrays b and c would store the data received from the newly connected
client, by calling the Receive function. After having restored the data sent by an actual
client, the program now advances further to enact the role of a client, which connects to
a real-life web server on port 80.

A TcpListener object is instantiated while writing a server, whereas, an object of class
TcpClient is employed while writing a Client. The object in this program is called t1. The
Connect function in the TcpClient object is invoked to connect to an actual web server
running on port 80. This function accepts 2 parameters, viz. the IP address of the
server and the port number that the server is listening on.

The GetStream function in the TcpClient object returns a NetworkStream object. This
value is stored in s1. Now, the data collected from the original client, stored in the two
byte-arrays of b and c, is written to the stream. This data is eventually dispatched to
the server. Ultimately, the data received by the actual client is sent to the actual server.
However, during this process, the trace program traps the bytes that fow to and fro.

The loop terminates only when there is no more data available from the server. The
DataAvailable property returns 'true' when there is more data to be read from the
244025452.doc 22 od 274
stream object. Thereafter, with the help of the Read function of the stream, the data
that has been received from the server, is read into a byte-array called d. This array is
then sent to the client using the Send function. Remember that the socket variable s
corresponds to the connection with the client, whereas, the socket connection s1 refers
to the connection with the server.

Thus, to the remoting client, the spy program behaves akin to a server, while it acts like
a client to the remoting server. This is the methodology that we have adopted to
appreciate how SOAP operates, when the client and server communicate with each
other in the world of remoting.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz {
public static v)i* 'ain()
{
:cp#lient t< " ne/ :cp#lient();
t<.#)nnect("<@A.7.7.<"6 87);
9et/)r5tream s< " t<.?ettream();
string sE;
sE " "-;: 3a.asmx .::-3<.<Fn2serG1gent, ')zilla3H.7 (c)mpatible; '4> I.7; ' Web ervices
#lient -r)t)c)l <.7.@J<H.<I)Fn#)ntentG:ype, text3xml; c(arset"utKG
8Fn;1-1cti)n, F"(ttp,33tempuri.)rg3abcF"Fn#)ntentG!engt(, @8IFn#)nnecti)n, LeepG
1liveFn.)st, l)cal()stFnFn" ;
Myte&+ l< " >nc)*ing.1#44.?etMytes(sE);
s<.Write(l<6 76l<.!engt( );
string sI;
sI " "<Nxml versi)n"F"<.7F" enc)*ing"F"utKG8F"N%Fn<s)ap,>nvel)pe
xmlns,s)ap"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3F"
xmlns,xsi"F"(ttp,33///./B.)rg3@77<3O'!c(emaGinstanceF"
xmlns,xs*"F"(ttp,33///./B.)rg3@77<3O'!c(emaF"%Fn<s)ap,M)*y%Fn<abc
xmlns"F"(ttp,33tempuri.)rg3F" 3%Fn<3s)ap,M)*y%Fn<3s)ap,>nvel)pe%";
Myte&+ l@ " >nc)*ing.1#44.?etMytes(sI);
s<.Write(l@6 76l@.!engt( );
#)ns)le.Write!ine(l@.!engt();
byte &+ * " ne/ byte&<777+;
tring a@ " "";
/(ile (s<.0ata1vailable)
{
s<.=ea*(*676<777);
a@ " a@C>nc)*ing.1#44.?ettring(*);
}
ystem.#)ns)le.Write!ine(a@);
}
}

Output o. Sp'
70@
;P11)1 1-- Continue
Server: Microso.t/IIS1D)-
Eate: !uF -= Oct 7--1 -0:7D:6I HM

;P11)1 7-- OC
Server: Microso.t/IIS1D)-
Eate: !uF -= Oct 7--1 -0:7D:6I HM
Cac!e/Control: privateF ma,/age%-
244025452.doc 23 od 274
Content/'pe: te,t1,ml? c!arset%ut./0
Content/9engt!: 6@1

"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*vi2a'"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*
This program is merely an icing on the cake. The output is akin to what a server sends
in response to a SOAP message. It simulates the workings of the Invoke function, i.e. it
invokes the abc function from the fle a.asmx. The client program in zzz is not executed
in the current program.

Let us anatomize the workings of the Invoke function.
After having created a TcpClient object t1, a connection is established to a web server,
i.e. IIS on localhost on port 80. The NetworkStream object s1 refers to a stream, by
means of which, data will be sent to the server. Thereafter, the string s5 is initialized to
a string value, similar to what the client, or to be more precise, the Invoke function
sends to the server. In the program, we have initialized s5 to the output received from
the earlier program. The Write function forwards this string to the server.

The next packet to be sent across is the SOAP payload. As before, we take the SOAP
payload output from the previous program and initialize string s6 to it. This is then
transported to the server. The Response packet from the server is then displayed on the
screen.

Thus, the web server is kept completely in the dark about the identity of the sender of
the packets. All that it knows is, that it has received a SOAP request, and that it must
respond to it by sending a SOAP response. We have taken a decision against proceeding
any further with the explanation of the spy program, because we are now reasonably at
ease with its workings. So, start the trace program from Microsoft and try out the next
program.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public l)ng abc(int i6 l)ng j)
{
return i C j;
}
}

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
244025452.doc 24 od 274
l)ng b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public l)ng abc(int i6 l)ng j)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject &+ c;
c " ne/ )bject&@+{i6j};
)bject&+ results " 4nv)5e("abc"6 c);
return (l)ng)results&7+;
}
}

Output
61

SOAP 4e5uest
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"2*71"12*
"1abc*
"1soap::od'*
"1soap:Envelope*

SOAP response
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*61"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

We have incorporated a few amendments in the asmx fle. The function abc is still
present in the fle, but with two parameters passed to it, viz. an int i and a long j. A
value is then returned back.

The program zzz.cs calls the abc function with two values of 10 and 21. In the abc
function, an array of objects named c is created, with a size of 2. We initialize the two
members of this array to the values stored in the parameters i and j, respectively. The
array is then passed to the Invoke function.

The SOAP request, unlike earlier, now has the 'abc' element with two children, i and j.
The launch of these names is a consequence of the function being passed two
parameters, i and j. Thus, the parameter names are considered important. The
Attribute placed above the function is also largely responsible for it.

244025452.doc 25 od 274
Had we changed the order of the initialization and placed the variable j before i, the
content of the tags would also have changed to 21, 10, instead of 10, 21. Thus, the
order of the listed parameters is determined by the sequence of the parameters in the
function. The namespace that abc belongs to, always remains the same. The SOAP
response also remains unchanged, since the result will always be 31, when the two
parameters are summed up.

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int abc(int i<6 int j<)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject &+ c;
c " ne/ )bject&@+{j<6i<};
)bject&+ results " 4nv)5e("abc"6 c);
return (int)results&7+;
}
}

Output
-

SOAP re5uest
"+,ml version%&1)-& encoding%&ut./0& +*
/ "soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
/ "soap::od'*
/ "abc ,mlns%&!ttp:11tempuri)org1&*
"i1*71"1i1*
"21*1-"121*
"1abc*
"1soap::od'*
"1soap:Envelope*

SOAP 4esponse
"+,ml version%&1)-& encoding%&ut./0& +*
/ "soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
/ "soap::od'*
/ "abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*-"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*


In this program, the datatype of 'long' is altered to 'int'. Notwithstanding this, there is
no change in the SOAP output, since only the names of the parameters are sent across,
244025452.doc 26 od 274
and not their data types. The names have been changed to i1 and j1 in the function,
thereby, resulting in the child elements of i1 and j1 in the SOAP payload.

A necessity for a separate function abc is thus justifed, as the SOAP request picks up
the names of the parameters from it. These names must match the names in the asmx
fle, or there could be trouble brewing soon! In this case, the asmx fle expects the
names to be i and j, whereas, we have specifed them as i1 and j1. No error messages
are displayed, but the resultant value of the response packet is zero. On realizing that i
and j were not received, the asmx fle assumes them to be zero. Thus, we need to be
cautious while naming our variables.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(int i<6 int j<)
{
return i< G j<;
}
}

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int abc(int j<6 int i<)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject &+ c;
c " ne/ )bject&@+{j<6i<};
)bject&+ results " 4nv)5e("abc"6 c);
return (int)results&7+;
}
}

Output
11

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"21*1-"121*
"i1*71"1i1*
"1abc*

SOAP 4esponse
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*11"1abc4esult*
"1abc4esponse*

244025452.doc 27 od 274
We have carried out a minor modifcation in the zzz.cs fle. The frst parameter is named
j1, while the second parameter is named i1. Thus, the order in the SOAP request
appears as j1 followed by i1. Further, the parameters passed remain as i1 and j1; and
thus, the content remains unchanged, i.e. 10 and 21. Thus, we must be very judicious
in our choice of mode that is employed to send data across.

The SOAP protocol does not perform any error checks. In the asmx fle, the parameters
are named as i1 and j1. Here, j1 is subtracted from i1, and the result of this subtraction
is sent of as the return value. In this context, the sequence is of no signifcance. Even
though the SOAP payload has the elements j1 and i1, their order is disregarded, and
the names of the elements are given importance. Hence, i1 will be assigned the value of
21, and j1 will be assigned the value of 10. Thus, the return value will invariably be 11.
You would also have observed that we are only displaying the relevant portions that are
basic and essential for our understanding of SOAP, and not of the entire SOAP packet.
Most of the residual code remains unaltered. Hence, it has not been displayed.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(int i<6 int j<)
{
return i< C j<;
}
&Web'et()*+
public int pPr(int i6 int j)
{
return i C j;
}
}

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
b " a.pPr(<776@<7);
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int abc(int i<6 int j<)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject &+ c;
c " ne/ )bject&@+{i<6j<};
)bject&+ results " 4nv)5e("abc"6 c);
return (int)results&7+;
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int pPr(int j6 int i)
{
)bject &+ c;
c " ne/ )bject&@+{i6j};
244025452.doc 28 od 274
)bject&+ results " 4nv)5e("pPr"6 c);
return (int)results&7+;
}
}

Output
61
61-

1st Message
4e5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"i1*1-"1i1*
"21*71"121*
"1abc*

4esponse
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*61"1abc4esult*
"1abc4esponse*

7nd Message
4e5uest
"p5r ,mlns%&!ttp:11tempuri)org1&*
"2*71-"12*
"i*1--"1i*
"1p5r*

4esponse
"p5r4esponse ,mlns%&!ttp:11tempuri)org1&*
"p5r4esult*61-"1p5r4esult*
"1p5r4esponse*

We have created another function named pqr in the asmx fle, and assigned the
WebMethod attribute to it. Furthermore, we have created the pqr function with the
[System.Web.Services.Protocols.SoapDocumentMethodAttribute()] attribute in the zzz.cs
fle, and called it from the Main function, as was done in the case of 'abc'. The trace
program now displays two SOAP messages, one for abc and the other for pqr.

We were under the impression that the SOAP message would be bunched up, which
however was not the case. Let us now change track slightly.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(int i<6 int j<)
{
return i< C j<;
}
}

zzz.cs
public class zzz
{
public static v)i* 'ain()
{
yyy a " ne/ yyy();
244025452.doc 29 od 274
int b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
}
}

yyy.cs
public class yyy , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int abc(int i<6 int j<)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject &+ c;
c " ne/ )bject&@+{i<6j<};
)bject&+ results " 4nv)5e("abc"6 c);
return (int)results&7+;
}
}

*csc 1t:librar' ''')cs
*csc 333)cs 1r:''')dll

You are sure to wonder as to what is the big idea behind this program. The program
runs in the same fashion as before. All that we have done is to broken up zzz into two
programs named zzz.cs and yyy.cs. The class zzz is not derived from anything at the
moment and it calls the abc function. The code for this function resides in class yyy.
The fle yyy.cs is compiled to a dll. Therefore, while compiling zzz, the /r switch is
specifed with yyy.dll. However, the output and the SOAP packets remain the same.

A vital point to be borne in mind is that, irrespective of where the code resides, the
WebService class is called zzz. Although there is no mention of class names in the SOAP
payload, we are confned to using just a single class name in our program. The asmx fle
may use a diferent name, but it must have only one WebService directive.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
<%@ Webervice !anguage""#$" #lass""yyy" %%

Parser Error Message: !ere can be onl' one JwebserviceJ directive)

Specifying two entries for the WebService directives would be asking for trouble. We
reiterate that since the SOAP payload does not mention the names of a class, only one
class can contain a WebService declaration.

Using the above approach, we have tried to highlight a few features related to web
services. The next chapter introduces a more innovative approach of working on these
concepts.
7
Web Services Eescription 9anguage
>WSE9B

244025452.doc 30 od 274
A WSDL fle 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 fle remains the
same. We have displayed the asmx fle below. All that the fle contains is, a single
function named abc.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(int i6 int j)
{
return i C j;
}
}

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

*Wsdl !ttp:11local!ost1a)asm,+WSE9
This creates a fle called zzz.cs. Compile the C# fle to a dll, using the following csc
command:

Csc 1t:librar' 333)cs

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

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int b;
b " a.abc(<76@<);
ystem.#)ns)le.Write!ine(b);
}
}

Compile it using Csc a.cs /r:zzz.dll . On running the exe fle a, an output of 31 is
obtained. In a single stroke, the WSDL program has efortlessly replicated all that we
had achieved with so much hard work in the previous chapter. In the zzz.cs fle, it
creates a class named zzz, which includes one function called abc. This function
contains code, which calls the abc function from the fle 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
33GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
33 <aut)generate*%
33 :(is c)*e /as generate* by a t))l.
33 =untime Qersi)n, <.7.@J<H.<I
33
244025452.doc 31 od 274
33 #(anges t) t(is Kile may cause inc)rrect be(avi)r an* /ill be l)st iK
33 t(e c)*e is regenerate*.
33 <3aut)generate*%
33GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG

33
33 :(is s)urce c)*e /as aut)Ggenerate* by /s*l6 Qersi)n"<.7.@J<H.<I.
33
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame""zzz)ap"6
9amespace""(ttp,33tempuri.)rg3")+
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
&ystem.0iagn)stics.0ebuggertep:(r)ug(1ttribute()+
public zzz() {
t(is.2rl " "(ttp,33l)cal()st3a.asmx";
}
&ystem.0iagn)stics.0ebuggertep:(r)ug(1ttribute()+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc"6
2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.!iteral6
-arametertyle"ystem.Web.ervices.-r)t)c)ls.)ap-arametertyle.Wrappe*)+
public int abc(int i6 int j) {
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+ {
i6 j});
return ((int)(results&7+));
}

&ystem.0iagn)stics.0ebuggertep:(r)ug(1ttribute()+
public ystem.41sync=esult Meginabc(int i6 int j6 ystem.1sync#allbac5 callbac56 )bject
asynctate) {
return t(is.Megin4nv)5e("abc"6 ne/ )bject&+ {
i6j}6 callbac56 asynctate);
}

&ystem.0iagn)stics.0ebuggertep:(r)ug(1ttribute()+
public int >n*abc(ystem.41sync=esult async=esult) {
)bject&+ results " t(is.>n*4nv)5e(async=esult);
return ((int)(results&7+));
}
}

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 fnally 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 fgure 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 fle, the opening
lines in the fle, must be a set of comments. So, the fle 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 frst time. The responsibility of this attribute is to denote a class containing one or
244025452.doc 32 od 274
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 fnally,
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 fle is named zzz.cs; furthermore, the fle is named zzz.cs, because the
WebService directive in the asmx fle 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 fle, 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 fle, 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 fle 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 fle gets displayed in the browser window. Create a new folder
wsdl and save the contents to a text fle named aa.wsdl within it. Then, enter the
following command:

Wsdl aa)wsdl

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

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
244025452.doc 33 od 274
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""int" type""s,int" 3%
<3s,sc(ema%
<3types%
<message name""abc)ap4n"%
<part name""parameters" element""s7,abc" 3%
<3message%
<message name""abc)ap;ut"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<message name""abc.ttp?et4n"%
<part name""i" type""s,string" 3%
<part name""j" type""s,string" 3%
<3message%
<message name""abc.ttp?et;ut"%
<part name""M)*y" element""s7,int" 3%
<3message%
<message name""abc.ttp-)st4n"%
<part name""i" type""s,string" 3%
<part name""j" type""s,string" 3%
<3message%
<message name""abc.ttp-)st;ut"%
<part name""M)*y" element""s7,int" 3%
<3message%
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%
<p)rt:ype name""zzz.ttp?et"%
<)perati)n name""abc"%
<input message""s7,abc.ttp?et4n" 3%
<)utput message""s7,abc.ttp?et;ut" 3%
<3)perati)n%
<3p)rt:ype%
<p)rt:ype name""zzz.ttp-)st"%
<)perati)n name""abc"%
<input message""s7,abc.ttp-)st4n" 3%
<)utput message""s7,abc.ttp-)st;ut" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz)ap" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
244025452.doc 34 od 274
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<bin*ing name""zzz.ttp?et" type""s7,zzz.ttp?et"%
<(ttp,bin*ing verb""?>:" 3%
<)perati)n name""abc"%
<(ttp,)perati)n l)cati)n""3abc" 3%
<input%
<(ttp,url>nc)*e* 3%
<3input%
<)utput%
<mime,mimeOml part""M)*y" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<bin*ing name""zzz.ttp-)st" type""s7,zzz.ttp-)st"%
<(ttp,bin*ing verb""-;:" 3%
<)perati)n name""abc"%
<(ttp,)perati)n l)cati)n""3abc" 3%
<input%
<mime,c)ntent type""applicati)n3xG///GK)rmGurlenc)*e*" 3%
<3input%
<)utput%
<mime,mimeOml part""M)*y" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt name""zzz)ap" bin*ing""s7,zzz)ap"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<p)rt name""zzz.ttp?et" bin*ing""s7,zzz.ttp?et"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<p)rt name""zzz.ttp-)st" bin*ing""s7,zzz.ttp-)st"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

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

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
244025452.doc 35 od 274
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sc(ema%
<3types%
<message name""abc)ap4n"%
<part name""parameters" element""s7,abc" 3%
<3message%
<message name""abc)ap;ut"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz)ap<" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt name""zzz)ap@" bin*ing""s7,zzz)ap<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

Akin to an XML document, which mandates the presence of an xml declaration with the
version attribute on the frst line, the WSDL fle 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 'defnitions'.

The tag named 'defnitions' 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
244025452.doc 36 od 274
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, fve namespaces
are created in the root tag.

<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%

The frst namespace is named as s. It points to a URI that represents XML Schemas.
XML Schemas are merely XML specifcations that ascertain whether the XML document
follows the laid down specifcations or not. There is more to it than just specifcations,
but for the moment, it would sufce to say that the rules are prescribed in the
specifcations. Thus, any element that starts with the namespace 's' followed by a colon,
belongs to the XML Schema namespace. Normally, the namespace prefx used is 'xsd',
but the name of the prefx is not as signifcant 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 fle.
One essential point to be taken into account is that, the wsdl fle is created by IIS from
the asmx fle. Therefore, everything in this fle represents the asmx fle. Also, it is the
wsdl fle and not the asmx fle, which is used by the WSDL program to create the proxy.
The targetNamespace also points to the soap world. The default namespace specifed by
the xmlns attribute, applies to all those elements that are without a namespace prefx.

The root tag of 'defnitions' contains six diferent 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 fle 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 prefx s. This schema element is the
root tag for any schema fle. The targetNamespace attribute is also mentioned in the
defnitions element.

<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%

All elements in this schema belong to the targetNamespace URI, which is tempuri.org.
The elementFormDefault attribute can have only two values, viz. qualifed and
unqualifed, with the default value being 'unqualifed'. The value qualifed merely
signifes that all elements from the targetNamespace must be qualifed with the
namespace prefx. 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
244025452.doc 37 od 274
surely not peeve anyone. For those of you who fnd 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 refects an element called abc. Let us perceive as to how and where
the element has been created in the fle.

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

<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,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 defne the
complexity of the type. There is a sequence tag that maintains an order. This tag in
turn, defnes two more elements named i and j.

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

The minOccurs in the element signifes 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 predefned 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 fle 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 signifcance
244025452.doc 38 od 274
here. Had you even attempted to add or subtract code from the asmx fle, the WSDL fle
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""abc)ap4n"%
<part name""parameters" element""s7,abc" 3%
<3message%
<message name""abc)ap;ut"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%

Two messages called abcSoapIn and abcSoapOut are created in the fle. 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 specifed 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 defnes 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 fle, 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.

<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%

A portType consolidates the operations that are to be performed on the defned
messages. Our portType is assigned the name of zzzSoap, which is formed by conjoining
the name of the class as specifed in the asmx fle (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
classifes the messages that are created, as either input or output.
244025452.doc 39 od 274

The next element is the binding element called zzzSoap1.

<bin*ing name""zzz)ap<" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%

The original WSDL fle is termed as the binding zzzSoap, but we modifed 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 specifes an operation abc, with the 'input' and the 'output' message
types. The binding element that follows, originates from the soap namespace, and is
diferent 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 efortless 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 defnition
created in the types element.

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

<service name""zzz"%
<p)rt name""zzz)ap@" bin*ing""s7,zzz)ap<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<3service%
244025452.doc 40 od 274

The value assigned to this service name determines the name of the cs fle. 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 fle, 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 exlanation o! the "S#$ !ile. %ncidentall&, we are not o'er and
done with it &et. (he seci!ications are rett& a)stract, and we still ha'e *iles to +o )e!ore we
slee,
6
Eata 'pes in WSE9

In this chapter, we shall explore diferent data types in greater depth and shall analyze
the transformation that occurs when data is sent across from client to server and vice-
versa. Be warned! While probing for answers, the journey may not be all that smooth.
For the sake of conceptual clarity and since we feel that it is our moral responsibility to
do so, we shall explicate the wsdl process yet again. However, we hope to be very
succinct in our explanation.

As usual, we start with the fle a.asmx. This fle has to be placed in the
c:\inetpub\wwwroot subdirectory.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(reK int i)
{
i " <7;
}
}


The function abc in the fle accepts only one parameter named i, of data type int, which
is passed by reference. For those of you who have been initiated only recently to the
world of C#, a ref parameter needs to be initialized before it is passed as a parameter. If
the function changes the value contained in the parameter, the change is refected back
in the main program also. The abc function alters the value of i to 10.

244025452.doc 41 od 274
Run Internet Explorer and enter the following URL: http://localhost/a.asmx?WSDL.
This will generate and display a wsdl fle.

If we display the entire WSDL fle, this book is likely to weigh a ton. Therefore, we have
sifted through and fltered out the code that is superfuous and dispensable, and saved
the contents in fle aa.wsdl in a newly created folder named www. This fle is displayed
below for your reference.

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8" N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sc(ema%
<3types%
<message name""abc)ap4n"%
<part name""parameters" element""s7,abc" 3%
<3message%
<message name""abc)ap;ut"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz)ap" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
244025452.doc 42 od 274
<p)rt name""zzz)ap" bin*ing""s7,zzz)ap"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

A major portion of the wsdl fle remains unchanged. There however are a few
modifcations in the type element, i.e. in the schema. The element of abc is created like
earlier, and the parameter i becomes the child element.

The parameter i is read/write, and is sent across as the ref parameter. It is mandatory
for the client that calls the code in the server, to specify a value. Thus, the SOAP
request packet displays the value of this parameter.

The second element in the types is the abcResponse. This element too has a child
element called i, which is exactly similar to the frst i child. This is for the simple reason
that the function abc in the asmx fle, is permitted to assign a value and return it back.
Thus, all ref parameters are sent to and fro in the SOAP payload.

We have efected a modifcation to the Uri property. To be precise, we have altered the
location attribute in soap:address element, within the service tag. The port number of
8080 is specifed, in place of 80. This is because, we intend to run the trace utility from
the SOAP Toolkit, in order to view the packets fowing to and fro. In the www folder,
write the program given below in a fle called a.cs.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int b " <77;
a.abc(reK b);
ystem.#)ns)le.Write!ine(b);
}
}

The program a.cs is a client program in which, an int variable named b is initialized to
100, and passed as a parameter to the abc function. After the function concludes
execution, the value of b is printed.

Prior to executing any program, start the trace utility from the SOAP toolkit. Then,
create a batch fle to hold a series of commands. Run the batch fle and view the output
in both, the console box as well as the trace window.

z.bat
*el R.exe
*el R.*ll
*el zzz.cs
/s*l aa./s*l
csc 3t,library zzz.cs
csc a.cs 3r,zzz.*ll
a

Output
244025452.doc 43 od 274
1-

race Output
Soap re5uest
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1--"1i*
"1abc*
"1soap::od'*

Soap 4esponse
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"1abc4esponse*
"1soap::od'*

Since majority of the commands need to be reiterated, we create a batch fle named
z.bat to contain them. In this fle, we initially delete all the output fles that have been
created earlier, and then, we call WSDL to create a proxy in the fle zzz.cs.

The only parameter furnished to the WSDL program is the fle aa.wsdl. We hereby
restate that the wsdl fle is created by the web server, after it has read the asmx fle. The
proxy zzz.cs is then compiled to a dll, so that it may be used as a reference while
creating the client executable named a.exe.

On running the client program 'a', the trace program exhibits the value of 100 in SOAP
Request, and the value of 10 in the SOAP Response. i is set to 10 in the asmx fle.
In the SOAP Request, the value of b i.e. 100, is sent across as the content of i. In the
response packet, the value of 10 is sent across as the content of element i. There is no
return value, because the abc function in the asmx fle returns void.

Finally, in the C# code generated by the WSDL program, the abc function accepts a
single ref parameter named i. The name of the parameter remains the same like the one
in asmx fle.

4n zzz.cs
public v)i* abc(reK int i)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+ {i});
i " ((int)(results&7+));
}

The invoke function is called, with the second parameter as an array of one int. The
return value stored in the array results[0], is type cast to an int and assigned to the ref
parameter i. Previously, this value had been returned back. The entire exercise provides
ample evidence of the fact that a ref parameter is visible in both, the response and
request packets.

Let us now unveil the mechanism by means of which, an array is transmitted from a
client to the server. The abc function in the asmx fle accepts an array of ints in the
variable i, which is the sole parameter.

a.asmx
244025452.doc 44 od 274
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(int &+ i)
{
}
}

4n aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8" N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
xmlns,s<""(ttp,33tempuri.)rg31bstract:ypes" target9amespace""(ttp,33tempuri.)rg3"
xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s7,1rray;K4nt" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""1rray;K4nt"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""int" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"% <s,c)mplex:ype 3% <3s,element%
<3s,sc(ema%
<s,sc(ema target9amespace""(ttp,33tempuri.)rg31bstract:ypes"%
<s,c)mplex:ype name""tring1rray"%
<s,c)mplex#)ntent mixe*""Kalse"%
<s,restricti)n base""s)apenc,1rray"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""tring" type""s,string" 3%
<3s,sePuence%
<3s,restricti)n%
<3s,c)mplex#)ntent%
<3s,c)mplex:ype%
<3s,sc(ema%
<3types%
<message name""abc)ap4n"% <part name""parameters" element""s7,abc" 3% <3message%
<message name""abc)ap;ut"% <part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3% <)utput message""s7,abc)ap;ut" 3% <3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz)ap" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"% <s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc"
style""*)cument" 3%
<input% <s)ap,b)*y use""literal" 3% <3input%
<)utput% <s)ap,b)*y use""literal" 3% <3)utput%
<3)perati)n%
244025452.doc 45 od 274
<3bin*ing%
<service name""zzz"% <p)rt name""zzz)ap" bin*ing""s7,zzz)ap"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt% <3service%
<3*eKiniti)ns%

Henceforth, in order to keep this book trim, we shall exhibit only the variations in the
fle, instead of the entire fle, unless required otherwise. We normally delete the element
block containing the words HttpGet and HttpPost from the wsdl fle. This block is
created by the server, while the asmx fle is being loaded in the browser window.

In the wsdl fle, the abc element reveals a complexType with a sequence. This is the
same as before. The 'nillable' attribute determines whether a value of 'null' is
permissible or not.

<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s7,1rray;K4nt" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
However, the array element i, now has the type attribute initialized to an ArrayOfInt.
This type does not originate from the XML Schema namespace, since XML Schemas do
not contain any arrays. But in future, if the XML world decides to support arrays, the
WSDL world is sure to voluntarily take away its support for arrays. The next element
defnition creates complexType with a name of ArrayOfInt.

<s,c)mplex:ype name""1rray;K4nt"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""int" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%

Here, unlike in the earlier case, the complexType element has been assigned a name,
thereby, facilitating its reuse in the fle. The element within the sequence of
complexType has been named int. The minOccurs has a value of zero, which is
indicative of the fact that the element is optional. The maxOccurs has a value of
'unbounded', allowing an indefnite count of int child elements. Finally, the type is
specifed as an int, which is one of the predefned data types of the XML Schema.

<s,sc(ema target9amespace""(ttp,33tempuri.)rg31bstract:ypes"%
<s,c)mplex:ype name""tring1rray"%
<s,c)mplex#)ntent mixe*""Kalse"%
<s,restricti)n base""s)apenc,1rray"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""tring" type""s,string" 3%
<3s,sePuence%
<3s,restricti)n%
<3s,c)mplex#)ntent%
<3s,c)mplex:ype%
<3s,sc(ema%

244025452.doc 46 od 274
There is one more schema root element, which belongs to the targetNamespace. The
name of the complexType is StringArray, and it commences with a complexContent
element. The responsibility of this element is to interpret mixed content.

The mixed attribute has a default value of 'false'. The value assigned to this attribute
resolves whether character data is permitted between child elements or not.

The 'restriction' element permits the use of an existing type, but it confnes the range
values that it can assume. Here, the base type that is to be restricted, is the Array type
from the soapenc namespace.

It is pertinent to note that the soapenc namespace deals with types that are not
embodied in the XML Schema defnition. The restriction element contains an element
called String, having the datatype of string, which can occur innumerable times. This
complexType has not been used anywhere in our program.

<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%

The return value for abc in the asmx fle is void. Therefore, the element named
abcResponse has a complexType, which contains no elements whatsoever.

In the client fle a.cs, an array variable b of type int is created, and thereafter, initialized
to the three values of 1, 3 and 5. The array is then supplied as a parameter to the
function abc.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int &+b ;
b " ne/ int&B+{<6B6E};
a.abc(b);
}
}

Run the batch fle named z.bat, and observe the output in the trace window.

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*
"int*1"1int*
"int*6"1int*
"int*D"1int*
"1i*
"1abc*

SOAP response
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*

244025452.doc 47 od 274
In the SOAP request, the child element is named as i, followed by the familiar element
int, as is observed in the WSDL fle. This acquaints us with the fact that the data type
of the array is an int. This name is not binding. In fact, any other name could have been
used in its place. It is the name of the parameter i that is of prime signifcance.

The SOAP response is empty, and in the time to come, we shall bore you stif, by making
a display of it. The fle zzz.cs or proxy makes for an interesting reading.

4n zzz.cs
public v)i* abc(
&ystem.Oml.erializati)n.Oml1rray4tem1ttribute ("int"6 4s9ullable"Kalse) + int&+ i)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {i});
}

The parameter i is tagged with an attribute named XmlArrayItemAttribute, which
specifes the name as int. Therefore, we see the word 'int' in the SOAP packet.

The property IsNullable establishes whether the array should be serialized in case it is a
null or otherwise. In this case, since the IsNullable property is initialized to 'false', only
the values shall be sent across. We shall anatomize and analyze this concept later.
a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(string &+ i 6 int &+ j)
{
}
}

The asmx fle now contains the same abc function, but the function now has two
parameters, i and j, which are arrays of type string and int, respectively.

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s7,1rray;Ktring" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" nillable""true" type""s7,1rray;K4nt" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""1rray;Ktring"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""string" nillable""true"
type""s,string" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,c)mplex:ype name""1rray;K4nt"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""int" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
244025452.doc 48 od 274
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%

In the truncated aa.wsdl fle, we frst observe the element abc with a sequence
containing two children i and j, of type ArrayOfString and ArrayOfInt, respectively. Both
the types belong to the namespace s0. The sequence of the elements is important.
Therefore, the elements i and j are in a predetermined order.

Then comes the complexType defnition for the ArrayOfString. It is analogous to the
ArrayOfInt defnition. The only distinction lies in the type attribute, which refers to a
string from the XML Schema namespace, and not to an int. The string and int are
predefned data types.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string&+b ;
int &+c ;
b " ne/ string&B+{".i"6"bye"6"9)"};
c " ne/ int&@+{<76@7};
a.abc(b6c);
}
}

The client program a.cs has two arrays b and c, declared to be of type string and int,
respectively. They are originally created with 3 and 2 members, respectively. They are
then initialized to some values; and thereafter, passed to the abc function.

SOAP re5uest
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*
"string*;i"1string*
"string*b'e"1string*
"string*(o"1string*
"1i*
"2*
"int*1-"1int*
"int*7-"1int*
"12*
"1abc*

The SOAP request in the trace output shows the two child elements in the correct
sequence, i.e. i followed by j.

The three string members are securely ensconced within the string element, and the int
child contains the second array.

4n zzz.cs
public v)i* abc(&ystem.Oml.erializati)n.Oml1rray4tem1ttribute("string"6 4s9ullable"true)+
string&+ i6 &ystem.Oml.erializati)n.Oml1rray4tem1ttribute("int"6 4s9ullable"Kalse)+ int&+ j)
244025452.doc 49 od 274
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {i6 j});
}

The zzz.cs fle also contains two array parameters with the same attribute as was
discussed in the earlier program. However, each attribute is allotted a distinct name.
There is hardly any diference between an array of strings and an array of ints.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(int &6+ i)
{
}
}
Error in :rowser
S'stem)E,ception: Met!od 333)abc can not be reKected) ///* S'stem)E,ception: Multi/
dimensional arra's are not supported) <se a 2agged arra' instead)

A multi dimensional array when used in the asmx fle, generates an error; it is so
because the concept of an array is not supported in WSDL. The best alternative that
comes to mind is the utilization of a jagged array. The function abc has now been
modifed to accept values into a jagged array.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(int&+&+ i)
{
}
}

Let us frst focus on the fle a.cs, in which the concept of a jagged array has been
explicated with considerable lucidity.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int&+&+ b " ne/ int&@+&+ { ne/ int&+ {<6@6B}6 ne/ int&+ {H6E} };
a.abc(b);
}
}

In a.cs, frst an array of size two is created. Then, the two arrays are initialized to arrays
of ints; with one having three members, and the other having two members. The
contents of the aa.wsdl fle are indeed quite attention grabbing!

4n aa./s*l
244025452.doc 50 od 274
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s7,1rray;K1rray;K4nt" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""1rray;K1rray;K4nt"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""1rray;K4nt" nillable""true"
type""s7,1rray;K4nt" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,c)mplex:ype name""1rray;K4nt"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""int" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%

Only one element i, of type ArrayOfArrayOfInt, is visible in the fle. A few lines later, the
type is specifed as a complexType. It has one member ArrayOfInt, whose type is also
ArrayOfInt. Thereafter, the type ArrayOfInt is created to accept a single element int, of
type int, from the XML Schema type.

The element i has minOccurs of 1 and maxOccurs of 1, thereby, making its presence
obligatory. The other types have the values for the attributes minOccurs and
maxOccurs assigned in such a manner, that they could contain values ranging from
none to infnity!

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*
"Arra'O.Int*
"int*1"1int*
"int*7"1int*
"int*6"1int*
"1Arra'O.Int*
"Arra'O.Int*
"int*="1int*
"int*D"1int*
"1Arra'O.Int*
"1i*
"1abc*

The SOAP request launches with the parameter name i, followed by an element called
ArrayOfInt, as specifed by the WSDL fle. There are two ArrayOfInt child elements,
since the frst array has two members. The frst child has three int elements and the
second child has two int elements. The number of elements is contingent upon the size
specifed while they are being created in the fle. This is how the concept of a jagged
array is implemented in SOAP and WSDL.
244025452.doc 51 od 274

zzz.cs
public v)i* abc(&ystem.Oml.erializati)n. Oml1rray4tem1ttribute("1rray;K4nt"6 4s9ullable"true)+
&ystem.Oml.erializati)n.Oml1rray4tem1ttribute("int"6 4s9ullable"Kalse6 9esting!evel"<)+ int&+&+
i)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ { i});
}

The zzz.cs fle has two attributes as there are two arrays. The frst is an ArrayOfInt,
while the second is an int. The NestingLevel indicates that it is one level below the main
level. Earlier on, the attribute of XmlArrayItemAttribute had a single level.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
}

In this example, a simple object, which is an instance of class yyy, is passed as a
parameter to the function abc. Both the classes yyy and zzz are in the same asmx fle.
But they could have jolly well been separated, in other words, the class could have been
placed in a dll, in the bin folder. We have placed them in the same fle for the sake of
convenience. The class is absolutely empty, i.e. it has no properties or functions or
variables or for that matter, anything at all!

The wsdl fle provided by the web server has the element named abc with the complex
type named as a, having the type yyy, from the s0 namespace. The yyy complexType is
then defned as an empty type, since the class yyy does not contain any members.

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy" 3%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%

244025452.doc 52 od 274
The client program simply creates a yyy object 'b', and calls the function abc with the
object b as a parameter.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy b " ne/ yyy();
a.abc(b);
}
}

SOAP 4e5uest
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"a 1*
"1abc*
"1soap::od'*

The SOAP request displays the element a as the name of the parameter with empty
content, since the class yyy has no members. Also, the proxy generated contains the
function abc with the yyy object as a parameter. The Invoke function creates an array of
objects, with a single member named 'a'.

zzz.cs
public v)i* abc(yyy a)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
}
public class yyy
{
}

The next program demonstrates passing objects or reference types.
Here, there is a class yyy containing two int variables, i and j. The function abc returns
the sum of these two int variables.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(yyy a)
{
return a.i C a.j;
}
}
public class yyy
{
public int i6j;
}

The wsdl fle, like earlier, contains the same parameter 'a' as an element. But the
complexType defnition for yyy has undergone transformation. Earlier, it was an empty
244025452.doc 53 od 274
type, but now it contains the variables i and j, as elements in a sequence. It also has
attributes, which mandate their occurrence, once and only once.

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sc(ema%
<3types%

The client program creates a yyy object 'b', and then, initializes the i and j members to
10 and 20, respectively. Thereafter, it calls the function abc with the object 'b' as a
parameter. The return value, which obviously is 30, is stored in a variable named 'p' and
thereafter, it is displayed.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy b " ne/ yyy();
b.i " <7;
b.j"@7;
int p " a.abc(b);
ystem.#)ns)le.Write!ine(p);
}
}

Output
6-

The SOAP payload very clearly illustrates how an object is sent across in a SOAP
request.

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*
"i*1-"1i*
244025452.doc 54 od 274
"2*7-"12*
"1a*
"1abc*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*6-"1abc4esult*
"1abc4esponse*

Both the public members are serialized on the wire. This implies that the object 'b' is
not sent across. Instead, the values of the individual variables are dispatched. Thus, the
element 'a' carries the values 10 and 20, enveloped within elements i and j, respectively.

This highlights the fact that objects are passed by value, and not by reference. The
return packet graciously carries the value of 30 in the abcResult element.

zzz.cs
public int abc(yyy a)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
return ((int)(results&7+));
}
public class yyy
{
public int i;
public int j;
}

The proxy merely passes the yyy object 'a' to the Invoke function, and type casts the
return value to an int. The only variation incorporated here is that, the class yyy has
two public variables, i and j.

In this slightly larger asmx fle, the class yyy contains a public variable i, a private
variable j, and a protected variable k. Further, three public properties i1, i2 and i3 are
also present.


a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int abc(yyy a)
{
a.i " <777;
return a.i@;
}
}
public class yyy
{
public int i;
private int j;
pr)tecte* int 5;
public int i<
{
get
{
244025452.doc 55 od 274
return <<;
}
set
{
}
}
public int i@
{
get
{
return <@;
}
}
public int iB
{
set
{
}
}
}

Since the variables j and k are not marked as public in the proxy named zzz.cs, the
class yyy displays only the variable i. Thus, only public members are serialized,
whereas, protected and private members are not.

zzz.cs
public class yyy
{
public int i;
public int i<;
}

Furthermore, only the property of i1 is visible, since it is in possession of both, a get
and a set accessor. The properties of i2 and i3 have only one accessor. Therefore, they
are not taken into consideration. In order to be serialized, properties have to be both,
public and read/write.

The wsdl fle depicts the element 'a' as before, with the type yyy. The complex type yyy
now holds two elements named i and i1, in a specifc sequence.

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""i<" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
244025452.doc 56 od 274
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sc(ema%
<3types%

The rules that apply to a proxy are binding on the wsdl fle too. Only public members
and properties containing both, the accessors of get and set, are visible. Technically,
there is no concept of a 'property' in a wsdl fle. Thus, in the context of a wsdl fle, there
is no clear-cut distinction between properties and variables.

The abcResponse element is not afected by the introduction of the new instance
variables and properties.

The client can only initialize the members of i and i1. The other two variables, j and k
cannot be accessed, since they remain out of bounds or of-limits. The property i3 has a
set accessor and therefore, this too cannot be accessed. Besides, there is no indication
of a variable by that name in the class yyy, within the zzz.cs fle.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy b " ne/ yyy();
b.i " HE7;
b.i< " HE;
int p " a.abc(b);
ystem.#)ns)le.Write!ine(p);
ystem.#)ns)le.Write!ine(b.i);
}
}

Output
17
=D-

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*
"i*=D-"1i*
"i1*=D"1i1*
"1a*
"1abc*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*17"1abc4esult*
"1abc4esponse*

The SOAP request is straightforward, wherein, the values of 450 and 45 are ensconced
in the elements of i and i1. The names of the elements are the same as in the class yyy,
within the a.asmx fle.

244025452.doc 57 od 274
The return value that too is sent across is 12. This is the value that the property i2
returns. Thus, we are permitted to return the value of a property, since properties
behave like variables, but they contain barrels full of code. The code for the property
dwells on the server. Thus, the client need not lose sleep over its execution.

The server modifes the value of the variable i to 1000. However, this change is not
refected in any way in the SOAP response that is dispatched across.

Objects are sent across as values. Thus, there is no mechanism, by means of which,
this change that is efected by the server, can be passed onto the client. The return
statement explicitly has the property of i2. Hence, the value that is displayed on the
screen and is transported across, is 12.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public yyy(int i)
{
}
}

Error
''' cannot be seriali3ed because it does not !ave a de.ault public constructor)

E,ception Eetails: S'stem)E,ception: ''' cannot be seriali3ed because it does not
!ave a de.ault public constructor)

The above asmx fle throws an exception. This is because the class yyy now has a
constructor with an int parameter. With the introduction of this, the free constructor
that has no parameters, gets swept of its feet. Every object that gets serialized, must
have a public constructor taking no parameters.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public yyy(int i)
{
}
public yyy()
244025452.doc 58 od 274
{
}
}

zzz.cs
public class yyy
{
}

When we add the constructor having no parameters to the asmx fle, the error vanishes.
However, the proxy that is generated, ignores the constructors completely, and generates
an empty class altogether.

This demonstrates the fact that a constructor which has no parameters, is worthless,
since the proxy class would not refect such a constructor in the class. This is for the
reason that the WSDL language is devoid of adequate intelligence, to be able to handle
functions.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public int t(is&string a+
{
get
{
return <77;
}
set
{
}
}
}
zzz.cs
public class yyy
{
}

The concept of an indexer is also not passed on to the WSDL fle. Hence, there is no
sign of it in the proxy also. Thus, despite the presence of a valid indexer in the class yyy
of public access with a get and set accessor, it is not refected in the proxy fle zzz.cs.
This substantiates the fact that indexers are incapable of being activated remotely.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
public v)i* abc(yyy a)
{
}
244025452.doc 59 od 274
}
public class yyy
{
public static int i;
public rea*)nly int 5;
}

zzz.cs
public class yyy
{
public int 5;
}

The static variable i does not exist in the class yyy. Only the 'read only' variable k is
present in the class, but it is without the 'read only' attribute. However, we are not
allowed to change the value of the variable k in the function abc, since the class yyy has
been informed about the 'read only' attribute in the asmx fle.

The main aim of analyzing the above programs is to demonstrate that, not all data types
can be used in the asmx fle.
a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public int i;
}
public class xxx , yyy
{
public int j;
}

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%


zzz.cs
244025452.doc 60 od 274
public class yyy
{
public int i;
}

The asmx fle has the abc function, which accepts a yyy object. The class yyy has been
created to contain a single variable i of datatype int. Also, another class named xxx is
defned in the fle, which derives from class yyy. The xxx class contains an int variable
named j. So far so good!

The aa.wsdl fle, as always, contains the initial set of statements, along with the
parameter 'a' of type yyy. The complex type named yyy has a single element, which is an
int named i. There is no trace of the class xxx in the entire fle. As the proxy is created
from the contents of the wsdl fle, the zzz.cs fle too has no reference to the class xxx. It
only contains information about the members of class yyy. These are the perils of
working with beta software!

In the next program, the only change that has been incorporated is, the addition of a
function called pqr, in the existing asmx fle. It accepts an instance of class xxx as a
parameter.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
&Web'et()*+
public v)i* pPr(xxx b)
{
}
}
public class yyy
{
public int i;
}
public class xxx , yyy
{
public int j;
}

The wsdl fle now contains many new statements as a outcome of the introduction of
the function pqr.

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
244025452.doc 61 od 274
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""pPr"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""b" nillable""true" type""s7,xxx" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""xxx"%
<s,c)mplex#)ntent mixe*""Kalse"%
<s,extensi)n base""s7,yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,extensi)n%
<3s,c)mplex#)ntent%
<3s,c)mplex:ype%
<s,element name""pPr=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%

As before, the element abc has a single parameter 'a', of type yyy. The complexType for
the yyy type, has an element i of type int.

Next, we encounter the empty abcResponse element. Every function with a WebMethod
attribute is represented by an element in the wsdl world. Therefore, the element pqr is
visible in the fle. This element has an element b of type xxx.

Instead of the regular sequence, the complex type xxx has a complexContent element. A
new element by the name of 'extension' is located within the complexContent element.
Unlike 'restriction' that restricts values, the element 'extension' simply extends the base
attribute, i.e. a class. Thus, the xxx complexType extends the complexType class. The
symbol of colon, used for derivation in C#, is neatly replaced by the word 'extension'.
With this extension element, all the members of the class xxx can be specifed.
Presently, we have only one member called j, of type int. The pqrResponse element
requires no explanation, since it is empty.

In the client program, we do things a little diferently. Instead of creating a yyy object,
we create an xxx object.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
xxx c " ne/ xxx();
244025452.doc 62 od 274
c.i " <7;
c.j " @7;
a.abc(c);
}
}

The two members of class xxx, viz. i from yyy and j from class xxx, are initialized after
creating an instance of class xxx. The function abc is passed an xxx object, and not a
yyy object, as specifed in the function parameter list. This does not bring about any
error because, wherever a base class is specifed, a derived class can be used
interchangeably.

The question that crops up at this stage is that- On receiving the SOAP packet, how is
the asmx fle able to establish that the original object is of type xxx and not of yyy?

The SOAP request utilizes a feature of the XML schema world, wherein it seeks out an
attribute called type, in the xsi namespace. This attribute specifes the run time data
type of the object.

;1- rePuest
<abc xmlns""(ttp,33tempuri.)rg3"%
<a xsi,type""xxx"%
<i%<7<3i%
<j%@7<3j%
<3a%
<3abc%

Thus, the proxy class reveals both the classes of yyy and xxx, and the fact that the xxx
class is derived from yyy.

zzz.cs
&ystem.Oml.erializati)n.Oml4nclu*e1ttribute (type)K(xxx))+
public class yyy
{
public int i;
}
public class xxx , yyy
{
public int j;
}
There is also an extra attribute called XmlIncludeAttribute, together with class yyy,
which is indicative of the fact that the yyy class is being used as a base class for the xxx
class.

Thus, when the server receives this packet, it is aware that the parameter 'a' has two
members i and j, and that it has received an xxx type and not the original yyy type.
Despite both i and j being received by the server in the function abc, only i can be
accessed and not j. An alternative approach would be to package only the members of
the yyy class across the wire.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
244025452.doc 63 od 274
&Web'et()*+
public v)i* abc(yyy a 6 xxx b 6 yyy c)
{
}
&Web'et()*+
public v)i* pPr(/// c)
{
}
}
public class yyy
{
public int i;
}
public class xxx , yyy
{
public int j;
}
public class /// , xxx
{
public int 5;
}

aa./s*l
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<s,element min;ccurs""<" max;ccurs""<" name""b" nillable""true" type""s7,xxx" 3%
<s,element min;ccurs""<" max;ccurs""<" name""c" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,c)mplex:ype name""xxx"%
<s,c)mplex#)ntent mixe*""Kalse"%
<s,extensi)n base""s7,yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,extensi)n%
<3s,c)mplex#)ntent%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""pPr"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""c" nillable""true" type""s7,///" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""///"%
<s,c)mplex#)ntent mixe*""Kalse"%
<s,extensi)n base""s7,xxx"%
<s,sePuence%
244025452.doc 64 od 274
<s,element min;ccurs""<" max;ccurs""<" name""5" type""s,int" 3%
<3s,sePuence%
<3s,extensi)n%
<3s,c)mplex#)ntent%
<3s,c)mplex:ype%
<s,element name""pPr=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%

In this program, one more class named www, derived from class xxx and which
contains a single variable k, has been added. The abc function takes three parameters:
The frst parameter is a yyy type.
The second is an xxx.
The third is yet again a yyy object.

The wsdl fle is a mirror image of the asmx fle. Thus, there are three child elements in
the abc element, viz. a, b and c, of type yyy, xxx and yyy, respectively.

The complexType yyy, as is usually the case, has a sequence with one element i of type
int. The complexType xxx has a complexContent, with an extension element that
extends the type yyy. There exists the newly added element j, similar to what was
observed in the earlier program. The newly introduced type is the www complexType. It
has been extended from the type xxx, and the sequence has an element k. Thus, all
extensions behave in a similar fashion.

In the client program a.cs, an object d of type www is created, and the three members i,
j and k of the object, are initialized to 100,200 and 300, correspondingly. This object d
is passed twice as a parameter to the function abc.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
/// * " ne/ ///();
xxx e " ne/ xxx();
*.i"<77;
*.j"@77;
*.5"B77;
e.i"<7;
e.j"@7;
a.abc(*6*6e);
}
}

One more object e, which is an instance of class xxx, is created and passed as the last
parameter to the function abc. This is accomplished after initializing the two members i
and j, to the values of 10 and 20, respectively. Bear in mind that the function requires
parameters in the sequence of yyy, xxx and yyy. There is no mention of a www object.

Now, we take a look at the SOAP request, where the function name abc is refected as
the main element.
244025452.doc 65 od 274

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
/ "a ,si:t'pe%&www&*
"i*1--"1i*
"2*7--"12*
"k*6--"1k*
"1a*
/ "b ,si:t'pe%&www&*
"i*1--"1i*
"2*7--"12*
"k*6--"1k*
"1b*
/ "c ,si:t'pe%&,,,&*
"i*1-"1i*
"2*7-"12*
"1c*
"1abc*

The packet displays the frst parameter 'a', which comprises of the values of 100, 200
and 300. However, in this case, the type attribute is initialized to the run-time data type
of a www object, and not of a yyy object.

The second parameter 'b' is a clone of 'a'. Here too, the run-time data type is www, in
place of xxx. The third parameter 'c' is expected to be a yyy data type. However, we have
provided an xxx data type. Hence, the type attribute shows the type as xxx. The Invoke
function in the proxy, does not show any variation at all.

zzz.cs
public v)i* abc(yyy a6 xxx b6 yyy c)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {a6 b6 c});
}

&ystem.Oml.erializati)n.Oml4nclu*e1ttribute(type)K(xxx))+
&ystem.Oml.erializati)n.Oml4nclu*e1ttribute(type)K(///))+
public class yyy
{
public int i;
}
&ystem.Oml.erializati)n.Oml4nclu*e1ttribute(type)K(///))+
public class xxx , yyy
{
public int j;
}
public class /// , xxx
{
public int 5;
}

The class yyy is now used as a base class for the two classes, xxx and www. For the very
same reason, the 'include' attribute is repeated twice. The class www derives only from
xxx. Hence, the 'include' attribute is used only once.

In the next round, we deter from making any amendment to the asmx fle. Therefore,
the wsdl fle and the proxy, remain the same.

a.cs
244025452.doc 66 od 274
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy c " ne/ xxx();
xxx * " ne/ ///();
yyy e " ne/ ///();
c.i " <;
*.i " @7;
e.i " B7;
a.abc(c6*6e);
}
}

;1- rePuest
<a xsi,type""xxx"%
<i%<<3i%
<j%7<3j%
<3a%
G <b xsi,type""///"%
<i%@7<3i%
<j%7<3j%
<5%7<35%
<3b%
G <c xsi,type""///"%
<i%B7<3i%
<j%7<3j%
<5%7<35%
<3c%
<3abc%

The client program creates a yyy object c, but initializes it to an xxx object. Thus, its
run time data type is xxx, and not yyy. It has only one member viz. i, that is initialized
to 1. As the data type of c is yyy, initializing the j member will result in a compiler error.

Thereafter, c is passed as the frst parameter to the function. The SOAP request displays
the type attribute having a value of xxx, and the element j with the content as 0. In an
object, un-initialized variables are always assigned a value of zero.
The second parameter d is an xxx object, which is initialized to a higher object named
www. Both the variables of i and j could have been initialized, but we chose to ignore j.
In the SOAP request for d, we see the run-time data type of www. Further, the default
values of both j and k are zero.

The last parameter 'e' to function abc, is of type yyy, but it is initialized to a www
instance. The SOAP request reveals the type attribute of www for the last parameter,
with its three child elements. The last two elements j and k, possess the value of 0.

Thus, the run time data type is more dependent upon the type of object that the
variable is initialized to, rather than the static data type that is used while creating the
variable. Also, the type attribute selects the child elements that are serialized or carried
across the wire.

The next program illustrates how interfaces can be used in an asmx fle. In the asmx
fle, the class yyy is derived from iii interface. In order to be technically on the right side
of WSDL, the function abc is provided with the iii interface, together with the yyy object.
244025452.doc 67 od 274

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(iii i 6 yyy a)
{
}
}
public interKace iii
{
}
public class yyy , iii
{
public int i;
}


The wsdl fle shows two child elements in the element abc, containing the types iii and
yyy. The complexType iii has an attribute called 'abstract', which is set to true. This
indicates that no element can use this complexType directly. Further, only a
complexType can derive from it. However, the default value is false.

Thus, the wsdl is an aide memoir or reminder to us that we are dealing with an
interface, rubbing the fact in, that interfaces are incapable of holding felds directly.

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s7,iii" 3%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""iii" abstract""true" 3%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%

zzz.cs
public abstract class iii
{
}
&ystem.Oml.erializati)n.Oml:ype1ttribute(9amespace""(ttp,33tempuri.)rg3")+
public class yyy
{
public int i;
}

244025452.doc 68 od 274
The proxy fle zzz.cs displays the interface converted into an abstract class iii. Also, the
yyy class is not derived from the abstract class, but it contains the members of the
interface. This substantiates the fact that the interface is not used in the program. All
this leads to a sole inference that, at this stage, interfaces are totally forbidden in an
asmx fle.

After having touched upon the concept of interfaces, let us examine structures. In C#,
the basic data types, such as int and char are termed as 'value data types', and not as
'reference data types'. They are employed wherever speed and efciency are of prime
importance. The struct data type in C# is a value data type. All value data types are
created on the stack.

The function abc in the asmx fle, accepts a single parameter of type yyy structure.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public struct yyy
{
public int i6j;
}

The wsdl fle has one child element 'a' of type yyy, which in turn, is a complexType
having two elements, i and j. Thus, there is no dissimilarity whatsoever, between a class
and a struct in the wsdl fle. Furthermore, there is no entity that diferentiates between
a class and a struct, in the wsdl vocabulary.
aa./s*l
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%

We now shift our focus upon the client program. Semantically, there is no dissimilitude
between a class and a structure. As before, the 'new' keyword is employed to create the
variable 'b', thereby, eliminating all the diferences that a class may have from a struct.
The yyy entity has all the looks and feel of a class.

244025452.doc 69 od 274
a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy b " ne/ yyy();
b.i " <7;
b.j " @7;
a.abc(b);
}
}

The object 'b' can be created only with the help of the 'new' keyword.

In normal programming, a struct entity does not employ the 'new' keyword. Therefore, it
is prudent not to use structures in the asmx fle, since wsdl is devoid of any such
notation, which may aid in describing structures. A wsdl fle contains only value types.

The proxy that is generated, is also of the belief that the yyy entity is a class, and not a
struct. With the exception of one small variation wherein, one extra Attribute named
XmlElementAttribute has been added to the parameter 'a', everything else remains
unaltered. The XmlElementAttribute attribute merely conveys that the parameter 'a' will
be serialized as an element, and would not be considered as an attribute.

zzz.cs
public v)i* abc(&ystem.Oml.erializati)n.Oml>lement1ttribute (4s9ullable"Kalse)+ yyy a)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
}
public class yyy
{
public int i;
public int j;
}

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
/ "a*
"i*1-"1i*
"2*7-"12*
"1a*
"1abc*

There is nothing exceptional about the SOAP request. The data values of 10 and 20 are
sent across, as is always done.

The next program demonstrates how an array of objects is sent to and fro, while being
used in an asmx fle.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy &+ a)
244025452.doc 70 od 274
{
}
}
public class yyy
{
public int i6j;
}

The function abc is granted an array of yyy objects as a parameter. The class yyy
consists of two public variables i and j, of data type int.

The wsdl fle displays the usual element 'a', of type ArrayOfyyy. This is the name of a
type, and the actual name per se, is of no signifcance. Had it been named as 'bbb', in
place of ArrayOfyyy, the complexType would have been of the same name, in that case.

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true" type""s7,1rray;KSyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,c)mplex:ype name""1rray;KSyy"%
<s,sePuence%
<s,element min;ccurs""7" max;ccurs""unb)un*e*" name""yyy" nillable""true" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" type""s,int" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,sc(ema%

The type ArrayOfyyy is made up of a sequence of two int type elements i and j. They are
allotted attributes, with values that sanction only one occurrence of each. However, the
element 'a' may have as many occurrences as is deemed ft.

In the client program, an object 'b', which is an array of two yyy objects, is created
using the 'new' keyword. Thereafter, the two yyy objects, b[0] and b[1], are created
individually and their members are initialized. An array of objects when considered
individually, is similar to a simple object. Thus, the objects b[0] and b[1] are treated in
much the same way, as any other simple object.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy &+ b " ne/ yyy&@+;
b&7+ " ne/ yyy();
b&7+.i " <;
b&7+.j " @;
244025452.doc 71 od 274
b&<+ " ne/ yyy();
b&<+.i " <7;
b&<+.j " @7;
a.abc(b);
}
}

zzz.cs
public v)i* abc(&ystem.Oml.erializati)n.Oml1rray4tem1ttribute ("yyy"6 4s9ullable"true)+ yyy&+ a)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
}
public class yyy
{
public int i;
public int j;
}

The lone parameter 'a' in the proxy, has an attribute called XmlArrayItemAttribute. This
attribute has the capability of serializing derived types. Normally, the attribute is used
whenever the Xml Serializer has to serialize a derived class, after having specifed the
base class.

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
/ "a*
/ "'''*
"i*1"1i*
"2*7"12*
"1'''*
/ "'''*
"i*1-"1i*
"2*7-"12*
"1'''*
"1a*
"1abc*

Finally, in the SOAP payload, the child element 'a' is seen to contain two yyy children,
which carry the data of the individual arrays.

The next program demonstrates as to how enums are handled in wsdl fles.

An enum is purely a variable, which is capable of containing only a stipulated range of
values. The enum yyy contains only two values, viz. aa and bb. The abc function in the
asmx fle accepts this enum.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public yyy abc(yyy a)
{
return yyy.bb;
}
}
public enum yyy
{
244025452.doc 72 od 274
aa " <6
bb " @
}

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,simple:ype name""yyy"%
<s,restricti)n base""s,string"%
<s,enumerati)n value""aa" 3%
<s,enumerati)n value""bb" 3%
<3s,restricti)n%
<3s,simple:ype%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" type""s7,yyy" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""yyy" type""s7,yyy" 3%
<3s,sc(ema%

Most of the code in the wsdl fle, upto the element 'a', remains unchanged. However, you
would have noticed that 'simpletype' has been used in place of 'complex type', for the
type yyy.
The 'restriction' element imposes an additional limitation over and above the current
restriction, on the base type being a string. It permits only certain values within the
string type. These values are specifed by a child element enumeration. Since there are
only two such enumeration elements 'aa' and 'bb', the simpleType yyy can contain only
one of these two values.

Thus, an enum can be represented in wsdl, because the XML schema supports the
concept of enumeration. The function returns an enum. Therefore, the abcResponse
element does not remain empty. Observe the element called yyy, of type yyy, located at
the very end. This element is not being utilized anywhere.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
ystem.#)ns)le.Write!ine(a.abc(yyy.aa));
}
}

Output
bb

zzz.cs
244025452.doc 73 od 274
public yyy abc(yyy a)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
return ((yyy)(results&7+));
}
public enum yyy
{
aa6
bb6
}

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*aa"1a*
"1abc*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*bb"1abc4esult*
"1abc4esponse*

The client program a.cs merely accepts a member aa from the enum yyy, as a parameter
to the abc function. Subsequent to this, it displays the return value. The abc function in
the proxy has no surprises tucked up its sleeve. Here, the enum data type is seen
without the values that we specifed in the asmx fle.

The values specifed for the enum variables in the asmx fle, do not get carried over to
the proxy. It is so because they are available in the asmx fle. Thus, if you observe the
SOAP output, you will realize that it displays only the name of the enum 'aa' being sent
across, and not its value. Also, the SOAP response elicits that the packet contains the
enum name 'bb', and not its value.

The fnal example in this chapter deals with an XmlNode type as a parameter to the abc
function. An XmlNode represents an XML document.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Oml;
public class zzz
{
&Web'et()*+
public v)i* abc(Oml9)*e a)
{
}
}

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""a" nillable""true"%
<s,c)mplex:ype mixe*""true"%
<s,sePuence%
<s,any 3%
<3s,sePuence%
<3s,c)mplex:ype%
244025452.doc 74 od 274
<3s,element%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%

The abc function now receives an XML fle in a SOAP payload. The wsdl fle has an
element 'a', which like before, is devoid of a type attribute. It has a complexType element
that describes its type.

The attribute 'mixed' has a value of 'true', which permits character data for this type.
The 'any' element permits the use of elements from a specifed namespace. As no
namespace attribute has been specifed, the default gives access to elements that may
belong to any namespace.

a.cs
using ystem.Oml;
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
Oml0)cument * " ne/ Oml0)cument();
*.!)a*Oml("<vijay%"C "<mu5(i%.i <s)nal 3%Mye<3mu5(i%" C "<3vijay%");
Oml9)*e e " *.0)cument>lement;
a.abc(e);
}
}

The client program begins with a class that understands an Xml fle called
XmlDocument. The LoadXml member requires a string that represents an XML
document.

There is a root element called 'vijay', which is followed by a valid Xml fle. The property
DocumentElement allows access to the XmlNode that represents this Xml fle. This is
furnished as a parameter to the abc function.

zzz.cs
public v)i* abc(ystem.Oml.Oml9)*e a)
{
t(is.4nv)5e("abc"6 ne/ )bject&+ {a});
}

The proxy server understands XmlNode, since it can recognize any element in a wsdl
fle.

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*
"vi2a' ,mlns%&&*
"muk!i*
;i
"sonal 1*
:'e
244025452.doc 75 od 274
"1muk!i*
"1vi2a'*
"1a*
"1abc*
"1soap::od'*

The SOAP request starts with the name of the parameter 'a', followed by the root tag
'vijay'. The default namespace is set to null. Thereafter, the entire Xml Document is
passed as the content.

(hus, there is no di!!erence )etween assin+ an int or an o)-ect or an .*l !ile in a S/01
ac2et, )ecause the& are )oth sent across as textual content.
=
EataSets

The focus in this chapter once again veers on to web services, but in the context of
DataSets. A DataSet is a collection of DataTable objects, which in turn, embody data.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.0ata;
public class zzz
{
&Web'et()*+
public 0ataet abc()
{
0ata:able t " ne/ 0ata:able("vijay");
0ata#)lumn c;
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.4ntB@");
c.#)lumn9ame " "c<";
t.#)lumns.1**(c);
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.tring");
c.#)lumn9ame " "c@";
t.#)lumns.1**(c);
0ataet * " ne/ 0ataet();
*.:ables.1**(t);
return *;
}
}

The opening line in the abc function within the asmx fle, creates a DataTable object
called t. The parameter supplied to the constructor of the DataTable object is the name
of the table, 'vijay'.

Every DataTable object is composed of columns, wherein, every single column is
represented by a DataColumn object. After creating an instance c of the DataColumn
class, the DataType property in the DataColumn class is initialized to the data type of
the column, which in this case, is an int. Therefore, the static GetType function from
the Type class is called with the full name of the type as its parameter.

244025452.doc 76 od 274
The ColumnName property assigns a name to the column, which is c1 in this case. The
DataTable has a Columns Collection property called Columns, which stores all the
DataColumn objects. With the help of the Add function that is incorporated in it, the
column named c1 is added to the Columns collection.

As a consequence, the Columns property now holds one column. A fresh instance of the
DataColumn object is created with the DataType of string, and is named as c2. This
DataColumn object too is added to the columns collection. Thus, the collection now is
in possession of two columns, viz. c1 and c2. Finally, a DataSet d comprises of the
Tables collection property Tables and employs the services of the Add function within it,
to add the table t to the dataset.

A Polite Reminder

The steps to be taken in the order of succession, are as follows:
Enter the url as http://localhost/a.asmx?WSDL in the browser.
Copy the contents displayed on the browser into the fle aa.wsdl under the www
subdirectory.
Ensure that the frst line begins at the very frst column.

Change the url from http://localhost/a.asmx to http://localhost:8080/asmx.
Finally, start the Trace utility program from the SOAP toolkit program option, to view
the SOAP request and the SOAP response packets.
Run the batch fle, z.bat, stipulated in the previous chapter, in order to obtain the
output, as depicted in the chapter.

Now, let us closely scrutinize a DataSet representation in a wsdl fle. We have displayed
only the relevant portions of the fle, which are adequate for corroborating our
explanation.

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,imp)rt namespace""(ttp,33///./B.)rg3@77<3O'!c(ema" 3%
<s,element name""abc"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" nillable""true"%
<s,c)mplex:ype%
<s,sePuence%
<s,element reK""s,sc(ema" 3%
<s,any 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""0ataet" nillable""true"%
<s,c)mplex:ype%
<s,sePuence%
<s,element reK""s,sc(ema" 3%
244025452.doc 77 od 274
<s,any 3%

<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<3s,sc(ema%

The abc element is devoid of all content, as the function does not accept any
parameters. Next, we stumble upon and encounter a new element called 'import', which
introduces all the schema defnitions in the XmlSchema document, thereby, facilitating
references to them in the schema document.

In the element abcResponse, the element of abcResult has a complexType. The
complexType for the abcResult element contains two elements:
The frst element is the sequence, followed by another element, which currently has
no name or type. Instead, it has a ref attribute. By using the ref attribute, other
elements that were created earlier, are now accessible. In this case, a reference is made
to the 'schema' element.
The second element in the complex type is the element 'any', which permits access
to all elements from any namespace.

There is yet another element called 'DataSet', which has the 'schema' element and the
'any' element, just like the earlier element. A salient point that needs to be emphasized
here is that, in the wsdl representation of a DataSet object, there is neither any mention
of a table named 'vijay', nor is there any sign of the columns or other details, such as
the Primary Key, etc. The client program merely calls the abc function, without any
parameters.

a.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
a.abc();
}
}

The proxy code in zzz.cs dispatches back the Dataset that has been returned from the
abc function. The DataSet is saved in the frst member of the 'results' array.

zzz.cs
public ystem.0ata.0ataet abc()
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&7+);
return ((ystem.0ata.0ataet)(results&7+));
}

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*
",sd:sc!ema id%&(ewEataSet& target(amespace%&& ,mlns%&&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:msdata%&urn:sc!emas/
microso.t/com:,ml/msdata&*
",sd:element name%&(ewEataSet& msdata:IsEataSet%&true&*
",sd:comple,'pe*
244025452.doc 78 od 274
",sd:c!oice ma,Occurs%&unbounded&*
",sd:element name%&vi2a'&*
",sd:comple,'pe*
",sd:se5uence*
",sd:element name%&c1& t'pe%&,sd:int& minOccurs%&-& 1*
",sd:element name%&c7& t'pe%&,sd:string& minOccurs%&-& 1*
"1,sd:se5uence*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:c!oice*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:sc!ema*
"diLgr:diLgram ,mlns:msdata%&urn:sc!emas/microso.t/com:,ml/msdata&
,mlns:diLgr%&urn:sc!emas/microso.t/com:,ml/diLgram/v1& 1*
"1abc4esult*
"1abc4esponse*

A DataSet, as is represented in a SOAP payload, embodies all the relevant information.


The abcResult element commences with a child element called schema from the
XMLSchema namespace, as is indicated by the namespace prefx xsd. The msdata
namespace prefx is initialized to a uri. The value currently assigned to it is the one
furnished by Microsoft.

The schema element is normally assigned an id that represents the name of the
DataSet. However, since we have not supplied an id, the default name of NewDataSet
has been used. The targetNamespace and the default namespace are both set to null.

Within the schema, there exists an element with the same name of NewDataSet, but
this refers to the name of the DataSet, since the IsDataSet attribute is set to true.

The complexType that defnes the structure of the DataSet, contains a 'choice' element
that allows the selection of only one of the many elements that are present. In this case,
since there is only a single element named 'vijay', the choice element is of no utility at
all. For the uninitiated reader, we reiterate that 'vijay' is the name of a DataTable, as
specifed in the asmx fle.

The DataTable element, i.e. 'vijay' is capable of having multiple occurrences. It has a
sequence with two column names, c1 and c2. Assigning the value of zero to minOccurs
is indicative of the fact that it is not obligatory to specify their values.

The last element is called a difgram. A difgram is an XML serialization format that
carries both, the original as well as, the current data. This is pressed into service for
marshalling a dataset over. We shall delve deeper into this concept as we make a
headway in the book. Here, we have merely declared two namespaces, as there is no
data present in our table.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.0ata;
public class zzz
244025452.doc 79 od 274
{
&Web'et()*+
public 0ataet abc()
{
0ata:able t " ne/ 0ata:able("vijay");
0ata#)lumn c;
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.4ntB@");
c.#)lumn9ame " "c<";
t.#)lumns.1**(c);
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.tring");
c.#)lumn9ame " "c@";
t.#)lumns.1**(c);
0ata=)/ r " t.9e/=)/();
r&"c<"+ " <;
r&"c@"+ " "(i";
t.=)/s.1**(r);
r " t.9e/=)/();
r&"c<"+ " <77;
r&"c@"+ " "Mye";
t.=)/s.1**(r);
0ataet * " ne/ 0ataet("s)nal");
*.:ables.1**(t);
return *;
}
}

Here, we have not displayed the fles named aa.wsdl, a.cs and zzz.cs since the code
contained in them remains unaltered.

Soap response
"abc4esult*
",sd:sc!ema id%&sonal& target(amespace%&& ,mlns%&&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:msdata%&urn:sc!emas/
microso.t/com:,ml/msdata&*
",sd:element name%&sonal& msdata:IsEataSet%&true&*
"1,sd:element*
"1,sd:sc!ema*
"diLgr:diLgram ,mlns:msdata%&urn:sc!emas/microso.t/com:,ml/msdata&
,mlns:diLgr%&urn:sc!emas/microso.t/com:,ml/diLgram/v1&*
"sonal ,mlns%&&*
"vi2a' diLgr:id%&vi2a'1& msdata:rowOrder%&-& diLgr:!asC!anges%&inserted&*
"c1*1"1c1*
"c7*!i"1c7*
"1vi2a'*
"vi2a' diLgr:id%&vi2a'7& msdata:rowOrder%&1& diLgr:!asC!anges%&inserted&*
"c1*1--"1c1*
"c7*:'e"1c7*
"1vi2a'*
"1sonal*
"1diLgr:diLgram*
"1abc4esult*
"1abc4esponse*

After creating a DataRow object r, the NewRow function of the DataTable is put into
operation in order to introduce a fresh row. The indexers, with the names of the
columns c1 and c2, have been initialized to selected values, in order to fll up data in
the two columns. Finally, by employing the Rows collection, this newly initialized row is
added to the DataTable.
244025452.doc 80 od 274

This process is iterated to add another row to the DataTable 'vijay', thereby, resulting in
two rows in the table. The name of the Dataset is also changed to 'sonal'. However, no
variation is witnessed in either the wsdl fle or the proxy or the server because, the only
innovation efected was, the introduction of data into the DataTable.

In the SOAP response, the id of the schema and element refect the new value of 'sonal'.
We have not displayed the remaining portion of the schema fle, since it remains
unchanged.

The wsdl fle demonstrates that the abcResult element commences with a schema
element, which may then be followed by any other element, from any namespace. Here,
the SOAP response contains the difgram element, which creates the namespace
prefxes msdata and difgr. A difgram may contain data from multiple namespaces. The
next element is the dataset name 'sonal'.

A Dataset, in turn, is constituted of multiple tables. In addition to the above, there
exists another dataset called 'vijay'. Hence, an element called 'vijay' is created. This
element is assigned an id of vijay1, and the second record is allocated an id of vijay2.
The rowOrder attribute is akin to a row number, where the frst record is numbered as
0, the second as 1, and so on.

The hasChanges attribute is assigned the value of 'inserted'. This is followed by the data
of the row, enclosed within tags, comprising of the names of the columns. Accordingly, a
DataSet frst dispatches the schema, followed by the actual data.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.0ata;
public class zzz
{
&Web'et()*+
public 0ataet abc()
{
0ata:able t " ne/ 0ata:able("vijay");
0ata#)lumn c;
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.4ntB@");
c.#)lumn9ame " "c<";
t.#)lumns.1**(c);
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.tring");
c.#)lumn9ame " "c@";
t.#)lumns.1**(c);
0ata=)/ r " t.9e/=)/();
r&"c<"+ " <;
r&"c@"+ " "(i";
t.=)/s.1**(r);
r " t.9e/=)/();
r&"c<"+ " <77;
r&"c@"+ " "Mye";
t.=)/s.1**(r);
0ata:able t< " ne/ 0ata:able("mu5(i");
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.4ntB@");
244025452.doc 81 od 274
c.#)lumn9ame " "*<";
t<.#)lumns.1**(c);
c " ne/ 0ata#)lumn();
c.0ata:ype " ystem.:ype.?et:ype("ystem.tring");
c.#)lumn9ame " "*@";
t<.#)lumns.1**(c);
r " t<.9e/=)/();
r&"*<"+ " <777;
r&"*@"+ " "(i@B";
t<.=)/s.1**(r);
r " t<.9e/=)/();
r&"*<"+ " @777;
r&"*@"+ " "Mye@B";
t<.=)/s.1**(r);
0ataet * " ne/ 0ataet("s)nal");
*.:ables.1**(t);
*.:ables.1**(t<);
return *;
}
}

Soap response
"abc4esult*
",sd:sc!ema id%&sonal& target(amespace%&& ,mlns%&&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:msdata%&urn:sc!emas/
microso.t/com:,ml/msdata&*
",sd:element name%&sonal& msdata:IsEataSet%&true&*
",sd:comple,'pe*
",sd:c!oice ma,Occurs%&unbounded&*
",sd:element name%&vi2a'&*
",sd:comple,'pe*
",sd:se5uence*
",sd:element name%&c1& t'pe%&,sd:int& minOccurs%&-& 1*
",sd:element name%&c7& t'pe%&,sd:string& minOccurs%&-& 1*
"1,sd:se5uence*
"1,sd:comple,'pe*
"1,sd:element*
",sd:element name%&muk!i&*
",sd:comple,'pe*
",sd:se5uence*
",sd:element name%&d1& t'pe%&,sd:int& minOccurs%&-& 1*
",sd:element name%&d7& t'pe%&,sd:string& minOccurs%&-& 1*
"1,sd:se5uence*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:c!oice*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:sc!ema*
"diLgr:diLgram ,mlns:msdata%&urn:sc!emas/microso.t/com:,ml/msdata&
,mlns:diLgr%&urn:sc!emas/microso.t/com:,ml/diLgram/v1&*
"sonal ,mlns%&&*
"vi2a' diLgr:id%&vi2a'1& msdata:rowOrder%&-& diLgr:!asC!anges%&inserted&*
"c1*1"1c1*
"c7*!i"1c7*
"1vi2a'*
"vi2a' diLgr:id%&vi2a'7& msdata:rowOrder%&1& diLgr:!asC!anges%&inserted&*
"c1*1--"1c1*
"c7*:'e"1c7*
"1vi2a'*
"muk!i diLgr:id%&muk!i1& msdata:rowOrder%&-& diLgr:!asC!anges%&inserted&*
"d1*1---"1d1*
"d7*!i76"1d7*
244025452.doc 82 od 274
"1muk!i*
"muk!i diLgr:id%&muk!i7& msdata:rowOrder%&1& diLgr:!asC!anges%&inserted&*
"d1*7---"1d1*
"d7*:'e76"1d7*
"1muk!i*
"1sonal*
"1diLgr:diLgram*
"1abc4esult*

As before, aa.wsdl, a.cs and zzz.cs remain unchanged. Therefore, they are not displayed
again. The asmx fle, which now incorporates a voluminous code, has an additional
DataTable object named t1, which refers to the table named 'mukhi'.

Two columns named d1 and d2 are added to the table. They are of type int and string,
respectively. Thereafter, two records are added to this table and eventually, the table is
added to the table collections of the DataSet.
The wsdl fle merely contains information about a DataSet. It does not embody any
information about the schema or the data in the tables. The client and the proxy
remain unaltered for the same reasons as specifed in the earlier examples.

As is customary, the large SOAP packet that is sent across, commences with the
schema element. The id and the name of the frst child element are initialized to 'sonal',
where 'sonal' represents a DataSet, since the IsDataSet attribute is set to true.

Then the complexType describes the DataSet object 'sonal'. It enjoys the discretion of
selecting from amongst the two elements of 'vijay' and 'mukhi'. This is because the
DataSet object contains two tables with these names. The choice element permits the
selection of only one element from amongst available set of elements.

Each of the tables is followed by its data structure, comprising of the columns, along
with their data types, represented as child elements. The minOccurs, with a value of
zero, can be omitted in the SOAP payload, if so desired. The same rules also apply to
the second table called 'Mukhi'.

As per convention, the difgram starts with the name of the dataset i.e. 'sonal', with the
default namespace set to null. Two child elements, beginning with 'vijay' are visible,
since the table 'vijay' consists of two records or rows. The same holds good for the two
records in the table 'mukhi', thus, resulting in the display of two child elements with
the name of 'mukhi'.

To begin with, in the case of both the tables, the 'rowOrder' has the value 0, and the
'hasChanges' is assigned the value of 'inserted', for each of the four records.
Consequently, it is the rows of the table 'vijay' that are displayed frst, followed by the
rows of the table 'mukhi'.

The rest of the difgram, i.e. the content embodied in the column names, remains
unchanged. The id feld assigns a unique name to each and every record in the
difgram.


a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
244025452.doc 83 od 274
using ystem.Web.ervices;
using ystem.0ata;
using ystem.0ata.Pl#lient;
public class zzz
{
&Web'et()*+
public 0ataet abc()
{
0ataet * ;
Pl#)nnecti)n c " ne/ Pl#)nnecti)n("server"(l)cal)FF9et0L;*atabase"pubs;ui*"sa;p/*";");
Pl0ata1*apter *a " ne/ Pl0ata1*apter ("select R Kr)m 1ut()rs /(ere auTlname"UW(iteU"6c);
* " ne/ 0ataet("vijay");
*a.Dill(*6 "ppp");
return *;
}
}

SOAP response
"abc4esult*
",sd:sc!ema id%&vi2a'& target(amespace%&& ,mlns%&&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:msdata%&urn:sc!emas/
microso.t/com:,ml/msdata&*
",sd:element name%&vi2a'& msdata:IsEataSet%&true&*
",sd:comple,'pe*
",sd:c!oice ma,Occurs%&unbounded&*
",sd:element name%&ppp&*
",sd:comple,'pe*
",sd:se5uence*
",sd:element name%&auMid& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&auMlname& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&auM.name& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&p!one& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&address& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&cit'& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&state& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&3ip& t'pe%&,sd:string& minOccurs%&-& 1*
",sd:element name%&contract& t'pe%&,sd:boolean& minOccurs%&-& 1*
"1,sd:se5uence*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:c!oice*
"1,sd:comple,'pe*
"1,sd:element*
"1,sd:sc!ema*
"diLgr:diLgram ,mlns:msdata%&urn:sc!emas/microso.t/com:,ml/msdata&
,mlns:diLgr%&urn:sc!emas/microso.t/com:,ml/diLgram/v1&*
"vi2a' ,mlns%&&*
"ppp diLgr:id%&ppp1& msdata:rowOrder%&-&*
"auMid*1I7/67/11I@"1auMid*
"auMlname*W!ite"1auMlname*
"auM.name*Go!nson"1auM.name*
"p!one*=-0 =A@/I776"1p!one*
"address*1-A67 :igge 4d)"1address*
"cit'*Menlo Park"1cit'*
"state*CA"1state*
"3ip*A=-7D"13ip*
"contract*true"1contract*
"1ppp*
"1vi2a'*
"1diLgr:diLgram*
"1abc4esult*

244025452.doc 84 od 274
So far, the DataTable has been created manually, which is not a very pragmatic way of
working. An enhanced and workable mechanism would be, to have the DataSet created
automatically, while records are being fetched from a database. The DataSet class and
the classes related to it, originate from the 'System.Data' namespace, while the actual
Data handling classes emanate from the 'System.Data.SqlCient' namespace.

Firstly, d is created as an object that appears analogous to the DataSet class. Then, an
SqlConnection object is created with the connection string as a parameter to the
constructor. The string passed to the constructor, determines the table in the database
on SQL Server, with which a connection is to be established. A database is a mere
collection of tables. The tables that hold our interest are contained in a database called
pubs. Finally, the userid and password are specifed. These individual pieces of data are
separated by semi-colons and contain the words 'server', 'uid' and 'pwd', which are
reserved by SQL Server. Thus, we are compelled to employ these words.

The Authors table lies in the 'pubs' database and is installed by the .NET samples.
While the installation of the samples is in progress, the InstMSDE program installs a
server on every machine. In our case, the server that has been installed is 'localhost'.

Next, an SqlDataAdapter object is created where the constructor accepts an SQL select
statement and the newly created SqlConnection object. Further, the DataSet object is
instantiated with the name 'vijay', provided through the constructor. The Fill function in
the SqlDataAdapter initiates the retrieval of data from the database.

Firstly, a connection is actually made to the table in the database. Then, the select
statement retrieves all the records from the Authors table, where the feld au_lname in
the record has a value of 'White'. If the 'where' clause is not been specifed, it would
result in the extirpation of all the records from the table.

The Fill function flls up the DataSet object d, which is passed as the frst parameter.
The data retrieved from the Authors table is named as ppp, which is the second
parameter. Finally, the DataSet contains a single table, which is despatched across the
wire.

The SOAP response is not disconcerted about the source of the data, i.e. whether the
data originates from a database or it has been entered manually. As always, it displays
the name of the dataSet 'vijay', followed by the second parameter of the Fill function, i.e.
ppp. This is followed by the innumerable names of the felds from the Authors table,
comprising of the entire data schema. Details, such as the relationships amongst
tables, the Primary Key etc., are not disclosed. The difgram simply specifes the
DataSet name 'vijay', and a single element ppp, with all the data posited within the
columns. Now, we progress and press on to a simple example using a DataGrid.
a.asmx
<%@ Webervice !anguage""#$" class""ccc" %%
using ystem.Web.ervices;
using ystem.0ata;
using ystem.0ata.Pl#lient;
public class ccc , Webervice {
&Web'et()*+
public 0ataet abc()
{
244025452.doc 85 od 274
0ataet * " ne/ 0ataet();
Pl#)nnecti)n c) " ne/
Pl#)nnecti)n("server"(l)cal)FF9et0L;*atabase"n)rt(/in*;:ruste*T#)nnecti)n"yes");
Pl0ata1*apter c " ne/ Pl0ata1*apter("elect R Kr)m #ust)mers"6 c));
c.Dill(*6 "pPr");
return *;
}
}

zzz.cs
using ystem;
using ystem.0ra/ing;
using ystem.Win*)/s.D)rms;
using ystem.0ata;
public class zzz , D)rm {
0ata?ri* *;
public zzz()
{
#lientize " ne/ ize(I776 H<B);
ccc c " ne/ ccc();
0ataet *s " c.abc();
* " ne/ 0ata?ri*();
*.ize " ne/ ize(E8H6 BBI);
*.!)cati)n " ne/ -)int(86 8);
*.0ata)urce " *s;
*.0ata'ember " "pPr";
#)ntr)ls.1**(*);
}
public static v)i* 'ain() {
1pplicati)n.=un(ne/ zzz());
}
}
s.bat
*el R.exe
*el R.*ll
/s*l.exe 3l,# aa.W0!
csc.exe 3t,library ccc.cs
csc.exe zzz.cs 3r,ccc.*ll
zzz

244025452.doc 86 od 274
Screen 4.1

Within this asmx fle, there exists a function abc, which merely returns a DataSet that
is loaded with the records from the Customers table. Thereafter, to create a wsdl fle
from the above asmx fle, the URL of http://localhost/a.asmx?WSDL is specifed in the
browser. The fle contents are saved in aa.wsdl.

Once this has been accomplished, the batch fle s.bat is run, in order to execute a
series of commands. The proxy code in the fle ccc.cs contains a class ccc, which is
referred to extensively in the client program zzz.cs.

For those of you who have not read our book on WinForms, it is important to know that
the client program zzz.cs is a Windows applications, which displays a DataGrid control
in a window. This DataGrid object d has a property called DataSource, which is
initialized to a DataSet object that contains the data displayed by the data grid. The
DataMember property, when specifed, refers to the name of the table in the data set,
whose data is to be displayed. In this case, the name of the table is 'pqr'.

Thus, it is amply evident that the program is strikingly similar to the earlier programs;
the only dissimilarity being that the DataSet feeds a DataGrid object. The code in the
asmx fle that actually fetches or creates the DataSet, remains unaltered when
employed by any application. This is due to the fact that the DataSet ds gets initialized
by the code in the abc function.

If you are desirous of acquiring enhanced conceptual clarity, the most optimum
technique would be to modify the port number of localhost to 8080, and then, view the
packets in the output window of the Trace program. The SOAP response packet displays
the data in a similar fashion, as was witnessed earlier.

Master-Detail Relationships:

244025452.doc 87 od 274
a.asmx
<%@ Webervice !anguage""#$" class""ccc" %%
using ystem.Web.ervices;
using ystem.0ata;
using ystem.0ata.Pl#lient;
public class ccc , Webervice
{
&Web'et()*+
public 0ataet abc()
{
0ataet c " ne/ 0ataet();
Pl#)nnecti)n c) " ne/
Pl#)nnecti)n("server"(l)cal)FF9et0L;*atabase"n)rt(/in*;:ruste*T#)nnecti)n"yes");
Pl0ata1*apter a< " ne/ Pl0ata1*apter("elect R Kr)m #ust)mers"6 c));
Pl0ata1*apter a@ " ne/ Pl0ata1*apter("elect R Kr)m ;r*ers"6 c));
a<.Dill(c6 "#ust)mers");
a@.Dill(c6 ";r*ers");
return c;
}
}

aa.xs*
<xs*,sc(ema i*""*<" target9amespace""" xmlns"""
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema" xmlns,ms*ata""urn,sc(emasGmicr)s)KtG
c)m,xmlGms*ata"%
<xs*,element name""#ust)mers"%
<xs*,c)mplex:ype%
<xs*,all%
<xs*,element name""#ust)mer40" type""xs*,string"3%
<3xs*,all%
<3xs*,c)mplex:ype%
<3xs*,element%
<xs*,element name"";r*ers"%
<xs*,c)mplex:ype%
<xs*,all%
<xs*,element name"";r*er40" ms*ata,=ea*;nly"":rue" ms*ata,1ut)4ncrement"":rue"
type""xs*,int"3%
<xs*,element name""#ust)mer40" min;ccurs""7" type""xs*,string"3%
<3xs*,all%
<3xs*,c)mplex:ype%
<3xs*,element%
<xs*,element name""***" ms*ata,4s0ataet""true"%
<xs*,c)mplex:ype%
<xs*,c()ice max;ccurs""unb)un*e*"%
<xs*,element reK""#ust)mers"3%
<xs*,element reK"";r*ers"3%
<3xs*,c()ice%
<3xs*,c)mplex:ype%
<xs*,uniPue name""#)nstraint<" ms*ata,-rimaryLey""true"%
<xs*,select)r xpat("".33#ust)mers"3%
<xs*,Kiel* xpat(""#ust)mer40"3%
<3xs*,uniPue%
<xs*,5eyreK name""ppp" reKer""#)nstraint<"%
<xs*,select)r xpat("".33;r*ers"3%
<xs*,Kiel* xpat(""#ust)mer40"3%
<3xs*,5eyreK%
<3xs*,element%
<3xs*,sc(ema%

zzz.cs
using ystem;
using ystem.Win*)/s.D)rms;
using ystem.0ra/ing;
244025452.doc 88 od 274
using ystem.0ata;
public class zzz , D)rm
{
*** *;
0ata?ri* *@;
0ata?ri* *<;
public zzz()
{
*@ " ne/ 0ata?ri*();
* " ne/ ***();
*< " ne/ 0ata?ri*();
*@.!)cati)n " ne/ -)int(86 @EI);
*@.:ext " "*@";
*@.ize " ne/ ize(E8H6 @H8);
*@.D)re#)l)r " ystem.0ra/ing.ystem#)l)rs.Win*)/:ext;
*@.Mac5#)l)r " ystem.0ra/ing.ystem#)l)rs.Win*)/;
*@.0ata)urce " *;
*@.0ata'ember " "#ust)mers.ppp";
*<.!)cati)n " ne/ ystem.0ra/ing.-)int(86 8);
*<.:ext " "*<";
*<.ize " ne/ ize(E8H6 @H7);
*<.D)re#)l)r " ystem.0ra/ing.ystem#)l)rs.Win*)/:ext;
*<.Mac5#)l)r " ystem.0ra/ing.ystem#)l)rs.Win*)/;
*<.0ata)urce " *;
*<.0ata'ember " "#ust)mers";
:ext " "#ust)mer ;r*ers";
#lientize " ne/ ize(I776 E8<);
#)ntr)ls.1**=ange(ne/ #)ntr)l&+ {*@6*<});
ccc c " ne/ ccc();
0ataet *s " c.abc();
*.'erge(*s);
}
public static v)i* 'ain(string&+ args)
{
1pplicati)n.=un(ne/ zzz());
}
}

a.bat
*el R.exe
*el R.*ll
*el aa.cs
xs* 3* aa.xs*
/s*l.exe 3l,# aa.W0!
csc 3t,library ccc.cs
csc 3t,library aa.cs
csc zzz.cs 3r,ccc.*ll 3r,aa.*ll
zzz

244025452.doc 89 od 274
Screen 4.2

This program displays data in datagrids, which functions on the foundation of a master-
detail relationship. The application has two data-grids:
One displays data from the Customers table.
The other displays data from the Orders table with regard to a specifc customer.
The Orders table is comprised of a very large number of records, as all orders have been
stored in a single fle. While the above program is being employed, and when we click on
an individual customer in the frst data grid, the orders only of that particular customer
get displayed in the second grid. To facilitate this, a parent-child or master-detail or one-
to-many relationship has to be established between the Customers table and the Orders
table.

The zzz.cs fle has two DataGrid objects, d1 and d2. The program is larger in size than
the earlier ones, since properties like ForeColor and BackColor have been assigned
specifc values. The DataSource member for both the DataGrid objects is initialized to
d, which is an instance of class ddd, whereas, the DataMember for the DataGrid d1 is
Customers, and that for the DataGrid d2 is Customers.ppp.

The AddRange function is then used to add the two DataGrid objects d1 and d2 into an
array. Finally, an object c is created, which is an instance of ccc. The class ccc is the
WebService class from the fle a.asmx. The abc function in this class is responsible for
retrieving the data from the Customers and Orders table.

244025452.doc 90 od 274
Within the abc function in the asmx fle, two tables viz. Customers and Orders, are
flled up with data by using the Fill function, and the dataset is then returned. Thus,
the DataSet ds contains two tables. This DataSet ds is merged with the ddd object d.

The object of class ddd is used primarily for the data schema or rules. The DataSet
object ds supplies the raw data. The relationship between the Orders table and the
Customers table is stored in the ddd class. Therefore, it is mandatory on our part to
fgure out who creates the ddd class, and how it gets created.

In order to accomplish this, we commence with the fle aa.xsd. We shall not probe any
deeper into the details of the XML Schema world, except to state that it is one of the
three most salient pillars of the XML world. Schemas are basically used for
documentation. In this particular case, it is used for a relationship between tables. It is
employed to ensure that the XML fle conforms to the rules that are imposed on it.

The root tag is schema, with the xsd namespace pointing to a well-known URI. The
targetNamespace and default namespace are null, while the other namespace prefx
defned is msdata. The id attribute has no utility at this juncture.

The next tag or element in sequence is that of Customers. This name has been obtained
from the name of our Table. As every element needs a type, the Customers element is
assigned the type 'complexType'. Within it, is ensconced a list of elements that
constitute the defnition of Customer. In our case, there is only one item named
CustomerID, of type string. Normally, all the felds from the Customer table are listed
out.

The same procedure is adopted for the Orders table too. Here, the two columns listed
out are OrderID and CustomerID, consisting of the attributes ReadOnly and
AutoIncrement, which are self-explanatory. The most crucial element is the one named
ddd. Since the IsDataSet attribute has the value of true, therefore, using the xsd
program on the aa.xsd fle, it creates a class named ddd, which is derived from the class
DataSet containing tons of code.

The complexType tag is followed by the choice element, which enables the user to select
from amongst multiple elements that follow. There are two elements to choose from, and
both of these refer to the Customers and Order elements, using the ref attribute. The
keyref called ppp, refers to a constraint called Constraint1, which is created by using a
unique element.

The XPath expression of //Customers in the selector element indicates a 'node from
anywhere'. This is so because the symbol // stands for 'any location'. An XPath
expression is generally used when some data has to be located in a node. In our code,
the feld of interest is the CustomerID. Close on the heels of the selector, is one more
XPath expression having the value of //Orders, bearing in mind that the Xpath feld is
now specifed as CustomerID.

Thus, we have been triumphant in building a relationship, where every CustomerID
record in the Customer table is mapped to multiple CustomerID records in the Orders
table. As an outcome of this, the DataMember of the second grid takes on the notation
244025452.doc 91 od 274
of Customers.ppp. It is so because ppp now is the keyref, which displays only those
records that have the same Customer id as the active customer in the frst grid.

A snippet of code from the aa.cs fle that is created by the xsd program, has been
displayed below.

aa.cs
#ust)mers0ata:able table#ust)mers;
;r*ers0ata:able table;r*ers;
0ata=elati)n relati)nppp;
private v)i* 4nit#lass()
{
0ataet9ame " "***";
9amespace " "";
table#ust)mers " ne/ #ust)mers0ata:able();
:ables.1**(table#ust)mers);
table;r*ers " ne/ ;r*ers0ata:able();
:ables.1**(t(is.table;r*ers);
table;r*ers.#)nstraints.1**(ne/ D)reignLey#)nstraint("ppp"6 ne/ 0ata#)lumn&+
{ table#ust)mers.#ust)mer40#)lumn}6 ne/ 0ata#)lumn&+ {
table;r*ers.#ust)mer40#)lumn}));
relati)nppp " ne/ 0ata=elati)n("ppp"6 ne/ 0ata#)lumn&+ {
table#ust)mers.#ust)mer40#)lumn}6 ne/ 0ata#)lumn&+ {
table;r*ers.#ust)mer40#)lumn}6 Kalse);
=elati)ns.1**(t(is.relati)nppp);
}

The InitClass function gets called by the constructor of the ddd class, wherein, the
DataSetName property is set to ddd and the Namespace is set to null.

Thereafter, two tables named tableCustomers and tableOrders are created as instances
of the classes derived from DataTable. Both the tables are added to the Tables
collection. The most crucial statement here is the Foreign Key constraint called ppp. A
foreign key of any table is always a Primary key of some other table. In our case,
CustomerID is a primary key in the Customers table, whereas, it dons the mantle of a
Foreign key in any other table that embodies it.
The constructor of the Foreign Key Constraint is assigned two DataColumn objects:
The CustomerID from the Customers table as the Primary key.
The CustomerID column from the Orders table as the Foreign key.

/nce a #ata3elation o)-ect has )een created, it then )eco*es the )ounden dut& o! the s&ste*
to *aintain this relation or 4onstraint. (his constraint will ensure that no record is added in
the /rder ta)le, unless it contains a 4usto*er%# that is resent in the 4usto*ers ta)le. (he
#ata3elation retrie'es records in a si*ilar *anner. %! we )&ass the xsd !ile, we would ha'e
to enter the a)o'e code *anuall&, which is o)'iousl& a 'er& tedious tas2.
D
Webservices and Gavascript

Until recently, C# programs were pressed into action to execute the code contained in
an asmx fle. Since the scales are heavily tilted in favour of scripting languages, we
considered it to be much more prudent to develop a convenient method of calling
functions remotely, using a scripting language like JavaScript, within an html fle.
244025452.doc 92 od 274

This chapter takes a small breather from the C# language, and immerses itself in the
world of JavaScript, which is a scripting language. Javascript in an html fle can be
used to call functions remotely. The packets that fow to and from IE that loads the html
fle to the web service, are SOAP-based.

Before we embark on our journey, we need to download a fle named webservice.htc
from the Microsoft site, and place it in the root directory of IIS at C:\inetpub\wwwroot.
The URL to download the fle is
http://msdn.microsoft.com/downloads/samples/internet/behaviors/library/webservic
e/webservice.htc.

This fle has a size of 48714 bytes. A fle with the htc extension exhibits one of
Microsoft's extended support to html fles, where it enables you to write code and attach
it to an html element. There is no need to decipher the code in this fle for the moment.
Therefore, let us actually get down to the task of calling code within a webservice named
a.asmx, from an html fle called a.html. The html fle has to be placed in the root
directory, i.e. c:\inetpub\wwwroot.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
public int abc(int i6 int j)
{
return i C j;
}
}

a.(tml
<#=4-: language""Vavacript"%
var n " <7;
Kuncti)n init<()
{
s.useervice("(ttp,33l)cal()st3a.asmxNW0!"6"yyy");
s.yyy.callervice("abc"6@@6n);
alert(";ver");
}
Kuncti)n aaa()
{
alert(event.result.value);
}
<3#=4-:%
<b)*y )nl)a*""init<()"%
<input type"text i*""s" style""be(avi)r,url(/ebservice.(tc)" )nresult""aaa()" 3%
<3b)*y%

Output
Messagebo, / over
Messagebo, / 67

Our asmx fle is nothing to crow about! It merely contains a simple function abc, which
accepts two int values. The values contained in the parameters are added up, and then,
the sum is returned back.
244025452.doc 93 od 274
The html fle is where the real action lies. All script-related code, be it in JavaScript or
Visual Basic script, is enclosed within the Script tag. Since we are using JavaScript- the
scripting language invented by Netscape, the language attribute is assigned the value of
'JavaScript'. Thereafter, two functions named init1 and aaa are created.

In order to create a function in JavaScript, the syntax that is followed is: the word
'function', followed by the 'name of the function', followed by the familiar () and {} braces.
This syntax is similar to the one seen in the C# language. Nothing really changes in the
world of programming languages after all!

There is no dire necessity of creating a variable in JavaScript, but for those who are
addicted to the traditional programming paradigm, the word 'var' is to be specifed with
the name of the variable, which in our case is 'n'. The variable n has been assigned a
value of 10. In a scripting language like Java Script, there is no concept of a data type
at all. There is no way of specifying the data type of the variable n, because most
scripting languages are type-less.

Returning to the html fle, we stumble upon the familiar html tag called 'body', which
has an attribute of 'onload'. Since it is initialized to init1, the function init1 gets
executed when the html fle is loaded into the browser. Thus, before the user gets
control, this function gets called. But, before init1 can be called, the rest of the html fle
is evaluated. The textbox has an id of 's', and the code in the htc can now be accessed
using this identifer. The html tag named 'input' displays a textbox in the browser
window. The attribute of 'style' attaches an htc fle to the element. Bear in mind that the
name of the htc fle has to be specifed using the specifc syntax. There is no necessity
of using the 'div' tag, as has been the case in most of the Microsoft examples. Just any
element can ft the bill.

The attribute of 'onresult' is assigned a function name 'aaa', which shall be called, each
time a result is made available from the remote server. This approach eliminates the
possibility of an eternal wait while the server processing is in progress, since the server
may take inordinately long to accomplish its task of executing a function and returning
a value. When the response SOAP packet is received from the server, the function aaa
gets called.
Once the html fle is rendered, the function init1 gets called. In init1, the frst function
to be called from the htc fle is 'useservice'. You may open the htc fle and view this
function for your sheer personal satisfaction.

The frst parameter is the WSDL representation of the asmx fle. Hence, the URL is
specifed as http://localhost/a.asmx?WSDL.

Hereinafter, the WSDL fle will be identifed by the name 'yyy' throughout the rest of the
program. This name is in no way related to any name in the asmx fle. It is the abstract
representation in the WSDL fle that is taken into consideration, and not the actual
code in the asmx fle. You can switch on the SOAP trace utility program and bear
witness to the entire wsdl fle being received.

The second function to be called from the htc fle is callService. In order to call this
function, a predefned pattern needs to be followed. Here, the id 's' is frst specifed,
244025452.doc 94 od 274
followed by the name of the webservice 'yyy', and fnally, by the function name
'callService'. Thus, the resultant expression is s.yyy.callService.

The parameter supplied to this function, frst accepts the function to be called in an
asmx fle, i.e. abc, followed by the list of parameters to be supplied to abc, viz. 22 and n.
The parameters may either be the actual numbers or variables. The 'alert' function
containing the text of 'over', displays a message box containing the text 'over'.

On entering the url of http://localhost/a.html in the browser address box, a textbox
gets displayed initially, followed by two message boxes:
The frst one with the text of 'over'.
The second one with the value of 32.

Here, we have made an asynchronous call. What it signifes is that, the function
'callService' does not 'block' or 'wait'; it immediately executes the next line of code.
Hence, the alert message box gets displayed. If and when, the return SOAP packet
arrives, the function aaa is executed, which exhibits the return value of 32. This
number 32 is displayed using the value member of the result object in the event object.
The sequence of the alerts is of no signifcance.

In the next program, the a.asmx fle remains unchanged. In addition to it, another asmx
fle named b.asmx makes an appearance.

b.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
public int pPr(int i6 int j)
{
return i R j;
}
}

a.(tml
<#=4-: language""Vavacript"%
var n " <7;
Kuncti)n init<()
{
s.useervice("(ttp,33l)cal()st3a.asmxNW0!"6"yyy");
s.useervice("(ttp,33l)cal()st3b.asmxNW0!"6"xxx");
i " s.yyy.callervice("abc"6@@6n);
j " s.xxx.callervice("pPr"6<@@6n);
alert(";ver " C i C U U C j);
}
Kuncti)n aaa()
{
alert(event.result.value C U U C event.result.i*);
}
<3#=4-:%
<b)*y )nl)a*""init<()"%
<input type"text i*""s" style""be(avi)r,url(/ebservice.(tc)" )nresult""aaa()" 3%
<3b)*y%

244025452.doc 95 od 274
Output
Messagebo, Over - 1
Messagebo, 67 -
Messagebo, 177- 1

The function pqr in b.asmx simply multiplies the two parameters passed to it, and
returns the result.

In the html fle, the init1 function assigns the name yyy to the frst webservice named
a.asmx, and the name xxx to the second web service named b.asmx. A single element,
which hereinafter is identifed as 's', can be associated with multiple web services.

A hiatus at this point is that the function aaa gets called for both invocations of
functions abc and pqr, in the two webservices. The question is- how does the system
distinguish one web service call from the other? To ascertain this diference, the return
value of the callService function is stored in two diferent variables, i and j.

For the frst alert containing the text of 'over', the value of i is zero, and that of j is one.
The function aaa, when called, displays the result of the multiplication, which is stored
in the value member. It also displays the id member of the result object, which belongs
to the event object. Thus, the alert displays the values of 32 0, followed by 1220 1.
Therefore, using this method, we can now identify the caller of the callback function
aaa.

a.(tml
<#=4-: language""Vavacript"%
Kuncti)n init<()
{
s.useervice("(ttp,33l)cal()st3a.asmxNW0!"6"yyy");
s.yyy.callervice("pPr");
}
Kuncti)n aaa() {
a " event.result.err)r0etail.c)*e;
b " event.result.err)r0etail.string;
c " event.result.err)r0etail.ra/;
* " event.result.err)r;
alert(a C U U C b C U U C c C U U C *);
}
<3#=4-:%
<b)*y )nl)a*""init<()"%
<input type"text i*""s" style""be(avi)r,url(/ebservice.(tc)" )nresult""aaa()" 3%
<3b)*y%
Message :o,
Client Invalid Argument null true

In the above html fle, we deliberately erred, by requesting the program to execute the
function pqr. No function by this name exists in the a.asmx fle. In spite of this error,
function aaa got called, which then reported the error. The error member in the result
object contained the value of true, and the code and string members in the errorDetail
displayed the position and the error message, respectively.

Thus, any error in the asmx fle can easily be brought to light. In case of any error, the
errorDetail member contains a non-null value; in the absence of all errors, the error
member is false, and the errorDetail member contains a null value. Hence,
244025452.doc 96 od 274
comprehensive error checks can be performed, based merely on the value contained in
this member.

a.(tml
<#=4-: language""Vavacript"%
Kuncti)n init<()
{
s.useervice("(ttp,33l)cal()st3a.asmxNW0!"6"yyy");
s.yyy.callervice( bbb6 "abc"6 <7 6@7);
}
Kuncti)n bbb(r)
{
alert(r.value);
}
<3#=4-:%
<b)*y )nl)a*""init<()"%
<input type"text i*""s" style""be(avi)r,url(/ebservice.(tc)" 3%
<3b)*y%

Message:o,
6-

This program evinces the advantages of JavaScript over the C# language. By the way! I
am no stranger to the fact that this is a C# book, but nonetheless, there are a few facts
that need to be brought to light for your knowledge.

Remove the onresult attribute from the input. Then, specify a javascript function named
bbb in the callService. Thereafter, follow it up with the parameters, starting with abc,
which is the name of the function in the webservice, followed by the parameters to the
function. Function bbb now gets called with a parameter 'r', which is the result object.
The alert function displays the value contained in the value member, i.e. 30. There isn't
much dissimilarity in the two approaches, other than the method used to obtain the
result object.

a.(tml
<#=4-: language""Vavacript"%
Kuncti)n init<()
{
var a " ne/ ;bject();
a.Kunc9ame " "abc";
a.async " true;
a.time)ut " <@7;
s.useervice("(ttp,33l)cal()st3a.asmxNW0!"6"yyy");
i " s.yyy.callervice( bbb 6 a 6 <7 6@7);
alert("(i" C i);
}
Kuncti)n bbb(r)
{
alert( UbbbU C r.value);
}
Kuncti)n aaa()
{
alert( UaaaU C event.result.value);
}
<3#=4-:%
<b)*y )nl)a*""init<()"%
<input type"text i*""s" style""be(avi)r,url(/ebservice.(tc)" )nresult""aaa()" 3%
<3b)*y%
244025452.doc 97 od 274

Output
Messagebo, !i-
Messagebo, bbb6-


In the above html fle, the onresult attribute points to the aaa function, which shall be
called when a SOAP message arrives. The init1 function creates a new object called 'a',
and then initializes the funcName member to abc, which is the function to be called.
Thereafter, the async member is set to true, thereby, making the call asynchronous. The
'timeout' determines the waiting period for the arrival of the response packet.

The useService method remains unaltered. In callService, the name of the callback
function is specifed initially, followed by the object 'a', thereby, furnishing all the values
in a single stroke. Finally, the parameters to the function in the object are supplied. You
may have noticed that there are too many overheads for a single function named
callService.

The function bbb eventually gets called, and it overrides the onresult value, which is
specifed in the input element. Thus, we witness two message boxes. The frst displays
hi0, while the second displays bbb30. On modifying the value of the async property to
false (i.e. a.async = false), the client is prevented from proceeding further,
until the SOAP packet returns. Therefore, the functions aaa and bbb shall never get
called. It is advisable to use this type of synchronous behaviour sparingly and with
deliberate care.

Asynchronous Execution

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
public int abc(int i6 int j)
{
return i C j;
}
}

The aa.wsdl fle remains the same and hence is not displayed.


a.cs
using ystem;
public class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
1sync#allbac5 c " ne/ 1sync#allbac5(abc);
41sync=esult r " a.Meginabc(<76@76c6a);
/(ile (r.4s#)mplete* "" Kalse)
{
#)ns)le.Write!ine(0ate:ime.9)/);
244025452.doc 98 od 274
}
#)ns)le.=ea*!ine();
}
public static v)i* abc(41sync=esult a)
{
zzz * " (zzz) a.1synctate;
int r;
r " *.>n*abc(a);
#)ns)le.Write(r);
}
}

zzz.cs
public ystem.41sync=esult Meginabc(int i6 int j6 ystem.1sync#allbac5 callbac56 )bject
asynctate)
{
return t(is.Megin4nv)5e("abc"6 ne/ )bject&+ {i6j}6 callbac56 asynctate);
}
public int >n*abc(ystem.41sync=esult async=esult)
{
)bject&+ results " t(is.>n*4nv)5e(async=esult);
return ((int)(results&7+));
}

Output
EatimeN)
6-


z.bat
*el R.exe
*el R.*ll
*el zzz.cs
/s*l aa./s*l
csc 3t,library zzz.cs
csc a.cs 3r,zzz.*ll
a

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"2*7-"12*
"1abc*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*6-"1abc4esult*
"1abc4esponse*

We commence with the smallest asmx fle, which has a single function named abc. The
quandary that we may face at this juncture is that, if the function abc on the server-
side uses up an hour to complete execution, the program would have to wait at the call,
until the function fnished execution, and thereby, bringing the execution of the
remaining code to a grinding halt. So, would it not be a sagacious move to let the code
execution continue, even after the function call is completed? Once the call has been
completed, it could notify another function and pass it the return value. This program
goes behind the scenes to reveal the mechanics of implementing an asynchronous call!

244025452.doc 99 od 274
Since the asmx fle resides on the server, it displays the familiar abc function, devoid of
any alteration. However, in the C# client, numerous modifcations have been carried
out.

The object 'a' is an instance of the class zzz, and the object 'c' is an instance of class
AsyncCallback. The name of a static function abc in class aaa, is passed to the
constructor of the AsyncCallback delegate. Thereafter, in place of the function abc, the
function Beginabc gets called with four parameters:
The frst two parameters are for the abc function.
The third parameter is c, which is the AsyncCallback object. This delegate calls the
function abc, when the function abc on the remote server completes execution.
The fourth parameter is the zzz object itself.
It is impossible to estimate the time frame in which the abc function is likely to
accomplish its task. Therefore, the remaining code goes on with its execution. The
IsCompleted property of type boolean contains the value of false, till the function on the
server completes execution, or till the SOAP response packet has been received. Thus,
we quit out of the loop when the IsCompleted member returns true. While the loop is in
progress, the only code that is executed is the WriteLine function, which contains the
DateTime value. Once the IsCompleted value changes to true, the abc function gets
called.

The function abc is passed a parameter 'a', of type IAsyncResult, which contains a
property called AsyncState. This property represents the zzz object. Using this zzz
object, the function Endabc is called, which eventually returns the answer from the
remoted function. This value is then displayed on the Console. Thus, the proxy
generates two functions, viz. Beginabc and Endabc. Instead of Invoke, a function
named BeginInvoke is employed, which is passed the name of the function in a string
form, followed by an array of objects for the parameters. This is followed by the name of
the callback delegate, and fnally, by the zzz object. The Endabc function uses the
EndInvoke function to return an array of objects, from which, the frst int is returned.

It is highly improbable that you are able to discern the method of invocation that has
been employed, by merely examining the SOAP packets. Therefore, in the SOAP world,
mundane issues such as, synchronous and asynchronous calls, pale into
insignifcance. Thus, SOAP has to lean on various other infrastructural crutches, in
order to work efectively. In the real world, it cannot be used by itself, as a standard.
However, issues regarding distributed computing are given due consideration by the
SOAP standard.


a.cs
using ystem;
public class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
41sync=esult r " a.Meginabc(<76@76null6 null);
#)ns)le.Write!ine("MeK)re");
r.1syncWait.an*le.Wait;ne();
int c;
244025452.doc 100 od 274
c " a.>n*abc(r);
#)ns)le.Write!ine(c);
}
}

Output
:e.ore
6-

There are myriad ways of implementing asynchronous behaviour. Since there is neither
a callback function abc, nor any delegate, the last two parameters of the Beginabc
function are assigned the value of null. When the Beginabc function is called, the
WaitOne function is executed, which waits until the function abc completes execution.

(he ro+ra* does not consu*e an& resources5 instead, it slees until a S/01 resonse is
recei'ed. (he !a*iliar 6nda)c !unction is e*lo&ed to o)tain the answer. (he *ilea+e that
&ou wish to deri'e, shall deter*ine the *ost oti*al *echanis* o! i*le*entin+
as&nchronous )eha'iour.
@
SOAP ;eaders

All the previous chapters had riveted their attention on two salient components of the
SOAP packet, i.e. the Envelope and the Body. In this chapter, we shall pan our focus
onto the third major component of the SOAP payload, known as the Header. The SOAP
Header is optional, but when present, it should be placed immediately after the
Envelope, but before the Body.

In the case of headers, there exists abundant fexibility to settle on what they should be
used for. These headers are generally employed in order to send across information that
should not to be sent as part of the SOAP body, since it does not form part of the data.
Thus, specifc pieces of information, such as userid, password, authentication,
encryption, security information, etc. are incorporated in the headers.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
public yyy z;
&Web'et()*+
&)ap.ea*er("z")+
public int abc(int i6 int j)
{
return i C j;
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}
244025452.doc 101 od 274

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public yyy b;
public static v)i* 'ain()
{
aaa a" ne/ aaa();
a.b " ne/ yyy();
a.b.name""vijay" ;
a.b.pass""s)nal" ;
int i " a.abc(<76@7);
#)ns)le.Write!ine(i);
}
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("b")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
public int abc(int i6 int j)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+ {i6j});
return ((int)(results&7+));
}
public aaa()
{
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

z.bat
*el R.exe
*el R.*ll
*el zzz.cs
/s*l aa./s*l
csc a.cs
a

Output
6-

SOAP re5uest
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%!ttp:11sc!emas),mlsoap)org1soap1envelope1
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap:;eader*
"''' ,mlns%&!ttp:11tempuri)org1&*
"name*vi2a'"1name*
"pass*sonal"1pass*
"1'''*
"1soap:;eader*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"2*7-"12*
"1abc*
"1soap::od'*
244025452.doc 102 od 274
"1soap:Envelope*

SOAP response
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*6-"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

Here, we have cogitated on the client program named a.cs, instead of the asmx fle,
since it is the client that dispatches the headers that are received by the asmx fle. As in
the past, the client program is written manually, and is followed by the wsdl program, in
order to generate the proxy.

After the creation of a new instance of the aaa object, an object b derived from
SoapHeader is created, since the intent is to send a few headers across. The class yyy,
which is derived from SoapHeader, contains two members called 'name' and 'pass'. They
are initialized to the values 'vijay' and 'sonal', respectively. These are the values that are
required to be sent across in the header. Thus, the basic principle is to derive a class
from SoapHeader, and initiate a list of variables in it, whose values are to be sent
across.

Thereafter, the function abc is called. It is lodged in the class aaa. The only modifcation
that is carried out to this function is, the addition of an extra attribute named
SoapHeaderAttribute, containing the object b, since it holds the values that are to be
sent across in the header. Everything else remains unchanged.

The SOAP request reafrms the fact that the headers are actually sent across. As usual,
the Envelope drifts into sight frst, followed by the SOAP Header. Since the name of the
class is yyy, it becomes the parent for the two child elements named 'name' and 'pass',
which contain the values of 'vijay' and 'sonal', respectively. In this case, the headers are
not sent back.

Thus, custom headers can easily be created with the help of any user-defned content.
For instance, the client can send the userid and password over in the header. From the
SOAP point of view, the mechanism employed by the server to handle this information is
of no consequence at all.

Let us now expound the asmx fle more comprehensively by perusing another example.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz {
public yyy z;
&Web'et()*+
&)ap.ea*er("z")+
244025452.doc 103 od 274
public int abc(int i6 int j)
{
int 5 " z.name.!engt(;
int l " z.pass.!engt(;
return 5 C l;
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

Output
1-

In the asmx fle, the class yyy is derived from the SoapHeader. This is akin to what was
witnessed in the client program. Thereafter, an object z is created as an instance of the
yyy class.

The function abc has been provided with an extra attribute named SoapHeader, which
in very clear-cut terms, specifes that the name of the object is z, and that it contains
the soap headers in the string format.

When the function abc gets called, the system frst initializes the object z to the values
found in the Header. In our case, thereafter, we merely determine the length of the two
header values that are sent across, and add these up. Thus, the output obtained is 10.
However in real life, there exists ample fexibility for you to act as you desire, when faced
with such a situation. Having unraveled the mystery of the client program, you would
realise that the concept of web service can be comprehended with efortless ease.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
public yyy z;
&Web'et()*+
&)ap.ea*er("z")+
public v)i* abc()
{
z.name " "9)";
z.pass " "yes";
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

aa./s*l
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype 3%
<3s,element%
244025452.doc 104 od 274
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""yyy" type""s7,yyy" 3%
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""name" nillable""true" type""s,string" 3%
<s,element min;ccurs""<" max;ccurs""<" name""pass" nillable""true" type""s,string" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,sc(ema%
<message name""abcyyy"%
<part name""yyy" element""s7,yyy" 3%
<3message%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,abcyyy" part""yyy" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
a.yyyQalue " ne/ yyy();
a.yyyQalue.name""vijay" ;
a.yyyQalue.pass""s)nal" ;
a.abc();
}
}

zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
public yyy yyyQalue;
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("yyyQalue")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
public v)i* abc()
{
t(is.4nv)5e("abc"6 ne/ )bject&7+);
}
}
&ystem.Oml.erializati)n.Oml=))t1ttribute(9amespace""(ttp,33tempuri.)rg3"6 4s9ullable"Kalse)+
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

The SOAP request and the response packet remain the same as seen in the earlier
program.

244025452.doc 105 od 274
Once again, our primary focus remains impaled on the asmx fle. The class yyy is
derived from the class SoapHeader. Therefore, the soap headers are visible in the
packet. The elements stipulated here are sent across as tags within the header. In this
case, the header comprises of two elements, viz. 'name' and 'pass'. Prior to every
function, we need to specify the headers that the function shall receive.

The function abc shall receive its headers in an object z, which is an instance of the
class yyy. It has been provided as a string parameter, because the SoapHeader specifes
that the object name should be in a string format. The function abc merely modifes the
values contained in 'name' and 'pass'. These newly assigned values are then sent
across. In the normal course, we would have accessed the values that are sent across,
and then modifed them.

You would have discerned vast variations in the aa.wsdl fle. This is because, when we
encounter a class derived from SoapHeader, IIS is alerted to the fact that Headers too
have been sent across.

The element abc has no parameters; therefore, it has an empty complexType. Since the
name of the class is yyy, an element called yyy is created. The type of this element is
also yyy. It does not possess any other content. Next, a complexType yyy is created to
accommodate two elements called 'name' and 'pass', which correspond to the variables
in the class yyy.

Upto this point, in the wsdl fle, there has been no indication that the class yyy has
been derived from the SoapHeader class. Besides, there is no allusion to the fact that
yyy represents a class that is responsible for sending the Headers across. This is
because the schema section looks exclusively at schemas, and Headers have no
representation in a schema.

Now, we revert our attention right back to the message element, which was enucleated
in one of the earlier chapters. Apart from the two messages sighted in the earlier
programs, one more message is sent over. This message contains only a single part
named yyy. The element represented by this part is called yyy. It is of type yyy, which is
the class derived from SoapHeader. Thus, every class derived from SoapHeader is
provided with a message element.

The operation abc has a simple input and output section. The input section has a Body
element, comprising of a Header element from the soap namespace. The 'required'
member with the value of 'true', mandates the presence of a header. The message is
named as abcyyy. This name is formed by the conjunction of the name of the function,
and the name of the header class. It specifes the format of the header.

Thus, headers are dispatched as per the functions. This statement will be proved
beyond doubt in one of the forthcoming examples. The yyy part is responsible for the
message, since this is where the element is expressly specifed. The 'use' attribute
works in a manner analogous to the 'operation' element.

As always, a new instance of the zzz class is created in the client program, and the
yyyValue member is initialized to a yyy object. The header class is yyy. Therefore, the
244025452.doc 106 od 274
member that represents this header in the proxy is named as yyyValue, i.e. classname
plus the word 'Value'. The 'name' and 'pass' members are initialized to 'vijay' and 'sonal',
respectively. When the function abc is called, the headers are sent across, as a
consequence of the attributes created in the proxy.

Let us now explore the proxy generated by the wsdl fle. The class yyy is sighted at the
absolute end of the fle that has been derived from SoapHeader. This is due to the fact
that 'operation' contains the Header tag for the element yyy. The function remains the
same, except that the SoapHeaderAttribute has been added. The string parameter
contains the name of the object that would carry the header data yyyValue. All
functions that carry this attribute, send the headers across the wire.

So far, the SOAP Headers have been gliding in one direction only, i.e. from the client to
the server. It is our intent to reverse this direction in the next example, i.e. send the
Headers back from the server to the client.

In order to achieve this, we efect a minor modifcation to the asmx fle, by changing the
SoapHeader attribute to the following:

&)ap.ea*er("z"60irecti)n")ap.ea*er0irecti)n.4n;ut)+

aa./s*l
<)utput%
<s)ap,b)*y use""literal" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,abcyyy" part""yyy" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<3)utput%

a.cs
a.abc();
#)ns)le.Write!ine(a.yyyQalue.name);
#)ns)le.Write!ine(a.yyyQalue.pass);

Output
(o
Oes

zzz.cs
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("yyyQalue"6
0irecti)n"ystem.Web.ervices.-r)t)c)ls.)ap.ea*er0irecti)n.4n;ut)+
soap response
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap:;eader*
"''' ,mlns%&!ttp:11tempuri)org1&*
"name*(o"1name*
"pass*'es"1pass*
"1'''*
"1soap:;eader*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*
"1soap:Envelope*

244025452.doc 107 od 274
By merely adding one more property to the SoapHeader attribute, we have been able to
add a header to the SOAP response packet. In the asmx fle, the values of the 'name'
and the 'pass' properties are initialized to 'no' and 'yes', respectively.

Further, since the Direction property has been set to 'InOut', the headers now fow in
both directions. The default value of the Direction property is 'In'. The third possible
value that it can assume is 'Out', which is normally used in the response packet only.

The wsdl fle does not display the word 'InOut'. Moreover, the output element in the
operation for abc, which earlier contained a single member body, now has an additional
member - the header, along with its attributes.

Since the wsdl fle contains the Header element in both the input and the output
elements, the Direction property in the proxy is set to 'InOut'. The client program adds
two lines at the end, to display the values of the 'pass' and 'name' members, which are
modifed to 'yes' and 'no', respectively.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
public yyy z;
public xxx z<;
&Web'et()*+
&)ap.ea*er("z")+
&)ap.ea*er("z<")+
public v)i* abc()
{
}
&Web'et()*+
&)ap.ea*er("z<")+
public v)i* pPr()
{
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}
public class xxx , )ap.ea*er
{
public string aa;
}

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
a.yyyQalue " ne/ yyy();
244025452.doc 108 od 274
a.xxxQalue " ne/ xxx();
a.yyyQalue.name""vijay" ;
a.yyyQalue.pass""s)nal" ;
a.xxxQalue.aa""mu5(i" ;
a.abc();
a.pPr();
}
}

aa./s*l
<message name""abcyyy"%
<part name""yyy" element""s7,yyy" 3%
<3message%
<message name""abcxxx"%
<part name""xxx" element""s7,xxx" 3%
<3message%
<message name""pPrxxx"%
<part name""xxx" element""s7,xxx" 3%
<3message%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,abcyyy" part""yyy" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,abcxxx" part""xxx" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<)perati)n name""pPr"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3pPr" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,pPrxxx" part""xxx" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%


zzz.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
public yyy yyyQalue;
public xxx xxxQalue;
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("yyyQalue")+
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("xxxQalue")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc"+
public v)i* abc()
{
t(is.4nv)5e("abc"6 ne/ )bject&7+);
}
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("xxxQalue")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute((ttp,33tempuri.)rg3pPr)+
public v)i* pPr()
{
t(is.4nv)5e("pPr"6 ne/ )bject&7+);
}
}
244025452.doc 109 od 274
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}
public class xxx , )ap.ea*er
{
public string aa;
}

Soap 4e5uest 1
"soap:;eader*
",,, ,mlns%&!ttp:11tempuri)org1&*
"aa*muk!i"1aa*
"1,,,*
"''' ,mlns%&!ttp:11tempuri)org1&*
"name*vi2a'"1name*
"pass*sonal"1pass*
"1'''*
"1soap:;eader*

Soap 4e5uest 7
"soap:;eader*
",,, ,mlns%&!ttp:11tempuri)org1&*
"aa*muk!i"1aa*
"1,,,*
"1soap:;eader*

Though the above example may span numerous pages, its sole purpose is to
demonstrate the fundamental concept that, the SOAP header packets get created in
accordance with the attributes placed before the function. Thus, the function that is
called, determines the SOAP headers that get sent across.

There are two classes, xxx and yyy, both of which are derived from SoapHeader.
Thereafter, two objects representing the headers, viz. z and z1, are created when the
SOAP payload arrives from the client to the server. The names of these two variables are
inconsequential, and do not get refected in the wsdl fle. The Attribute SoapHeader is
most crucial, as this attribute determines what is to be sent across.

The function abc utilizes this attribute twice, and therefore, the contents of both the
classes, yyy and xxx, are sent across as headers. Thus, a call to the function abc will
result in the transmission of three elements in the header, viz. 'name', 'pass' and 'aa'.
On the other hand, the function pqr would have only a single element in the header, i.e.
'aa', since it has only one SoapHeader attribute.

The wsdl fle reinforces the statement that we have just made. The function abc has two
headers; hence, two message elements named 'abcyyy' and 'abcxxx' are visible, unlike in
the earlier program. Since the function pqr has only a single header, a single part
named 'pqrxxx' is visible.

Every function embodies its own operation element. To begin with, the function abc in
the input transmits two headers across. Hence, the header element is displayed twice.
The frst is a message 'abcyyy', while the second is 'abcxxx'. The output does not have
any headers. Thus, no header element exists. We could possibly have combined the last
two programs and sent only a single header across, using the direction property.
244025452.doc 110 od 274
The operation called pqr has a single header named xxx, which is to be sent across. The
value of the direction property is 'In', by default. We have not displayed the schemas,
since they fail to introduce anything innovative. The schemas that have been created for
yyy and xxx are identical.

The client program is acquainted with the fact that there exist two objects. Hence,
yyyValue and xxxValue are created, to represent the objects z and z1, respectively. Then,
using the object 'a', the functions abc and pqr are called. In the proxy, we now have two
classes, yyy and xxx, which are derived from the SoapHeader class.

Correspondingly, we also have two objects named xxxValue and yyyValue, to represent
them. The proxy object is very similar to the asmx fle. The function abc sends two
headers across. Thus, it has two SoapHeaderAttribute attributes. The function pqr has
only a single SoapHeaderAttribute.

Here, a round trip gets executed, in that, the asmx fle gets converted to wsdl, which in
turn, becomes the proxy. The frst SOAP request is that of the function abc. We are
sending two disparate headers from two diferent classes. Thus, the element 'aa'
becomes a part of the xxx class, while the 'name' and 'pass' members become part of
the yyy class.

The headers are not bundled and sent across. Instead, they are dispatched depending
upon the class that they belong to. Therefore, they could enjoy the same names, and yet
be diferentiated at the receiving end. The second packet represents the function pqr,
where only a single header is sent across. Each packet represents a single function.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz {
public yyy z;
&Web'et()*+
&)ap.ea*er("z"6 =ePuire*"true)+
public v)i* abc()
{
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

aa./s*l
<s)ap,(ea*er n<,rePuire*""true" message""s7,abcyyy" part""yyy" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
public static v)i* 'ain()
{
244025452.doc 111 od 274
zzz a" ne/ zzz();
a.abc();
}
}

The asmx fle remains unaltered, except that the function abc has the SOAP header set
to the object 'z', and the Required property set to 'true'. The value of default signifes
that it is mandatory for the client to send the header across, before it can send the
packet over.

The aa.wsdl fle shows only a single line, where the header element contains a
'Required' attribute. By default, it is set to a value of 'true'. In the a.cs fle, since an
instance of the yyyValue object is not created, an exception is thrown.

Output
<n!andled E,ception: S'stem)Web)Services)Protocols)Soap;eaderE,ception: 4e5uired
Peld1propert' 333)'''Qalue o. SOAP !eader ''' was not set b' t!e client prior to
making t!e call)

a.asmx
&)ap.ea*er("z"6 =ePuire*"Kalse)+

aa./s*l
<s)ap,(ea*er message""s7,abcyyy" part""yyy" use""literal" 3%

zzz.cs
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("yyyQalue"6 =ePuire*"Kalse)+

soap re5uest
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*
"1soap:Envelope*

As a result of transforming the value of the Required attribute to 'false', the header
element of the wsdl fle that gets generated, is by far much simpler, and contains very
few attributes. It does not have any attribute named Required. The client program
remains unchanged.

The proxy that is generated, almost mirrors the asmx fle. Hence, the Required attribute
is visible, along with the SoapHeader attribute, above the function abc. However, the
SOAP request does not specify any Header details. Thus, in the fnal analysis, the value
in the Required attribute determines whether a SOAP header should be sent across or
not.

Change the code in the Main function within a.cs to the following

public static v)i* 'ain() {
zzz a" ne/ zzz();
a.yyyQalue " ne/ yyy();
a.abc();
}
soap re5uest
244025452.doc 112 od 274
"soap:;eader*
"''' ,mlns%&!ttp:11tempuri)org1&*
"name ,si:nil%&true& 1*
"pass ,si:nil%&true& 1*
"1'''*
"1soap:;eader*

Earlier, since the yyyValue was not initialized to any object, an exception was thrown.
Now, a yyy object is created, but none of the members are initialized. The SOAP packet
discloses the Header details, but it uses the 'nil' attribute to signify that they are empty
or null. If we change the Required attribute to 'true' in the asmx fle, the SOAP request
displayed above, will be generated.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
&Web'et()*+
public string abc()
{
return "(ell";
}
}

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public yyy b;
public static v)i* 'ain()
{
aaa a" ne/ aaa();
a.b " ne/ yyy();
a.b.name""vijay" ;
a.b.pass""s)nal" ;
string i " a.abc();
#)ns)le.Write!ine(i);
}
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("b")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
public string abc()
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&7+);
return ((string)(results&7+));
}
public aaa()
{
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
}
}
public class yyy , )ap.ea*er
{
public string name;
public string pass;
}

244025452.doc 113 od 274
Output
!ell

The above program, which is a C# client, is a near clone of the frst C# program of the
chapter. Any diference, if at all, lies in the fact that the function abc returns a string.
The above program compiles by itself, without any wsdl fle.

The salient point to be noted here is that, despite sending a header across, the asmx fle
seems unable to recognize or acknowledge the header's presence. Neither are there any
errors generated.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
public )ap2n5n)/n.ea*er u;
&Web'et()*+
&)ap.ea*er("u"6 =ePuire*"Kalse)+
public string abc()
{
return u.>lement.4nnerOml C u.>lement.9ame;
}
}

Output
"name ,mlns%&!ttp:11tempuri)org1&*vi2a'"1name*
"pass ,mlns%&!ttp:11tempuri)org1&*sonal"1pass*
'''

In our asmx program, an object 'u' of the class SoapUnknownHeader has been freshly
appended. Therefore, before the function abc gets called, this object contains all the
headers that are not known. This is on account of the SoapHeader attribute having the
object name of 'u'. In our case, we have only a singular header named 'yyy'.

The value of the Required parameter should be 'false', failing which, an unknown header
would have to be sent across manually. In the function, the contents of the header are
displayed, by merely employing the Element member of type XmlElement. This is
achieved by displaying the InnerXml member and the 'name' property that retrieves the
name of the header, i.e. yyy.

A property called DidUnderstand, which accepts a boolean value, is set by the asmx fle,
in order to convey that it has been able to comprehend the unknown header. This is not
refected in the SOAP packet that is sent across.

Add the following property to a.cs

a.b.1ct)r""mu5(i" ;

Soap re5uest
"soap:;eader*
"''' soap:actor%&muk!i& ,mlns%&!ttp:11tempuri)org1&*

244025452.doc 114 od 274

Now, we add one more property called Actor, which is part of the SoapHeader class and
initialize it to mukhi. This results in the creation of an attribute named 'actor', in the
SOAP request packet. The 'actor' attribute is SOAP's way of determining who should be
reading and understanding the Header.

Here, we have assigned it a value of 'mukhi', but in practical applications, it should
contain a uri.

This is the fnal illustration that carries out authentication by using an aspx fle,
instead of a client program.

a.aspx
<%@ -age !anguage""#$"%%
<%@ 4mp)rt 9amespace""ecurity"%%
<%@ 4mp)rt 9amespace""ystem.Web.ervices.-r)t)c)ls" %%
<script runat"server%
public v)i* -ageT!)a*()
{
s<.4nner.tml " "";
}
public v)i* abc(;bject sen*er6 >vent1rgs z)
{
zzz s " ne/ zzz();
aaa a " ne/ aaa();
a.2ser " us.Qalue;
a.-ass/)r* " pass.Qalue;
s.aaaQalue " a;
string r " s.abc();
s<.4nner.tml " r;
}
<3script%
<K)rm runat"server%
2sername,
<input type"text i*"us runat"server 3%
<br%
-ass/)r*,
<input type"text i*"pass runat"server 3%
<br%
<input type"submit runat"server ;nerver#lic5""abc" value""!)gin" 3%
<3K)rm%
result, <K)nt c)l)r"re*%
<span i*"s< runat"server 3%

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class aaa , )ap.ea*er
{
public string 2ser;
public string -ass/)r*;
}
public class zzz , Webervice
{
public aaa z;
&Web'et()*+
&)ap.ea*er("z")+
public string abc()
244025452.doc 115 od 274
{
iK (z.2ser "" "vijay" WW z.-ass/)r*"""mu5(i")
return "all is )5ay";
iK (z.2ser "" "s)nal" WW z.-ass/)r*"""ba*")
return "all is n)t )5ay";
return "s)met(ings g)ne /r)ng";
}
}

a.bat
*el R.*ll
/s*l a./s*l 3namespace,ecurity
csc.exe 3t,library zzz.cs
m* c,FinetpubF///r))tFbin
c)py zzz.*ll c,FinetpubF///r))tFbinF

SOAP re5uest
"soap:;eader*
/ "aaa ,mlns%&!ttp:11tempuri)org1&*
"<ser*sonal"1<ser*
"Password*muk!i"1Password*
"1aaa*
"1soap:;eader*
/ "soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*somet!ing gone wrong"1abc4esult*
"1abc4esponse*

We commence by creating the fle a.aspx in the C:\inerpub\wwwroot folder. The
language is explicitly specifed as C#, because the default language is VB. This is
followed by a series of unproductive Import statements, to enable you to abandon
writing the namespace names over and over again. The code will eventually emanate
from the Namespace Security. The whole world uses namespaces, so why should we be
called the nonconformists or the odd ones out?

The 'runat' attribute is mandatory, although we are aware that everything runs only at
the server end. The Page_Load function gets called each time the page is sent from the
server to the client.

Thereafter, we simply initialize the s1 element, which is a span element, to a blank
value. We could have used a label instead, but on a personal whim, we preferred the
span element.

On the screen, the words 'username' and 'password' are displayed along with two
textboxes, having ids of 'us' and 'pass', respectively. The user is expected to key-in a
user id and a password. The 'type' for the password box should be specifed as
'password' to avoid displaying the characters, since they are being entered. Moreover,
there is a button that calls the function abc on the server, every time the user clicks on
it.

Before advancing any further with deciphering the code contained in the function abc,
let us examine the asmx fle. The class zzz has a function named abc, which receives a
244025452.doc 116 od 274
soap header called 'aaa', in the form of an object 'z'. This header class aaa has two
members, User and Password.


The function abc ascertains whether the User and Password contain specifc pre-
defned values or not. The activity performed by this function has nothing in common
with the function abc of the aspx fle.

If the username is entered as 'vijay', and the password is entered as 'mukhi', an OK
message is received. However, if the user name is specifed as 'sonal', and the password
is specifed as 'bad', an altogether diferent message is received. If any other values are
specifed, a default message is displayed. In real life, the values are compared with data
contained in a database.

Once the asmx fle is done with, create a wsdl fle as before, by entering the url of
http://localhost/a.asmx?WSDL in the browser. The only diference here is that the wsdl
fle must be saved as 'a.wsdl' in the c:\inetpub\wwwroot\bin folder. The batch fle frst
calls the wsdl program, and the /namespace option places all the code of the class zzz
in the namespace security. Thereafter, zzz.cs is compiled into a dll fle, as before.

Once the stage is set, load the browser and enter the url as http://localhost/a.aspx. In
the textboxes, enter the values for the userid and password, and then, click on the
button. This calls the function abc.

The function abc in the aspx fle frst creates an object 's', which is an instance of the
class zzz. The rationale behind placing the class in the bin folder is that, the system
normally searches this location for classes.

Another object named aa is created, which is an instance of the SoapHeader class.
Then, the User and Password members are initialized to the text specifed in the
textboxes, identifed with the ids of 'us' and 'pass', respectively.

Once this is accomplished, the aaaValue member, which represents the header object in
class zzz, is initialized to 'a', which is an instance of the SoapHeader class. In this
manner, all the initialized values are passed to the header.

Thereafter, the function abc sends the header across, and the value returned by the
remoted function is placed into the span's InnerHtml member.

7ou can chan+e the ort nu*)er to 8080 in the wsdl !ile, in order to o)ser'e the !low o!
ac2ets in the trace ro+ra*. (hus, the S/01 re8uest and resonse re*ain the sa*e,
irresecti'e o! whether we wor2 with a client 49 ro+ra* or with an asx !ile.
I
SOAP E,tensions

The SOAP Request packet, when it arrives at the web server, is in the form of an XML
document. The relevant information, such as function names and parameters, need to
244025452.doc 117 od 274
be extracted from the XML document. This act of extraction is termed as de-
serialization. At the other end, the system when it is to send a value over, it has to
create a SOAP Response packet, which is an XML fle containing the value. To
accomplish this, a process called Serialization is executed.

This Serialization and De-serialization of SOAP packets is achieved by using SOAP
Extensions. This chapter explains how the packets can be parsed and messages can be
intercepted.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
&vijay()+
public v)i* abc()
{
}
}
The webservice possesses a simple attribute called 'vijay', which is applied to the
function abc. On loading the asmx fle in the web browser, an error is generated, since
the compiler fails to recognize the word 'vijay'.

The error displayed in the browser window is
JCS-7=@: !e t'pe or namespace name Jvi2a'J could not be located >are 'ou missing a
using directive or an assembl' re.erence+B

Thus, the compiler needs to be educated about the fact that 'vijay' is a class.

While loading the asmx fle, the compiler scans the dll fles in the bin subdirectory,
within the c:\inetpub\wwwroot folder, for the class named 'vijay'.

Since it is unable to locate it, it expresses its inability to compile the code. To surmount
this error, create the bin folder, if it is not already present at the location specifed, and
enter the following code in a fle named aaa.cs:

aaa.cs
using ystem;
using ystem.4;;
using ystem.Web.ervices.-r)t)c)ls;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay1ttribute , 1ttribute
{
}

Compile the fle by giving the command as

C:RinetpubRwwwrootRbin*csc 1t:librar' aaa)cs

To enable creation of an attribute called 'vijay', a class named 'vijayAttribute' or 'vijay'
must be present in the library. The word 'Attribute' is specifed after the class name
'vijay', in order to appease the naming conventions. The attribute called AttributeUsage
that is specifed over the class name, is optional.
244025452.doc 118 od 274


The parameter Method restricts the use of this attribute over a function; however, there
is no curb on its use over entities such as, a class or a property. To qualify as an
attribute, the most important criteria that the class 'vijay' must satisfy is that, it must
be derived from the class Attribute.

The asmx fle loads successfully in the browser. The regular client program is used, to
call the function abc. The process of calling code remains unaltered. After you have
created a proxy from the wsdl fle, use the batch fle and then, run the program.

a.cs
class aaa {
public static v)i* 'ain() {
zzz a" ne/ zzz();
a.abc();
}
}

z.bat
*el R.exe
*el R.*ll
*el zzz.cs
/s*l aa./s*l
csc 3t,library zzz.cs
csc a.cs 3r,zzz.*ll
a

In the next program, 'vijay' is derived from the class SoapExtensionAttribute, which in
turn, is derived from the class Attribute. It is mandatory to derive all custom extensions
from the above class.

aaa.cs
using ystem;
using ystem.4;;
using ystem.Web.ervices.-r)t)c)ls;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
}
Compiler Error
*csc 1t:librar' aaa)cs

aaa)cs>DF1=B: error CS-D6=: Jvi2a'J does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tensionAttribute)E,tension'pe)getJ
aaa)cs>DF1=B: error CS-D6=: Jvi2a'J does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tensionAttribute)Priorit')getJ
aaa)cs>DF1=B: error CS-D6=: Jvi2a'J does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tensionAttribute)Priorit')setJ

The SoapExtensionAttribute class contains two properties, Extensiontype and Priority,
hence, if the two members are not implemented, an error will be generated. We see four
errors being generated because the 'get' and the 'set' accessors of both the properties
are yet to be implemented. The next program implements the required members in the
class.

aaa.cs
244025452.doc 119 od 274
using ystem;
using ystem.4;;
using ystem.Web.ervices.-r)t)c)ls;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute {
public )verri*e :ype >xtensi)n:ype {
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity {
get
{
return 7;
}
set
{
}
}
}
public class mu5(i {
}

Other than returning the Type of a class mukhi, there is nothing more added to these
properties. Each time, the framework will call the ExtensionType property to decipher
the type of the extension class.

Executing the client program throws an exception with the errors shown below:

Output
C:Rwww*a
<n!andled E,ception: S'stem)Web)Services)Protocols)SoapE,ception:
S'stem)Web)Services)Protocols)SoapE,ception: Server was unable to process re5uest)
///* S'stem)InvalidCastE,ception: E,ception o. t'pe S'stem)InvalidCastE,ception was
t!rown)
at
S'stem)Web)Services)Protocols)Soap4eKectedE,tension)HetInitiali3er>9ogicalMet!odIn.
o met!odIn.oB
at
S'stem)Web)Services)Protocols)Soap4eKectedE,tension)HetInitiali3ers>9ogicalMet!odIn
.o met!odIn.oF Soap4eKectedE,tensionST e,tensionsB
at S'stem)Web)Services)Protocols)SoapServer'pe))ctor>'pe t'peB
at S'stem)Web)Services)Protocols)SoapServerProtocol)Initiali3e>B
at S'stem)Web)Services)Protocols)ServerProtocolUactor')Create>'pe t'peF
;ttpConte,t conte,tF ;ttp4e5uest re5uestF ;ttp4esponse responseB
at
S'stem)Web)Services)Protocols)Soap;ttpClientProtocol)4ead4esponse>SoapClientMess
age messageF Web4esponse responseF Stream responseStreamB
at S'stem)Web)Services)Protocols)Soap;ttpClientProtocol)Invoke>String
met!od(ameF Ob2ectST parametersB
at 333)abc>B
at aaa)Main>B

These errors have occurred because the class 'mukhi' should have been derived from
the class SoapExtension. Hence, we do the same, as depicted below. Henceforth, we will
only display the class 'mukhi', since it contains the code that performs the required
task.

244025452.doc 120 od 274
aaa.cs
public class mu5(i , )ap>xtensi)n
{
}

During the compilation of the program, after having derived the class 'mukhi' from the
SoapExtenstion class, a few more errors are generated during the creation of the library.
This is for the reason that the class SoapExtension comprises of four abstract
functions, which are yet to be implemented.

Compiler Error
aaa)cs>7DF1=B: error CS-D6=: Jmuk!iJ does not implement in!erited abstract member

JS'stem)Web)Services)Protocols)SoapE,tension)HetInitiali3er>S'stem)Web)Services)Prot
ocols)9ogicalMet!odIn.oF
S'stem)Web)Services)Protocols)SoapE,tensionAttributeBJ

aaa)cs>7DF1=B: error CS-D6=: Jmuk!iJ does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tension)HetInitiali3er>S'stem)'peBJ

aaa)cs>7DF1=B: error CS-D6=: Jmuk!iJ does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tension)Initiali3e>ob2ectBJ

aaa)cs>7DF1=B: error CS-D6=: Jmuk!iJ does not implement in!erited abstract member
JS'stem)Web)Services)Protocols)SoapE,tension)
ProcessMessage>S'stem)Web)Services)Protocols)SoapMessageBJ

The next program incorporates the required functions in the class 'mukhi'.

aaa.cs
public class mu5(i , )ap>xtensi)n
{
public )verri*e v)i* 4nitialize()bject ))
{
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
return null;
}
public )verri*e )bject ?et4nitializer(:ype s)
{
return null;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
}
}

When the four functions are added, everything is hunky dory. At this stage, it is
inconsequential to attempt and gauge the wherewithal, i.e. how, when and why these
functions are called. We shall save the explanation for a rainy day.

aaa.cs
public class mu5(i , )ap>xtensi)n {
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
244025452.doc 121 od 274
/.Dlus(();
/.#l)se();
}
public )verri*e v)i* 4nitialize()bject ))
{
abc("4nitialize");
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
abc("?et4nitializer <");
return null;
}
public )verri*e )bject ?et4nitializer(:ype s)
{
abc("?et4nitializer @");
return null;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
abc("-r)cess'essage " C m.tage);
}
}

a.txt
?et4nitializer <
4nitialize
-r)cess'essage MeK)re0eserialize
-r)cess'essage 1Kter0eserialize
-r)cess'essage MeK)reerialize
-r)cess'essage 1Ktererialize

The class 'mukhi' now has a function abc, which accepts a string as a parameter. This
string is written to the fle c:\a.txt. The FileStream class constructor is used to specify
the fle name and the mode of operation of the fle. The two modes indicated here
facilitate addition of text to this fle.

Once this has taken efect, an object w, of type StreamWriter is created, by calling the
constructor of the object and supplying it with a FileStream object. The WriteLine
function in this class is then employed to write information onto the fle. The Flush
function actually implements the writing, and the Close function closes the writer.

Thus, each time the function abc is called, in efect, we are appending some text to this
fle. As an outcome, we are able to detect the functions that have been called, and their
sequence of execution, by merely examining the contents of the fle a.txt.

To begin with, the function GetInitializer, which accepts two parameters, gets called. It
is followed by the Initialize function. Then, it is the ProcessMessage function that gets
called four times; and on each occasion, it is called with a diferent value for the Stage
property. This property belongs to an enum named SoapMessageStage.
The frst value is BeforeDeserialize, which occurs after the system has received the
SOAP payload, but before it has deserialized the request. This is followed by the
AfterDeserialize message, where the system deciphers or deserializes the message, but
has not yet handed over the SOAP request packet to the asmx fle. The last two
messages deal with the reverse process, i.e. of sending the SOAP response payload over
to the client.

244025452.doc 122 od 274
Using the ProcessMessage function that gets called at a specifc instant in time, we can
smoothly construe the SOAP payload, which has either been received, or is being sent
across.

aaa.cs
public class mu5(i , )ap>xtensi)n
{
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public )verri*e v)i* 4nitialize()bject ))
{
abc("4nitialize");
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
abc("?et4nitializer <");
return null;
}
public )verri*e )bject ?et4nitializer(:ype s)
{
abc("?et4nitializer @");
return null;
}
tream );
tream n;
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
abc("1Ktererialize " C n.-)siti)n C " " C n.!engt( );
n.-)siti)n " 7;
:extWriter / " ne/ treamWriter());
:ext=ea*er r " ne/ tream=ea*er(n);
string s< " r.=ea*:)>n*();
/.Write!ine(s<);
abc(s<);
/.Dlus(();
}
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eerialize " C ).-)siti)n C " " C n.-)siti)n C " " C ).!engt( C " " C n.!engt( );
:extWriter / " ne/ treamWriter(n);
:ext=ea*er r " ne/ tream=ea*er());
string s " r.=ea*:)>n*();
/.Write!ine(s);
abc(s);
abc("MeK)re0eerialize< " C ).-)siti)n C " " C n.-)siti)n C " " C ).!engt( C " " C n.!engt( );
/.Dlus(();
abc("MeK)re0eerialize@ " C ).-)siti)n C " " C n.-)siti)n C " " C ).!engt( C " " C n.!engt( );
n.-)siti)n " 7;
}
}
public )verri*e tream #(aintream( tream s )
{
abc("#(aintream");
) " s;
244025452.doc 123 od 274
n " ne/ 'em)rytream();
return n;
}
}

a.txt
?et4nitializer <
4nitialize
#(aintream
MeK)re0eerialize 7 7 @JJ 7
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc xmlns""(ttp,33tempuri.)rg3" 3%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%
MeK)re0eerialize< @JJ 7 @JJ 7
MeK)re0eerialize@ @JJ B7< @JJ B7<
#(aintream
1Ktererialize B7A B7A
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3" 3%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

The singular objective of the above example is to display the SOAP packet, which is
either sent or received by the web server. Before we dive beneath the surface to explore
the details of its working, we need to ofer a terse explanation on XML serialization and
de-serialization.

The relevant parameters, such as function names and parameters in the SOAP payload,
needs to be extracted from the XML document. This act of extraction is termed as de-
serialization.

Before the system commences with the disintegration of the XML fle, it calls
ProcessMessage, with the value BeforeDeSerialize. Upto this instant, only the original
SOAP document is available in its pristine form, untouched by human hands!

Once the system extracts the requisite information from the XML fle, it calls the
ProcessMessage with the value AfterDeserialize; thus, intimating that the task has been
completed.

Now to send a value over, that is to create an XML fle containing the value , a process
called Serialization is executed. However, before this is carried out, the ProcessMessage
function is called, with the message code of BeforeSerialize. After the values have been
encoded into an XML document, the ProcessMessage gets called for the last time, with a
value of AfterSerialize.

Thus, at the stage of BeforeDeserialize, the original XML payload is available, and at the
stage of AfterSerialize, the XML document has been created. We concern ourselves with
244025452.doc 124 od 274
these events, since we intend to write the XML documents to the disk. The salient point
to be borne in mind is that, during the stage of Deserialization, the XML document is to
be read, whereas, at the time of Serialization, the document is to be written to.

Now, let us revert back to the program.
In the ProcessMessage function, there is an 'if' statement, which ascertains whether the
value of the Stage property is the enum value BeforeDeserialize, which belongs to the
enum SoapMessageStage. If the 'if' statement passes muster, it signifes that the
incoming SOAP payload must be read.

Using the function abc, the message is written to the fle. However, on closer
examination, we realize that the function ChainStream gets called frst. A Stream
parameter is passed to this function. This parameter is used extensively when the XML
documents are to be read or written to, coupled with the SOAP payload.

As the Stream object is very crucial to get at the SOAP payload, its value is saved in a
public variable named 'o'. Thereafter, a variable 'n', which has been created earlier, is
initialized to a MemoryStream object. Then, it is duly returned. We shall ponder upon it
and scrutinize this return value a little later.

The Stream class is incapable of reading and writing. Therefore, a StreamReader object
named 'r' is created, whose constructor is passed the Stream 'o'. We could have
specifed the data type StreamReader for 'r', but we have specifed the abstract class
TextReader instead, since the StreamReader class is eventually derived from the
TextReader class. This was done for yet another reason, i.e. all the illustrations
furnished by Microsoft have also resorted to the above technique.

Stream variable named 'n', which has been declared earlier and initialized to
MemoryStream in the ChainStream function, is used to create a StreamWriter object.
The Position property of the Stream reveals the cursor position or the byte number,
where the data would be written. The Length property contains the number of bytes in
the Stream.

As we are at the initial stages of execution, the position of fle pointer in the stream that
is to be read is 0, and its length is 299 bytes. It is a well-known fact that the size of a
SOAP request is 299 bytes. The stream that is used for writing, does not embody any
value. Hence, the position of the fle pointer is at zero, and the value of the length too is
zero.

The ReadToEnd function reads all the data upto the end of the stream, and returns it in
a string format, ensconced in the variable 's'. The WriteLine function in the TextWriter
object w, fnally writes the string s to the MemoryStream n. The function abc writes the
string to the fle a.txt.

The function ReadToEnd then moves the fle pointer to the last byte that it has read.
Since 299 bytes have been read, the fle pointer is now positioned at byte 299. The
Gordian Knot or the dilemma here is that, the fle pointer for the writer has remained
static at position 0. It is the function Flush that actually writes to disk, thereby,
updating the values contained in Position and Length.
244025452.doc 125 od 274

Writing to a fle on disk is an expensive process. Therefore, it is economical to
consolidate all the Writes. In addition to the existing bytes, two extra bytes get added.
Since, the fle pointer is stuck at byte 301 in the writer at this stage, it is binding to set
it to 0, as this is what the system anticipates.

Please note that the system will interpret the data written to the stream 'n' as the
incoming data. Efectively, we have just copied data from one stream to another.
However, very soon, we shall amend the data passed to the asmx fle.
Now that we have read the incoming stream, and written it out, let us examine the
message AfterSerialize. At this point in time, the situation is as follows:
There is an XML document response, which is ready to bolt the stable doors and
reach the client.
The MemoryStream n contains 307 bytes of data within it.
The fle pointer is positioned at the end of the fle.

Firstly, the fle pointer is repositioned at the absolute start position. Thereafter, a reader
is created using the stream 'n', unlike on the last occasion, where it was used for
creating a writer. As the ChainStream function always gets called, the Stream 'o' is used
for writing, and not for reading. Any data that is written to this stream, shall be sent to
the client.

To summarise, the system frst calls ChainStream, obtains a return stream object,
writes 307 bytes in it, and then, calls AfterSerialize. Subsequent to this, the bytes are
written to the stream 'o'. Previously, the stream 'o' was used to read the incoming SOAP
request. But now, we use it to write the SOAP response. In the bargain, both, the
response and request packets are saved to the fle on disk.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
&vijay()+
public int abc(int i6 int j)
{
return i C j;
}
}

a.cs
class aaa {
public static v)i* 'ain()
{
zzz a" ne/ zzz();
int 5 " a.abc(<76@7);
ystem.#)ns)le.Write!ine(5);
}
}

aaa.cs
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eerialize " C ).-)siti)n C " " C n.-)siti)n C " " C ).!engt( C " " C n.!engt( );
244025452.doc 126 od 274
:extWriter / " ne/ treamWriter(n);
:ext=ea*er r " ne/ tream=ea*er());
string s " r.=ea*:)>n*();
int j " @AH;
abc(s&j+.:)tring());
abc(s&jC<+.:)tring());
abc(s&jC@+.:)tring());
abc(s&jCB+.:)tring());
/.Write!ine(s);
abc(s);
abc("MeK)re0eerialize< " C ).-)siti)n C " " C n.-)siti)n C " " C ).!engt( C " " C n.!engt( );
/.Dlus(();
n.-)siti)n " @AH;
/.Write(UHU);
/.Dlus(();
n.-)siti)n " 7;
}

Output
@-

SOAP 4e5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"2*7-"12*
"1abc*

a)t,t
Initiali3e
C!ainStream
:e.oreEeSeriali3e - - 6=6 -
1
-
"
1
"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"i*1-"1i*
"2*7-"12*
"1abc*
"1soap::od'*
"1soap:Envelope*
:e.oreEeSeriali3e1 6=6 - 6=6 -
C!ainStream
A.terSeriali3e 6D0 6D0
"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*@-"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

244025452.doc 127 od 274
Let us attempt at appreciating the SOAP extensions from a fresh perspective. The asmx
fle has the familiar function abc, which now accepts two parameters and returns an
int. Since we want to trace the bytes that are traversing to and fro, we shall follow the
same process that has been executed innumerable times before.

In other words, before running the batch fle z.bat, we shall create a wsdl fle and
modify the port number of localhost to 8080. The values assigned to the function abc
are 10 and 20. Thus, the expected output is the value 30. However, it is quite
astonishing to fnd the value 60 being displayed. There is defnitely something wrong
somewhere!
We have only displayed the 'if' statement, which gets activated when the
BeforeDeserialize event gets triggered. At this instant, the string 's' contains the entire
SOAP payload. On examining bytes 274 to 277 of the SOAP payload, we realize that byte
274 holds the digit 1, of the number 10. This is the content of the variable i. The string
is written and fushed in the MemoryStream, as before.

Then, the fle pointer is positioned at byte 274, and using an overload of the Write
function, the value of 1 is replaced by the ASCII character 4. Thus, the value changes
from 10 to 40, resulting in a return value of 60, instead of the expected 30. All
characters written to the stream 'n' get amalgamated into the incoming SOAP packet.
Therefore, the original stream 's' is not read at all, since the stream that returned, is the
one that is sent to the asmx fle.

In a situation where the client compresses a fle and sends it to the server, the server
must have a program running, which will receive the bytes and decompress them,
before placing the new contents in the stream 'n'.

The SOAP request that is received by the trace, contains the numbers 10 and 20. This
is because the trace receives the output before it is sent over to the server. Thus, the
trace and the client will notice the same SOAP packet. The change is made to the
stream 'n', and not to 's'. The contents that are visible in the a.txt fle, are a spitting
image or a replica of what the client sends to the trace program. These contents are
eventually forwarded to the server.

aaa.cs
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
n.-)siti)n " 7;
:extWriter / " ne/ treamWriter());
tream=ea*er r " ne/ tream=ea*er(n);
string s< " r.=ea*:)>n*();
abc(s<);
string s@ " s<.=eplace("I7"6"J7");
/.Write!ine(s@);
/.Dlus(();
}

Output
A-

a)t,t
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*@-"1abc4esult*
244025452.doc 128 od 274
"1abc4esponse*

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*A-"1abc4esult*
"1abc4esponse*

In the aaa.cs fle, we have only displayed the AfterSerialize message. At this stage, we
are aware that the string read from the Stream 'n' contains the SOAP output. Now,
instead of writing it directly to the Stream 'o' that is received from ChainStream, we frst
write the characters to the fle a.txt, in order to verify the result to be 60.

Then, by using the Replace function, all occurrences of the string 60 in the string s1,
are replaced by 90. The return value contains the modifed string. This new string s2 is
then sent across to the client. Since the packet reaches the trace program frst, the
SOAP response displays the result as 90. Also, since the value being sent across is 90,
the output of the client is displayed as 90.

We have just demonstrated how we can exercise absolute control over both, the SOAP
payload that is being sent to the asmx fle, and the packets being sent from the server
to the client.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay()+
public v)i* abc()
{
}
&Web'et()*+
&vijay()+
public v)i* pPr()
{
}
}

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
a.abc();
a.abc();
a.pPr();
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Web.ervices.-r)t)c)ls;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
244025452.doc 129 od 274
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get {
return 7;
}
set { }
}
}
public class mu5(i , )ap>xtensi)n
{
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public mu5(i()
{
abc("#)nstruct)r");
}
public )verri*e v)i* 4nitialize()bject ))
{
abc("4nitialize " C ));
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
abc("?et4nitializer < " C m);
iK ( m.9ame "" "abc")
return "s)nal";
else
return "mu5(i";
}
public )verri*e )bject ?et4nitializer(:ype s)
{
abc("?et4nitializer @");
return null;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
abc("-r)cess'essage " C m.tage);
}
}

a.txt
#)nstruct)r
?et4nitializer < Q)i* abc()
#)nstruct)r
?et4nitializer < Q)i* pPr()
#)nstruct)r
4nitialize s)nal
-r)cess'essage MeK)re0eserialize
-r)cess'essage 1Kter0eserialize
-r)cess'essage MeK)reerialize
-r)cess'essage 1Ktererialize
244025452.doc 130 od 274
#)nstruct)r
4nitialize s)nal
-r)cess'essage MeK)re0eserialize
-r)cess'essage 1Kter0eserialize
-r)cess'essage MeK)reerialize
-r)cess'essage 1Ktererialize
#)nstruct)r
4nitialize mu5(i
-r)cess'essage MeK)re0eserialize
-r)cess'essage 1Kter0eserialize
-r)cess'essage MeK)reerialize
-r)cess'essage 1Ktererialize

The asmx fle has two functions named abc and pqr, containing the attribute 'vijay'. The
client program calls the function abc twice, and the function pqr only once. The aaa.dll
as usual, contains the function abc. Additionally, it contains the GetInitializer function,
which displays the string representation of the frst parameter, i.e. LogicalMethodInfo.

The SOAP Extension should at no cost, trammel the speed of the system. To ensure
this, the framework frst ascertains the number of functions contained in the asmx fle,
and then, it creates an equal number of copies of the class mukhi. Since the asmx fle
has two functions, the constructor is called twice.

Then, it calls the function GetInitializer with two parameters. The frst parameter is a
LogicalMethodInfo that represents a function. The String representation displays the
prototype of the string.

This class has a function called 'name', which provides the name of the function having
the attribute of 'vijay'. Thus, on the frst occasion, the GetInitializer gets called because
of the function abc, while on the second occasion, it is called due to the function pqr.
The task of GetInitializer is to return a value, which will be passed to the Initialize
function. The Name property ascertains whether the name of the function is abc or not.
If it is so, the value returned is 'sonal', or else, it is 'mukhi'. This entire process is
executed only once. This value that is returned is cached internally.

Each time a function gets called, its constructor gets called once. Thereafter, the
function 'Initialize' gets called, with the value that is returned by function GetInitializer.
Thus, calling the function abc twice, results in a call to the Initialize function, with the
parameter value of 'sonal'. This is how depending upon the function name, parameters
can be passed to functions.

To summarize, when a function is called manifold times, GetInitializer gets called only
once; whereas, the Constructor and the Initialize function get called every time that the
function is executed. The function ProcessMessage gets called four times per function
call.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay(Dilename""c,FFz.txt")+
244025452.doc 131 od 274
public v)i* abc()
{
}
&Web'et()*+
&vijay(Dilename""c,FFz<.txt")+
public v)i* pPr()
{
}
&Web'et()*+
&vijay()+
public v)i* xyz()
{
}
}

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
a.abc();
a.abc();
a.pPr();
a.xyz();
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Web.ervices.-r)t)c)ls;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
private string Ki " "c,FFz@.txt";
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get
{
return 7;
}
set
{
}
}
public string Dilename
{
get
{
return Ki;
}
set
{
Ki" value;
}
244025452.doc 132 od 274
}
}
public class mu5(i , )ap>xtensi)n
{
string K;
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
vijay b " (vijay)a;
return b.Dilename;
}
public )verri*e )bject ?et4nitializer(:ype s)
{
return type)K(vijay);
}
public )verri*e v)i* 4nitialize()bject ))
{
K " (string) );
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream(K6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Ktererialize)
abc("-r)cess'essage " C m.tage);
}
}


z.txt
-r)cess'essage 1Ktererialize
-r)cess'essage 1Ktererialize

X<.txt
-r)cess'essage 1Ktererialize

X@.txt
-r)cess'essage 1Ktererialize

This program demonstrates the phenomenon of passing data dynamically onto the
SOAP extension.

For the frst time, we have passed a parameter named FileName, to the attribute of
'vijay'. The frst two functions, abc and pqr, use a diferent flename, while the last
function, xyz uses none. This parameter is primarily used to determine the fle name
that is to be used while writing the text. A total of three fles are created in the root.

The client program a.cs merely calls the three functions, viz. abc, pqr and xyz. In
aaa.cs, the class 'vijay' is of prime signifcance. Since every parameter to an attribute
must have a corresponding public property by the same name, there exists a property
called 'Filename'. The task of this read-write property is to return the value held in the
variable 'f' to the 'get' accessor. It is also responsible for setting the same variable to the
244025452.doc 133 od 274
reserved parameter value, in the 'set' accessor. The string 'f' is used only to store the
state or value of the property Filename.

Technically speaking, the state of the property Priority should also be stored in a
variable, but since we are not interested in its value, we do not do the same. The
GetInitializer function gets called frst. Its second parameter is a handle to the attribute
class 'vijay'. The parameter is cast to type 'vijay', and then, the Filename property value
is returned.

The function abc sets the value of 'f' to "C:\z.txt", and the function pqr sets the value of
'f' to "c:\z1.txt". Since the function xyz does not call this property at all, the default
value of 'f', i.e. "c:\z2.txt", remains unchanged. When the Initialize function gets called,
the above values are sent across as parameter values. The string 'f' is initialized to the
parameter 'o' that is passed.

Thus, whenever the function abc gets called in the function ProcessMessage, it assigins
a value to the variable 'f' depending upon the function being called.

Thus, the function abc now stores its data in three diferent fles, namely, z.txt, z1.txt
and z2.txt. This program demonstrates how an attribute can accept parameters, and
thereafter, pass them on to the class 'mukhi'.

Now, we intend to capture the Headers in our trace program. So, we implement the
program from the Soap Headers chapter, which sends across a header. The
SoapMessage parameter is going to be the main focus of the residual programs of this
chapter.

a.cs
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class aaa , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public yyy b;
public static v)i* 'ain()
{
aaa a" ne/ aaa();
a.b " ne/ yyy();
a.b.name""vijay" ;
a.b.pass""s)nal" ;
a.abc();
}
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("b")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
public v)i* abc()
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&7+);
}
public aaa()
{
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
}
}
public class yyy , )ap.ea*er
{
public string name;
244025452.doc 134 od 274
public string pass;
}

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay()+
public v)i* abc()
{
}
}

aaa.cs
public class mu5(i , )ap>xtensi)n
{
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
return null;
}
public )verri*e )bject ?et4nitializer(:ype s)
{
return type)K(vijay);
}
public )verri*e v)i* 4nitialize()bject ))
{
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Kter0eserialize)
{
)ap.ea*er#)llecti)n s;
s " m..ea*ers;
abc(s.#)unt.:)tring());
)ap2n5n)/n.ea*er ( " ()ap2n5n)/n.ea*er)s&7+;
ystem.Oml.Oml>lement e " (.>lement;
abc(e.;uterOml);
}
}
}

a.txt
<
<yyy xmlns""(ttp,33tempuri.)rg3"%
<name%vijay<3name%
<pass%s)nal<3pass%
<3yyy%

We commence with a simple asmx fle, where the function abc returns a void. The
header program is modifed to return a void instead of a string. In any case, there is no
rationale behind complicating the code unnecessarily.
244025452.doc 135 od 274

In order to identify the headers that have been received, we are required to wait for the
AfterDeserialize event to occur, since the incoming XML has still not been parsed in the
BeforeDeserialize event.

In the AfterDeserialize event, it is the SoapHeaderCollection object named 's' that is
created frst. It is then initialized to the value contained in the Headers property of the
SoapMessage Object, m. The class SoapHeaderCollection, being a collection class, has a
property called Count, which identifes the number of SoapHeader objects contained in
the collection class. Presently, since only a single header exists, our output displays a
value of one.

With the help of the indexer, s[0] the single SoapHeader object is retrieved and stored in
h, a variable of type SoapUnknownHeader.
Since h is not of type SoapHeader, the use of a cast operator is imperative.

Thereafter, the Element property in the object is employed to initialize an object of type
XmlElement. The entire node is then displayed, using the OuterXml function.

This is how we can display the headers that are sent across. BeforeSerialize is the other
event where we deal with headers. This property is read-only. Therefore, we cannot
amend the headers using this property.

Next, we present the smallest asmx fle, as well as, the smallest client. We don't come
across any of the complications that were present in other programs, such as the trace
program, etc.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
&vijay()+
public int abc(int i6 int j)
{
return i C j;
}
}

a.cs
class aaa {
public static v)i* 'ain() {
zzz a" ne/ zzz();
int 5 " a.abc(<76@7);
ystem.#)ns)le.Write!ine(5);
}
}

aaa.cs
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Kter0eserialize)
{
abc(m.1cti)n);
abc(m.'et()*4nK).:)tring());
244025452.doc 136 od 274
abc(m.;neWay.:)tring());
abc(m.2rl);
}
}

a.txt
(ttp,33tempuri.)rg3abc
4ntB@ abc(4ntB@6 4ntB@)
Dalse
(ttp,33l)cal()st3a.asmx

This program outputs four properties of the SoapMessage class, which are written to
the fle a.txt. These properties are as follows:
The frst property is the familiar Action property, which displays the value of the
SOAPAction HTTP header. This is the only HTTP header that SOAP introduces.
The second property is the MethodInfo property, which provides all the details about
a function. It helps us to structure our code to act in a particular way, depending upon
the call to a specifc function.
The third property is the OneWay property, which returns the value of the OneWay
property of the SoapDocumentMethodAttribute attribute. Here, the value is 'false'.
The fourth property is the URL property, which reveals the URL of the remote server,
where the execution takes place.

aaa.cs
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Kter0eserialize)
{
int i;
i " (int)m.?et4n-arameterQalue(7);
abc(i.:)tring());
i " (int)m.?et4n-arameterQalue(<);
abc(i.:)tring());
}
}

Output
6-

a)t,t
1-
7-

The SOAP payload triggers of the BeforeSerialize event, when it frst arrives at the web
server. Thereafter, the XML fle is Deserialized, wherein, all the parameters are extracted
from the XML document.

Once this is over, the AfterDeserialize event gets triggered. Here, we use the function
GetInParameterValue with the parameter 'number', and obtain the values of the
parameters that are passed. Thus, the index 0 returns the value of i, and the index 1
returns the value of j. This is a useful way of ascertaining the values of parameters
directly, instead of parsing the XML stream manually, since the manual process is
extremely time consuming.

a.asmx
<%@ Webervice !anguage""#$" class""zzz" %%
using ystem;
244025452.doc 137 od 274
using ystem.Web.ervices;
public class zzz {
&Web'et()*+
&vijay()+
public int abc(reK int i6int j 6 reK int 5)
{
return @BH;
}
}
a.cs
class aaa {
public static v)i* 'ain()
{
zzz a" ne/ zzz();
int p " B7;
int P " @7;
a.abc(reK p6@76 reK P);
}
}

aaa.cs
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.MeK)reerialize)
{
int i;
i " (int)m.?et;ut-arameterQalue(7);
abc(i.:)tring());
i " (int)m.?et;ut-arameterQalue(<);
abc(i.:)tring());
}
}

a.txt
B7
@7

The asmx fle has a function abc, which starts with a 'ref' parameter, followed by an 'int'
parameter, and fnally, ends with a 'ref' parameter. The client program follows along the
same lines. Since the BeforeSerialize event gets fred, it provides ample proof that the
'out' parameters have been assigned values, and that, the function abc has been called.

Thus, the function GetOutParameterValue in the event BeforeSerialize, provides the
value stored in the 'out' parameters, only when it is assigned a number. Thus, the index
0 represents the variable 'i', and the index 1 represents the second 'out' parameter 'q'.
This is because, it is the second 'out' parameter, though overall, it is the third
parameter in the parameter list,
aaa.cs
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.MeK)reerialize)
{
int i;
i " (int)m.?et=eturnQalue();
abc(i.:)tring());
}
}

a.txt
@BH
244025452.doc 138 od 274

(he :e!oreSeriali;e e'ent can also sul& the return 'alue. (he !unction a)c returns 234,
which is the 'alue returned !ro* the !unction <et3eturn=alue. 0t this oint, we cannot a*end
an& o! these 'alues, since these 'alues are >read?onl&>.


Encr'pting and Eecr'pting Soap
Eata

This chapter dapples with Encrypting and Decrypting Soap Headers. It presupposes
that you would possess some basic knowledge of the elements contained in an XML
document. To put it precisely, it expects you to be cognizant of the process of accessing
the contents of the nodes that constitute an XML document. This is for the reason that
a SOAP payload is merely an XML document consisting of nodes, which in turn, also
have nodes. These nodes are required to be accessed prior to modifying their contents.

The opening program in this chapter elucidates and establishes how you can gain
access to a node in an XML fle, in order to extract the relevant information from it. We
have created a new directory named ddd in the root, and created the following two fles
in this directory:

a.cs
using ystem;
using ystem.4;;
using ystem.Oml;
public class zzz
{
public static v)i* 'ain()
{
Diletream s " ne/ Diletream("a.txt"6 Dile')*e.;pen6 Dile1ccess.=ea*);
Oml:ext=ea*er r " ne/ Oml:ext=ea*er (s);
Oml0)cument * " ne/ Oml0)cument();
*.!)a*(r);
Oml9amespace'anager m " ne/ Oml9amespace'anager(*.9ame:able);
m.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n;
n " *.electingle9)*e("33s)ap,M)*y"6 m);
ystem.#)ns)le.Write!ine(n.4nner:ext C " " C n.9ame);
n " n.Dirst#(il*;
ystem.#)ns)le.Write!ine(n.4nner:ext C " " C n.9ame);
n " *.electingle9)*e("33s)ap,M)*y"6 m);
n " n.Dirst#(il*.Dirst#(il*;
ystem.#)ns)le.Write!ine(n.4nner:ext C " " C n.9ame);
}
}

a.txt
<Nxml versi)n""<.7" enc)*ing""utKG8" N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%vijay mu5(i<3abc=esult%
<3abc=esp)nse%
244025452.doc 139 od 274
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

Compile the .cs fle using the csc compiler, and then, run the executable. The output
generated is shown below.

Output
vi2a' muk!i soap::od'
vi2a' muk!i abc4esponse
vi2a' muk!i abc4esult

This program kicks-of and gets going by creating object 's', which is an instance of a
FileStream class. This constructor accepts three parameters:
The name of the fle - a.txt,
The mode to decide whether the File should be created or not - FileMode.Open
Whether the fle is to be opened for reading or writing - FileAccess.Read.

The fle a.txt is a clone of one of the SOAP responses received earlier by the client from
the server.

Now, in order to access specifc parts of the SOAP response packet, an object r of type
XmlTextReader is created. The XmlTextReader class requires either a Stream object or a
class derived from the Stream class as a parameter. Hence, the constructor is supplied
with the FileStream object 's'.

Once we have introduced a class that can read our XML fle from disk, we require the
services of another class named XmlDocument, which shall facilitate access to this XML
fle. The Load function in the XmlDocument object d is passed an XmlTextReader
object. Now, when the object d is used, it allows access to each individual node in the
fle.

Every XML Document has a NameTable object, which stores the names of the elements
and attributes, in the form of atomized strings. The data type of the NameTable is
XmlNameTable.

The XmlNamespaceManager class deals with namespaces, which is perfectly suited to
our requirement. The constructer is given a NameTable property as a parameter. The
namespace prefxes are associated with the URIs using this Namespace manager. On a
perusal of the a.txt fle, you would notice that all the elements are prefaced by the
namespace 'soap', which has a URI of http://schemas.xmlsoap.org/soap/envelope/.
Therefore, this pair must be registered with the Namespace manager.

The XmlNode object is used to represent a node in the XML fle. The SelectSingleNode
function in the object is employed to return the frst node for the specifed parameter. In
this case, the frst node is returned as 'Body', with a namespace prefx of 'soap'. The
second parameter to the function is the namespace manager 'm', which is conversant
with the 'soap' namespace prefx. In order to verify the outcome of our actions so far, we
display the InnerText and the Name properties of the node that we are currently
pointing to.

244025452.doc 140 od 274
The InnerText property provides the fnal content, which could include the child
elements; while the Name property provides the full name, including the namespace
prefx soap. Thus, the InnerText is 'vijay mukhi', and the Name is 'soap:Body'.

Each node is blessed with children and grandchildren. The FirstChild property provides
a handle to the frst child, abcResponse. The InnerText property ofers the same answer
as before, i.e. 'vijay mukhi', since the node of abcResult contains this text. In order to
access the grandchild abcResult, the FirstChild of the abcResponse node is employed.
We have printed out its name for the purpose of verifcation. Thus, we now have a
mechanism to access the diferent nodes embodied in the XML fle.

a.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
public class zzz
{
public static v)i* 'ain()
{
string s;
s " "<Nxml versi)n"F"<.7F" enc)*ing"F"utKG8F" N%Fn<s)ap,>nvel)pe
xmlns,s)ap"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3F"
xmlns,xsi"F"(ttp,33///./B.)rg3@77<3O'!c(emaGinstanceF"
xmlns,xs*"F"(ttp,33///./B.)rg3@77<3O'!c(emaF"%Fn<s)ap,M)*y%<abc=esp)nse
xmlns"F"(ttp,33tempuri.)rg3F"%Fn<abc=esult%vijay mu5(i<3abc=esult%Fn
<3abc=esp)nse%<3s)ap,M)*y%<3s)ap,>nvel)pe%";
byte&+ ms " >nc)*ing.2:D8.?etMytes(s);
'em)rytream ms< " ne/ 'em)rytream(ms);
Oml:ext=ea*er r " ne/ Oml:ext=ea*er(ms<);
Oml0)cument * " ne/ Oml0)cument();
*.!)a*(r);
Oml9amespace'anager m " ne/ Oml9amespace'anager(*.9ame:able);
m.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n;
n " *.electingle9)*e("33s)ap,M)*y"6 m);
n " n.Dirst#(il*;
ystem.#)ns)le.Write!ine(n.4nner:ext C " " C n.9ame);
}
}

Output
vi2a' muk!i abc4esponse

This example is at a slight variance with the earlier one. Instead of opening a fle
containing the xml code, it now contains a String s, which represents the entire XML
fle.

The string has to be converted into an array of bytes. To achieve this, we utilise the
static GetBytes function. The array of bytes received from the function, is then supplied
to the MemoryStream constructor.

The MemoryStream class, derived from the Stream object, represents a stream in
memory, and not on disk. Thus, we are entitled to supply the MemoryStream object to
the XmlTextReader constructor. The rest of the program is identical to the earlier one.

244025452.doc 141 od 274
a.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
public class zzz
{
public static v)i* 'ain()
{
string s;
s " "1M#";
byte&+ ms " >nc)*ing.2:D8.?etMytes(s);
'em)rytream ms< " ne/ 'em)rytream(ms);
byte&+ ms@ " ms<.:)1rray();
tringMuil*er s< " ne/ tringMuil*er();
K)r(int i"7; i<ms@.!engt(; iCC)
{
iK(i""(ms@.!engt(G<))
s<.1ppen*(ms@&i+);
else
s<.1ppen*(ms@&i+ C " ");
}
#)ns)le.Write!ine(s<);
}
}

Output
@D @@ @I

In the above program, a string variable 's' is initialized to ABC. Now, we intend to
convert the string into an array of bytes. For this, we use the GetBytes function. The
output is stored in the byte array called 'ms'. This byte array represents our string. It is
thereafter, supplied to a MemoryStream object named 'ms1'.

After having converted the string into a stream, we embark on the reverse procedure,
i.e. we use the ToArray function of the MemoryStream class, to convert a stream back
into an array of bytes. Thereafter, the StringBuilder class is used to display this array.

The byte array has a size of 3, since the string has three characters. Now, using the 'for'
loop, the individual strings are appended to the StringBuilder object s1, thereby,
concatenating all of them. Since we desire to insert a space between the individual
numbers, an extra space is subjoined while adding the number to the StringBuilder
object. However, no space is added after the last character. Finally, the three numbers,
along with the spaces, are displayed using the WriteLine function with s1 .

Having grappled with these essentials, we now progress onto the very heart of the
chapter, i.e. Encryption and Decryption.


DES is an acronym for Data Encryption Standard. It is one of the most widely used
standards for encryption. Other symmetric algorithms, such as RC2, also exist.

Symmetric algorithms use the same key or password for encryption and decryption;
while the Asymmetric algorithms, such as private key and public key, use diferent
passwords or keys for encryption and decryption. A password and key are synonyms,
244025452.doc 142 od 274
wherein, passwords are English-like and can easily be committed to the memory;
however, keys cannot be memorized.

One of the most widely used techniques in the world of security is authentication of
messages, where algorithms like MD5 or Message Digest 5 are implemented. On the
basis of the message text, a MD5 hash number is generated for the document. This
document is then sent across the wire, along with the number in an encrypted form. In
the event of a single byte of the fle being tampered with, the hash would change,
thereby, apprising the receiver of the fact that the document has been modifed in
transit.

Given below is an example of DES, where bytes are encrypted and the new value is
displayed.

a.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.ecurity.#rypt)grap(y;
public class zzz
{
public static v)i* 'ain()
{
Myte&+ 5 " {<6 @6 B6 H6 E6 I6 A 6 8};
Myte&+ 5< " {H6E6I6A686J6<76<<};
0>#rypt)ervice-r)vi*er * " ne/ 0>#rypt)ervice-r)vi*er();
'em)rytream ms< " ne/ 'em)rytream();
#rypt)tream s " ne/ #rypt)tream (ms<6 *.#reate>ncrypt)r( 56 5< )6 #rypt)tream')*e.Write);
byte&+ b " >nc)*ing.2:D8.?etMytes("1M#0");
s.Write(b6 76b.!engt();
s.Dlus(DinalMl)c5();
byte&+ b< " ms<.:)1rray();
tringMuil*er s< " ne/ tringMuil*er();
K)r(int i"7; i<b<.!engt(; iCC)
{
iK(i""(b<.!engt(G<))
s<.1ppen*(b<&i+);
else
s<.1ppen*(b<&i+ C " ");
}
#)ns)le.Write!ine(s<);
}
}

Output
A@ 71@ 170 1-I 77@ 1-= 1@= D0

We commence by creating an object of type DESCryptoServiceProvider, which is in the
namespace of System.Security.Cryptography. This namespace has infnite classes for
encoding and decoding data, hashing, generating random numbers, et al. The class
DESCryptoServiceProvider is the only pathway granting access to the classes that deal
with the DES standard.

244025452.doc 143 od 274
Therefore, we frst create an object of type DESCryptoServiceProvider, and then, set up
a memory stream. To comprehend DES, we also need to create an object 's', of the class
CryptoStream. The constructor of this class is supplied with three parameters.

The frst parameter is a stream, which shall hold the results of the encryption. Since we
are not too keen on saving this output to a fle on disk, we have specifed a memory
stream named 'ms1'.

The second parameter is of type ICryptoTransform. The value specifed here determines
the cryptographic transform that is required to be carried out. One such value that can
be specifed is 'hashing'. The CreateEncryptor function in object 'd', accepts two
parameters:
An 8-byte key or password in k
An 8-byte initialization in k1.

In real life, the password should be larger, and should normally contain some random
digits. Thus, the output generated would be used to encrypt the string "ABCD".

The last parameter is an enum CryptoStreamMode that can take either of the two
values, Read or Write. As we wish to write into the stream, the value given here is
CryptoStreamMode.Write.

The string "ABCD" is then converted into an array of bytes. This is because, in the .Net
world, an array of bytes is given preference over a string. As humans, we love to work
with strings, but here, who pays heed to our preferences? The array is then written to
the CryptoStream, using the Write function. There are three parameters to the Write
function:
The byte array b.
The starting point.
The length of the byte array.

As always, the bytes are fushed.

The next task is to ascertain the contents of the MemoryStream object ms1, which was
passed to the constructer of the CryptoStream class. ms1 now contains the string
"ABCD" in its encrypted form.

To do so, the function ToArray of the Memory Stream is utilized to return the data that
it contains, in the form of a series of bytes. The output displayed is the encrypted form
of the string "ABCD". Since we wish to insert a space between each number that is
displayed, we pursue an approach similar to the one that we had adopted earlier, in the
case of the StringBuilder class. The encrypted form of the string "ABCD" is displayed,
along with the spaces that we have inserted.

a.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.ecurity.#rypt)grap(y;
public class zzz
244025452.doc 144 od 274
{
public static v)i* 'ain()
{
Myte&+ 5 " {<6 @6 B6 H6 E6 I6 A 6 8};
Myte&+ 5< " {H6E6I6A686J6<76<<};
0>#rypt)ervice-r)vi*er *es " ne/ 0>#rypt)ervice-r)vi*er();
string s " "JI @<I <@8 <7A @@I <7H <IH E8";
c(ar&+ c " {U U};
string&+ ss " s.plit(c);
byte&+ b " ne/ byte&ss.!engt(+;
K)r(int i"7; i<b.!engt(; iCC)
{
b&i+ " Myte.-arse(ss&i+);
}
'em)rytream ms " ne/ 'em)rytream();
#rypt)tream cs " ne/ #rypt)tream(ms6 *es.#reate0ecrypt)r ( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(b6 76b.!engt();
cs.Dlus(DinalMl)c5();
byte &+ b@ " ms.:)1rray();
string s< " >nc)*ing.2:D8.?ettring(b@);
#)ns)le.Write!ine(s<);
}
}

Output
A:CE

This program, in a sense, is a continuation of the earlier program. The encrypted data is
now decrypted, using the DES standards.

The string 's' is initialized to the encrypted form of the string "ABCD", as displayed in
the earlier program. Since the spaces are also part of the string, the frst task is to get
rid of these spaces. They were inserted in the earlier program, for visual clarity of the
numbers. In order to remove these spaces, we have created a single byte array of chars,
containing only one character, i.e. 'space'.

The 'split' function that is part of the String class, accepts one parameter, and splits a
string on the occurrence of a specifc character or characters, in the array of chars. In
our case, the string is split into 8 strings, since there are a total of 7 spaces. These 8
numbers are accommodated in a new string array named 'ss'.

Finally, we need to copy these 8 strings into the array of bytes named 'b'. The Byte class
has a static Parse function, which converts a string stored in an array location into a
byte.

Thereafter, just like before, a memory stream object ms is created to contain the new
value in the memory. The CryptoStream object 'cs' is created, but it now employs the
CreateDecryptor function, since we want to decrypt the contents. The last enum
parameter is Write, because we intend to write the decrypted string to the memory
stream.

The Write function in the CryptoStream class obtains the array of bytes from the byte
array containing the encrypted data, and then, uses the DES standard to decrypt it.

244025452.doc 145 od 274
As we are keen on witnessing the outcome of our actions, we convert the Memory
Stream object ms into a byte array 'b2', and then, use the GetString function to convert
this byte array into a string.

The output reveals the string "ABCD", thus proving beyond doubt, that the string
"ABCD" was encrypted into some unintelligible mumbo-jumbo using DES, and
thereafter, the mumbo-jumbo was decrypted back to the string "ABCD".
a.aspx
<.:'!%
<.>10%
<script language""c$" runat"server%
public v)i* -ageT!)a*()
{
zzz a " ne/ zzz();
l.4nner.tml " a.abc();
}
<3script%
<3.>10%
<M;0S%
<b i*""l" runat""server"3%
<3.:'!%

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay+
public string abc()
{
return "1M#0";
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.ecurity.#rypt)grap(y;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get
{
return 7;
}
set
244025452.doc 146 od 274
{
}
}
}
public class mu5(i , )ap>xtensi)n
{
tream );
tream n;
Myte&+ 5 " {<6 @6 B6H6E6 I6 A 6 8};
Myte&+ 5< " {H6E6I6A686J6<76<<};
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
return a;
}
public )verri*e )bject ?et4nitializer(:ype t)
{
return type)K(vijay);
}
public )verri*e v)i* 4nitialize()bject i)
{
return;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eserialize");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(n);
/.Write!ine(r.=ea*:)>n*());
/.Dlus(();
n.-)siti)n " 7;
}
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
abc("1Ktererialize " C n.-)siti)n);
n.-)siti)n " 7;
Oml:ext=ea*er rr " ne/ Oml:ext=ea*er(n);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(rr);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
abc(n).9ame C " " C n).4nner:ext);
n) " n).Dirst#(il*.Dirst#(il*;
abc(n).9ame C " " C n).4nner:ext);
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
byte&+ inp " >nc)*ing.2:D8.?etMytes(n).4nner:ext);
'em)rytream ms< " ne/ 'em)rytream();
#rypt)tream cs " ne/ #rypt)tream(ms<6 *e.#reate>ncrypt)r( 56 5< )6
#rypt)tream')*e.Write);
abc("'em)ry tream MeK)re" C ms<.-)siti)n);
cs.Write(inp6 76 inp.!engt();
abc("'em)ry tream MeK)re" C ms<.-)siti)n);
cs.Dlus(DinalMl)c5();
abc("'em)ry tream MeK)re" C ms<.-)siti)n);
byte&+ )u " ms<.:)1rray();
string s< " "";
abc()u.!engt(.:)tring());
K)r(int i " 7; i< )u.!engt( ; iCC)
s< " s< C )u&i+.:)tring();
n).4nner:ext " s<;
abc()u&7+.:)tring());
244025452.doc 147 od 274
abc(s<);
'em)rytream ms " ne/ 'em)rytream();
*<.ave(ms);
abc("-)siti)n )K ms " C ms.-)siti)n );
ms.-)siti)n " 7;
n " ms;
:ext=ea*er r< " ne/ tream=ea*er(n);
:extWriter /@ " ne/ treamWriter());
string sB " r<.=ea*:)>n*();
/@.Write!ine(sB);
abc(sB);
/@.Dlus(();
}
}
public )verri*e tream #(aintream( tream stream )
{
) " stream;
n " ne/ 'em)rytream();
return n;
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
}

SOAP response
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*A@71@1701-I77@1-=1@=D0"1abc4esult*
"1abc4esponse*

:rowser Output
A@71@1701-I77@1-=1@=D0

a.txt
MeK)re0eserialize
1Ktererialize BI7
s)ap,M)*y 1M#0
abc=esult 1M#0
'em)ry tream MeK)re7
'em)ry tream MeK)re7
'em)ry tream MeK)re8
8
JI
JI@<I<@8<7A@@I<7H<IHE8
-)siti)n )K ms B8<
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%JI@<I<@8<7A@@I<7H<IHE8<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

244025452.doc 148 od 274
The above program is a protracted one, but all the same, it is absorbing, since it
demonstrates the actions on the server-side, during encryption of a string value, which
is to be dispatched to the client. It is our humble advice to you to ensue the steps
outlined by us, while running this program. It is because, we are of the frm opinion
that it is the safest and the most steadfast pathway, steering clear of any perplexity in
understanding the concept.

The aspx fle calls a function abc from the class zzz. The return value of this function is
passed to the InnerHtml property of the bold element, which has an id ofl. At this
stage, we cannot run this aspx fle in the browser, since no class named zzz exists in the
bin folder. We will not create this zzz class; instead, we shall task the asmx fle with this
errand.

The asmx fle has a function named abc, which returns the string ABCD. In addition to
this, an attribute of 'vijay' is added to it. Since no code for 'vijay' is available at the
moment, we get an error on loading the asmx. Hence, the WSDL fle is not created.

Error
Compiler Error Message: CS-7=@: !e t'pe or namespace name Jvi2a'J could not be
.ound >are 'ou missing a using directive or an assembl' re.erence+B

So, comment out the attribute 'vijay', and reload the asmx fle.

&Web'et()*+
33&vijay+
public string abc()
{
return "1M#0";
}

Save the wsdl contents in a fle named aa.wsdl in the bin folder, and not in wwwroot
folder. Add the port number 8080 to the localhost, and then, run the batch fle named
a.bat. This will create a dll named zzz.dll, which contains the code of the class zzz.

a.bat
c* FinetpubF///r))tFbin
/s*l aa./s*l
csc 3t,library zzz.cs

Run the trace utility from the Soap Toolkit, if it is not already active, and then, in the
browser window, load the aspx fle as :

(ttp,33l)cal()st3a.aspx

The browser window will display the string "ABCD". Further, the SOAP response packet
will display the value of "ABCD", which is being sent across.

Now, instead of sending the string "ABCD" in its pristine form, we wish the server to
encrypt it, and then, send it across to the browser.

244025452.doc 149 od 274
To accomplish this, the attribute of 'vijay' is utilised. Remove the comments from the
attribute 'vijay' in the a.asmx fle, and thereafter, create the fle aaa.cs in the bin folder.
Now, compile the code in this fle, and you will obtain a dll fle.

RinetpubRwwwrootRbin*csc 1t:librar' aaa)cs

Now, reload the asmx fle to create the wsdl fle. Change the port number to 8080 and
run the batch fle.

In aaa.cs, there exist a large number of 'using' statements. Although, quite a few of
them are redundant, with no utility at all, the one positive aspect of a few extra
statements strewn around is that, their presence is innocuous. The Attribute
AttributeUsage restricts the use of the attribute 'vijay' only on methods.

Next, we create the actual attribute class 'vijay', derived from SoapExtensionAttribute.
The code in this class is not substantial, except for the read-only property of
ExtensionType, which returns the class 'mukhi'. The class 'vijay' handles the
parameters that are passed from the attribute that gets forwarded to the 'mukhi' class.

Let us now proceed and press onto the main code in the class 'mukhi', wherein, our
primary focus shall be on the ProcessMessage function. In this function too, our main
object of interest is the AfterSerialize event. This is because, the SOAP packet has
already been created. The main task that remains to be accomplished is, the encryption
of the response that is being sent over.

But prior to that, the stream object passed to the ChainStream function as a parameter
is stored in a public Stream variable named 'o'. The data that is written to
MemoryStream object o, would be utilized by SOAP every now and then. Thereafter, the
Memory Stream object 'n' is initialized and supplied as the return value of the function.

Although we have no business to transact with the BeforeDeserialize event, the
presence of this event is mandatory, since the Stream object 'n' would remain empty in
its absence. This would result in the loss of the SOAP request data.

In the BeforeDeserialize event, a TextReader object 'r' is created, using the Stream object
'o'. Moreover, a TextWriter object 'w' is also created, using the empty MemoryStream 'n'.

The entire SOAP request that reads from the TextReader 'r', is then written to the Writer.
If the Stream 'w' in not fushed, nothing could possibly be written. As the SOAP
infrastructure expects the fle pointer to be positioned at the beginning, this basic
housekeeping activity is also performed in the BeforeDeserialize event. The function abc
can be used to corroborate our actions at each stage.

The main task rests in the AfterSerialize event, where the entire SOAP response that
has been generated, is initially read. As the fle pointer is at byte 360 ( revealed by the
function abc), the pointer is repositioned at the beginning, by setting the Position
property to 0.

Here, an XmlTextReader object 'rr' is created from the Stream object 'n', and then, an
Xml Document object 'd1' is instantiated. Thereafter, the Load function in the document
244025452.doc 150 od 274
class is used, to read the SOAP response 'rr' into the XmlDocument object. The
namespace of 'soap' is added to the Namespace manager, along with its url. The object
no of type XmlNode is then made to represent the frst node body in the SOAP response.

The function abc displays the name of the node body and its content, using the
properties of Name and InnerText. Since, the abcresult node is the only node of interest
to us at this point in time, the value within FirstChild in the FirstChild member is used.
The function abc prints the values, and we stand vindicated, since our stance has been
verifed.

Next, we create an instance of the wrapper class DESCryptoServiceProvider. A wrapper
or helper class shields us from the trivia or the nitty-gritty of the class. These
repugnant details are carefully wrapped up by this wrapper class.

The InnerText property of XmlNode contains the string that we desire to encrypt. Since
it is in a string form, it has to be converted into an array of bytes. The GetBytes function
converts the string into bytes, and thereafter, stores them into an array named 'inp'.

Now, arises the requirement of a MemoryStream object, which is to be provided to the
CryptoStream class. The CryptoStream class is the class that is used to encrypt the
bytes. The CryptoStream constructor takes three parameters, which are as follows:
The frst parameter is the MemoryStream object.
The second parameter is the encryption that needs to be performed. Therefore, the
function comprises of an 8-bye key in 'k', and a 8-byte initialization in 'k1'.
The third parameter is the mode which represents either a read or a write.

Once the CryptoStream object cs is created, we use the Write function to write the array
'inp', which accommodates the contents of the tag abcResult, in the byte form. The
second parameter to the Write function is the incipient point in the array. A value of
zero indicates the beginning of the array. The last parameter is the length of the array,
which needs to be written. The FlushFinalBlock function is like the Flush function,
which actually does the writing.

Now, the MemoryStream ms1 contains the encrypted bytes. The output of the function
abc provides ample evidence of the fact that, although the Write function may be
writing, it is actually the Flush function that writes the bytes to the MemoryStream.

The ToArray function is used to convert the encrypted bytes in the Memory Stream
object, into an array of bytes. Now, this 8-byte array has to be converted into an ASCII
string. So, we use a loop construct, wherein each and every byte of the array is
concatenated to the string s1. This string, which is the encrypted version of our SOAP
response, is then written to disk.

The InnerText property of the XmlNode is also initialized to this string, resulting in the
initialization of the XML document.

The XML document is then saved in the MemoryStream object named 'ms'. This new
MemoryStream contains the same XML fle that the SOAP infrastructure had created.
However, there is a minor variation here, i.e. the contents of abcResult tag are
encrypted.
244025452.doc 151 od 274

The File pointer in the new MemoryStream, which is at Position 381 due to the saving,
is now repositioned at the beginning of the fle. Then, the MemoryStream 'n' is equated
to 'ms', and a new TextReader object is created.

The TextWriter object uses the stream 'o', since it is this stream that should contain the
fnal SOAP payload. The stream 'o' in this event is used for writing the output that is to
be sent across. The stream 'n' is used to read the SOAP packet that is generated.

The string s3 is used to store the SOAP response, which is read from the reader. Then
subsequently, it is written out to the Writer, or to the Stream 'o'.

Yet another way of achieving this is, to read the bytes from the memory stream, convert
them into a string, and then, to write them with the help of the w2 object. The string s3
substantiates the fact that, the SOAP response that is sent across, comprises of
contents that are encrypted.

a.aspx
<.:'!%
<.>10%
<script language""c$" runat"server%
public v)i* -ageT!)a*()
{
zzz / " ne/ zzz();
l.4nner.tml " /.abc("(i");
}
<3script%
<3.>10%
<M;0S%
<b i*""l" runat""server"3%
<3.:'!%

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay(>nc">'.=esp)nse60ec"0'.=ePuest)+
public string abc( string a)
{
return "vijay " C a;
}
}

zzz.cs
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame"".ell)W)rl*)ap"6
9amespace""(ttp,33tempuri.)rg3")+
public class zzz, ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public zzz()
{
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
244025452.doc 152 od 274
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
&vijay(>nc">'.=ePuest60ec"0'.=esp)nse)+
public string abc(string a)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+{a});
return ((string)(results&7+));
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.ecurity.#rypt)grap(y;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
>' em)*e" >'.9)ne;
0' *m)*e" 0'.9)ne;
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get
{
return 7;
}
set
{
}
}
public >' >nc
{
get
{
return em)*e;
}
set
{
em)*e" value;
}
}
public 0' 0ec
{
get
{
return *m)*e;
}
set
{
*m)*e" value;
}
}
}
244025452.doc 153 od 274
public enum 0'
{
9)ne6
=esp)nse6
=ePuest
}
public enum >'
{
9)ne6
=esp)nse6
=ePuest
}
public class mu5(i , )ap>xtensi)n
{
tream );
tream n;
0' *m)*e;
>' em)*e;
Myte&+ 5 " {<6 @6 B6 H6 E6 I6 A6 8};
Myte&+ 5< " {<76<< 6 <@6 <B6 <H6 <E6 <I6 <A};
public mu5(i()
{
abc("#)nstruct)r");
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
abc("?et4nitializer " C m.:)tring());
return a;
}
public )verri*e )bject ?et4nitializer(:ype t)
{
abc("?et4nitializer <");
return type)K(mu5(i);
}
public )verri*e v)i* 4nitialize()bject i)
{
vijay a " (vijay) i;
*m)*e " a.0ec;
em)*e " a.>nc;
abc("4nitialize " C i.:)tring() C " " C a.0ec.:)tring() C " " C a.>nc.:)tring());
return;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
abc("1Ktererialize " C em)*e.:)tring() C " " C n.-)siti)n );
n.-)siti)n " 7;
iK ((em)*e "" >'.=ePuest) YY (em)*e "" >'.=esp)nse))
{
abc("1Ktererialize iK");
n.-)siti)n " 7;
Oml:ext=ea*er rr " ne/ Oml:ext=ea*er(n);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(rr);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
abc(n).4nner:ext);
byte&+ inp " >nc)*ing.2:D8.?etMytes(n).4nner:ext);
'em)rytream ms< " ne/ 'em)rytream();
244025452.doc 154 od 274
#rypt)tream cs " ne/ #rypt)tream(ms<6 *e.#reate>ncrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
byte&+ )u " ms<.:)1rray();
tringMuil*er s " ne/ tringMuil*er();
K)r(int i"7; i<)u.!engt(; iCC)
{
iK(i""()u.!engt(G<))
s.1ppen*()u&i+);
else
s.1ppen*()u&i+ C " ");
}
n).4nner:ext " s.:)tring();
'em)rytream ms " ne/ 'em)rytream();
*<.ave(ms);
ms.-)siti)n " 7;
n " ms;
}
:ext=ea*er r " ne/ tream=ea*er(n);
:extWriter / " ne/ treamWriter());
string sE " r.=ea*:)>n*();
abc(sE);
/.Write!ine(sE);
/.Dlus(();
}
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eserialize " C *m)*e.:)tring());
'em)rytream *s " ne/ 'em)rytream();
iK ((*m)*e "" 0'.=ePuest) YY (*m)*e "" 0'.=esp)nse))
{
abc("MeK)re0eserialize iK");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(*s);
string sI " r.=ea*:)>n*();
/.Write!ine(sI);
abc(sI);
/.Dlus(();
abc("-)siti)n )K *s " C *s.-)siti)n);
*s.-)siti)n " 7;
Oml:ext=ea*er r7 " ne/ Oml:ext=ea*er(*s);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(r7);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
string sB " n).4nner:ext;
abc(sB);
c(ar&+ c " {U U};
string&+ ss " sB.plit(c);
byte&+ b " ne/ byte&ss.!engt(+;
abc(ss.!engt(.:)tring());
K)r(int i"7; i<b.!engt(; iCC)
{
b&i+ " Myte.-arse(ss&i+);
}
byte&+ inp " b;
'em)rytream ms< " ne/ 'em)rytream();
#rypt)tream cs " ne/ #rypt)tream(ms<6*e.#reate0ecrypt)r( 56 5< )6
#rypt)tream')*e.Write);
244025452.doc 155 od 274
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
byte&+ )u " ms<.:)1rray();
string s< " >nc)*ing.2:D8.?ettring()u);
n).4nner:ext " s<;
abc(s<);
'em)rytream ms " ne/ 'em)rytream();
iK ( *m)*e "" 0'.=ePuest)
*<.ave("c,FFz.txt");
else
*<.ave("c,FFy.txt");
*<.ave(ms);
ms.-)siti)n " 7;
:ext=ea*er r< " ne/ tream=ea*er(ms);
:extWriter /< " ne/ treamWriter(n);
/<.Write!ine(r<.=ea*:)>n*());
/<.Dlus(();
}
else
{
abc("MeK)re0eserialize else");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(n);
/.Write!ine(r.=ea*:)>n*());
/.Dlus(();
}
n.-)siti)n " 7;
}
}
public )verri*e tream #(aintream( tream stream )
{
abc("#(aintream");
) " stream;
n " ne/ 'em)rytream();
return n;
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
}

a.txt
#)nstruct)r
?et4nitializer ystem.tring abc(ystem.tring)
#)nstruct)r
4nitialize vijay =esp)nse =ePuest
#(aintream
1Ktererialize =ePuest B@I
1Ktererialize iK
(i
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc xmlns""(ttp,33tempuri.)rg3"%
<a%@<H <BH A@ <B< <7I H< 8@ EE<3a%
<3abc%
244025452.doc 156 od 274
<3s)ap,M)*y%
<3s)ap,>nvel)pe%
#)nstruct)r
?et4nitializer ystem.tring abc(ystem.tring)
#)nstruct)r
4nitialize vijay =ePuest =esp)nse
#(aintream
MeK)re0eserialize =ePuest
MeK)re0eserialize iK
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc xmlns""(ttp,33tempuri.)rg3"%
<a%@<H <BH A@ <B< <7I H< 8@ EE<3a%
<3abc%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%
-)siti)n )K *s BEE
@<H <BH A@ <B< <7I H< 8@ EE
8
(i
#(aintream
1Ktererialize =esp)nse BIH
1Ktererialize iK
vijay (i
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%@@E J@ E8 <EJ I@ EE <<< @<E @@E @EE JA @7J @B@ <B7 B< JJ<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%
#(aintream
MeK)re0eserialize =esp)nse
MeK)re0eserialize iK
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%@@E J@ E8 <EJ I@ EE <<< @<E @@E @EE JA @7J @B@ <B7 B< JJ<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

-)siti)n )K *s H<I
@@E J@ E8 <EJ I@ EE <<< @<E @@E @EE JA @7J @B@ <B7 B< JJ
<I
vijay (i

z.txt
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc xmlns""(ttp,33tempuri.)rg3"%
244025452.doc 157 od 274
<a%(i<3a%
<3abc%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

y.txt
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,M)*y%
<abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%vijay (i<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

Output in :rowser
Qi2a' !i

a)bat
del V)dll
csc 1t:librar' aaa)cs
csc 1t:librar' 333)cs 1r:aaa)dll

This program sheds light on the concepts of encryption and decryption at their best.

The client program sends a SOAP request, which holds the encrypted value of "hi", to
the server. The server receives the encrypted parameter, decrypts it and transmits it
further, to the SOAP system. The function in the extension dll receives the parameter as
'hi', and reciprocates by sending the return value of 'vijay hi', in an encrypted form.
Then, the SOAP framework creates a SOAP packet, containing the return value in an
encrypted form, and then, sends it to the client. The client receives this encrypted
value, and decrypts it prior to faunting it in the browser window. This roller coaster
ride is an endeavor to unravel the mystery behind all the actions transpired above.

We set out by grappling with the aspx fle, as the frst step. The function abc in this fle
accepts a string parameter and then, returns a string. Subsequently, the browser
displays this string. The SOAP request and response packets that fow to and fro,
neither display the input string as "hi", nor do they disclose the response value of "vijay
hi", which is received from the server. All that they display, is a series of numbers,
foating from one end to the other.

SOAP re5uest
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*71= 16= I7 161 1-@ =1 07 DD"1a*
"1abc*
"1soap::od'*

SOAP response
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*77D A7 D0 1DA @7 DD 111 71D 77D 7DD AI 7-A 767 16- 61
AA"1abc4esult*
"1abc4esponse*
"1soap::od'*
244025452.doc 158 od 274

The asmx fle has a function named abc in the class zzz. This function accepts one
string parameter named 'a', and it returns a string that contains the word 'vijay',
concatenated to this string parameter.

It also has an attribute named 'vijay', which in turn, owns two parameters named Enc
and Dec, which are short forms for the terms Encrypt and Decrypt, respectively. Thus,
the class attribute 'vijay' now possesses two properties. The values of these properties
determine what needs to be done. EM and DM are enums, both of which specify that
the request or response is to be either encrypted or decrypted. The third value in the
enum is 'none'.

In our case, the values specifed here are indicative of the fact that, the Response is to
be encrypted, and the Request is to be decrypted.

The asmx fle is located on the server. Thus, it represents the processing that is to be
done at the server end. It is the bounden duty of the server to decrypt the data that has
been encrypted by the client, and to encrypt the Response data, which shall
subsequently be decrypted by the client.

Until now, the asmx fle was being used to create the client program, in that, it was
utilized for running the wsdl utility on the wsdl fle, and for creating the .cs fle. But for
the moment, we shall write the client program manually, since we have to place the
attribute named 'vijay'.

Candidly speaking, we employed the webserver for creation of the client program, and
subsequently, we eliminated the code that was unnecessary, and thus, redundant.
Thereafter, the attribute named 'vijay' made its debut.

Akin to the server, this attribute also accepts two parameters, viz. Enc=EM.Request,
Dec=DM.Response. These values signify that the Request is to be encrypted and the
Response is to be decrypted. The code remains almost identical, except for the
introduction of the attribute named 'vijay'. We have provided you with the bird's eye
view, before diving any deeper into comprehending the code of the attribute named
'vijay'.

When the URL with the aspx fle is written in the browser, a Get or Post is dispatched to
the Web Server. Let us designate the name 'A' for the Web Server. Subsequent to the fle
being positioned on the web server 'A', the aspx program gets converted into C# code,
and the function abc is called from the program named zzz.dll. Thereafter, this function
sends a SOAP packet, containing data encrypted by the SOAP extension dll, to another
server, which is named as 'B' merely on the whim. This server 'B' actually contains the
code of the function abc.

On receiving the SOAP payload, the server B executes the asmx fle. The SOAP
extension dll decrypts the data and calls the function abc, while furnishing it with the
original data value of 'hi'. The return value of the function i.e. 'vijay hi', is then
encrypted, and dispatched back to the client dll named zzz.dll, which is located on the
Web Server A. It is then decrypted by the code in the 'vijay' attribute extension dll, and
244025452.doc 159 od 274
the string 'vijay hi' is then returned back. Finally, the Web Server A creates an html fle
with the return value, and transports it to the browser. At times, this concept can be
truly bafing!

The fle aaa.cs is the extension dll, which contains the encryption and decryption code
for both, the client and the server. Thus, it has to handle a situation wherein, only the
Serialize events are triggered-of to encrypt the request from the client, and both the
Serialize and Deserialize events are triggered-of for the response packets from the
server.

The extension dll contains two enum classes called DM and EM, which symbolise
Decryption and Encryption, respectively. These enum classes identify the values to be
encrypted or decrypted, such as- the request, the response, or no value at all!
So, when we specify the enum value of EM.Response, the interpretation rendered by the
program is that, the Response has to be encrypted.

The class 'vijay' has two properties named Enc and Dec. Only those programs that
employ the attribute of 'vijay', are entitled to the use of Enc and Dec properties; and It is
these properties that 'set' or 'get' the value that is stored in the variables 'emode' and
'dmode'. In the present context, these variables store the state of the properties Dec and
Enc.

Next, the GetInitializer function returns the second parameter that is cached. Since you
have already been enlightened about the motive behind this call, we choose to ignore it
at this stage. The system calls this function twice, since there are two instances of the
attribute 'vijay':
First, for the client in zzz.cs
And then, for the server in a.asmx.

The prototypes of both the functions have to be identical. Firstly, the constructor is
called, followed by the GetInitializer function. Thereafter, the constructor is called yet
again; but this time, it is for the client data. The same process is repeated for the server
as well.

The Initialize function gets called each time. Here, the parameter i represents the 'vijay'
object. The value of the a.Dec property is Response, whereas, the value of the a.Enc
property is Request. The values unearthed by the function abc, vindicate our claim. It is
because, in the client zzz.cs, the parameters of the attribute 'vijay' are specifed as
Enc=EM.Request and Dec=DM.Response.

Thus, the Initialize function is called for the packet received from the client. In this
function, the values of the properties Dec and Enc, are saved in the variables dmode
and emode, respectively. This concludes the process of transferring data from the
attribute 'vijay', pertaining to the client.

In the ProcessMessage function, it is the AfterSerialize event which is called frst, since
the data originates from the client. The ChainStream function sets up the Streams,
prior to this event being fred. The Position parameter of the Stream object n is set to 0,
244025452.doc 160 od 274
because when the packet is received, the stream pointer is at the end of the Stream, at
position 326. This number corresponds to the size of the SOAP payload.

Now, emode contains the value of Request, since the packet has to be encrypted. Just to
jog your memory a little, this is so because, in the parameter of the 'vijay' attribute in
the client program named zzz.cs, the value of ENC is set to EM.Request.

Now, in order to populate the byte array, the code that was specifed earlier, has to be
entered. In order to pay our respects to the original programmer who wrote this class,
the StringBuilder class is used to concatenate the bytes from the byte array. Here, we
iterate through the byte array and utilise the Append function to add a byte to the
StringBuilder class named 's'. We have added a space between the encrypted values, in
order to brandish the output in a more aesthetic manner. These spaces will have to be
stripped of, prior to decryption of the numbers.

The InnerText is then initialized to the new output data, and the memory stream is
created. Once the loop terminates, the contents of the stream 'n' are written to the
Stream 'o'. The fle a.txt displays the SOAP payload that is being sent over. Presently,
only the frst parameter will be encrypted. The code catering to encryption of multiple
parameters is not entered.

Once the SOAP packet reaches the server, the decryption routine takes over. This is
because, in the asmx fle, the parameter supplied to the attribute 'vijay' is
Dec=DM.Request. The ChainStream function is called prior to the fring of the
BeforeDeSerialize event.

In this event, an empty MemoryStream object is created initially. Then, the value of the
dmode variable is ascertained, to determine whether it is Request or Response.

Since the value contained in dmode is 'Request', we enter the 'if' statement, which will
decrypt the SOAP payload sent from the client to the server. The encrypted SOAP
request payload from the client, which is saved in the Stream 'o', is then transferred to
the memory stream 'ds'. Since the Position property in the memory stream ds has
changed to 355, it is reset to 0.

Now, we require an XmlDocument to accommodate the encrypted data in the
MemoryStream 'ds'. Therefore, we create an XmlTextReader object named 'r0', and an
XmlDocument object named 'd1'. The Load function is pressed into service to copy the
XML data from the memory stream 'ds', to the XmlDocument 'd1'. After having provided
for the other details, we access the frst grandchild from the body. The XmlNode named
'no' represents this child node.

Thereafter, a wrapper object of class DESCryptoServiceProvider, is instantiated.
Further, the encrypted text, which is contained in the node 'no', is assigned to a string
s3, using the InnerText property. Since the text contains spaces, the Split function of
the string is provided with the delimiter of the 'space' character, and the output is
stored in a string array named 'ss'. There are a total of 7 spaces in the string s3.
Therefore, the size of the string array ss is 8. Once this is achieved, we create a byte
array named b, of length 8, and subsequently, iterate through a 'for' loop.
244025452.doc 161 od 274

The static function Parse in the Byte class, converts the string into a byte, and stores it
in a diferent member of the array. The member is decided on the basis of the value of
the variable i. The loop continues till all the string bytes have been transferred into the
array. We could have used the Byte array named 'b' for this purpose, but we decided to
create a new one named 'imp'. Ask us not why!

The next task is to decrypt this data. In order to accomplish this, an empty
MemoryStream object named 'ms1' is created and assigned to the CryptoStream
constructor, while the object cs is being created. The second parameter is the
CreateDecryptor function, with the same key and IV. This leads to the creation of an
object, which will decrypt the byte array and place the contents in the MemoryStream
ms1. The last parameter is the enum value of 'Write'.

Finally, the Write function in the stream is called, with the byte arrays that contain the
encrypted values. The end result is that, the memory stream ms1 shall now contain the
decrypted value. But hold your horses! This is attainable only when the stream is
fushed. For this, the FlushFinalBlock function is put to use. The decrypted text from
the MemoryStream ms1 is then acquired, using the ToArray function, which returns a
byte array containing the word 'hi'. The bytes are converted into a string, using the
GetString function. Ultimately, the value of 'hi' is displayed.

The task still remains unfnished, since an XmlDocument has yet to be created, with
this new value. The InnerText of the XmlNode is set to 'hi', and a MemoryStream object
'ms' is created. Then, using the Save function, the entire XmlDocument is written to
this object.

Finally, we employ the freshly created 'ms' MemoryStream as the Reader, and the
MemoryStream 'n' as the Writer. All that is written to this stream, shall be passed on to
the asmx program. The 'else' block is never called, since it is used only when the dmode
variable has a value of None 0 no decryption. Thus, you would realize that both
encryption and decryption, adhere to analogous rules.

The server calls the asmx fle, with the value of the parameter 'a' as 'hi'. The asmx fle
returns 'vijay hi', which is used by the server to create a SOAP payload. The SOAP
payload reaches the extension dll, where the AfterSerialize event gets called, but with
the value of emode as Response. The SOAP payload is now encrypted and sent across.

On receiving the encrypted SOAP response, the client uses the extension dll and
triggers of the BeforeDeSerialize event. The code contained in this block, converts the
encrypted bytes to the value 'vijay hi', since the value of dmode is DM.Response. The
fles z.txt and y.txt, exhibit the actual SOAP payload that has been received by the
server and the client, subsequent to the decryption. The above illustration is indeed an
enormous mental workout, but is worth comprehending.

Once you have ruminated and digested the above program, incorporate the following
two modifcations in the aaa.cs program:
Replace the two instances of the DESCryptoServiceProvider class, with the
RC2CryptoServiceProvider class.
244025452.doc 162 od 274

Change
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
To
=#@#rypt)ervice-r)vi*er *e " ne/ =#@#rypt)ervice-r)vi*er ();

The residual code remains unchanged. The eventual outcome is that, the algorithm
adopted for the encryption of data is RC2, and not the DES. This is suggestive of the
fact that, shifting from one algorithm to another, is indeed efortless.

SOAP re5uest
"soap::od'*
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*71= =- 7-A 100 A@ 0 AI =7"1a*
"1abc*
"1soap::od'*

SOAP response
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*1@= @A 71A 7 6 0 D0 =6 1ID 1=I D6 @= 117 1I@ 1D 101"1abc4esult*
"1abc4esponse*
"1soap::od'*

The SOAP payload here is diferent, since the encrypted data is at variance with the
earlier data, however, this does not seem to hassle the program at all. Now, let us make
rapid strides to the very last program of the chapter.

a.aspx
<.:'!%
<.>10%
<script language""c$" runat"server%
public v)i* -ageT!)a*()
{
zzz / " ne/ zzz("=#@");
l.4nner.tml " /.abc("(i");
zzz /< " ne/ zzz("0>");
l<.4nner.tml " /<.abc("Mye");
}
<3script%
<3.>10%
<M;0S%
<b i*""l" runat""server"3%
<p%
<b i*""l<" runat""server"3%
<3.:'!%

zzz.cs
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame"".ell)W)rl*)ap"6
9amespace""(ttp,33tempuri.)rg3")+
public class zzz, ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public yyy b;
public zzz(string s)
244025452.doc 163 od 274
{
b " ne/ yyy();
b.type " s;
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
&vijay(>nc">'.=ePuest60ec"0'.=esp)nse)+
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("b")+
public string abc(string a)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+{a});
return ((string)(results&7+));
}
}
public class yyy , )ap.ea*er
{
public string type;
}


a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class zzz
{
&Web'et()*+
&vijay(>nc">'.=esp)nse60ec"0'.=ePuest)+
public string abc( string a)
{
return "vijay " C a;
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.ecurity.#rypt)grap(y;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
>' em)*e" >'.9)ne;
0' *m)*e" 0'.9)ne;
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get
{
return 7;
}
set
{
}
244025452.doc 164 od 274
}
public >' >nc
{
get
{
return em)*e;
}
set
{
em)*e" value;
}
}
public 0' 0ec
{
get
{
return *m)*e;
}
set
{
*m)*e" value;
}
}
}
public enum 0'
{
9)ne6
=esp)nse6
=ePuest
}
public enum >'
{
9)ne6
=esp)nse6
=ePuest
}
public class mu5(i , )ap>xtensi)n
{
tream );
tream n;
0' *m)*e;
>' em)*e;
static string ctype " "=#@";
Myte&+ 5 " {<6 @6 B6 H6 E6 I6 A6 8};
Myte&+ 5< " {<76<< 6 <@6 <B6 <H6 <E6 <I6 <A};
public mu5(i()
{
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
return a;
}
public )verri*e )bject ?et4nitializer(:ype t)
{
return type)K(mu5(i);
}
public )verri*e v)i* 4nitialize()bject i)
{
vijay a " (vijay) i;
*m)*e " a.0ec;
em)*e " a.>nc;
abc("4nitialize " C i.:)tring() C " " C a.0ec.:)tring() C " " C a.>nc.:)tring());
return;
244025452.doc 165 od 274
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
abc("1Ktererialize " C em)*e.:)tring() C " " C n.-)siti)n );
n.-)siti)n " 7;
iK ((em)*e "" >'.=ePuest) YY (em)*e "" >'.=esp)nse))
{
abc("1Ktererialize iK");
n.-)siti)n " 7;
Oml:ext=ea*er rr " ne/ Oml:ext=ea*er(n);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(rr);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
byte&+ inp " >nc)*ing.2:D8.?etMytes(n).4nner:ext);
'em)rytream ms< " ne/ 'em)rytream();
abc("GGGGGGGGGGGGGGGGGGG" C ctype);
byte&+ )u " null;
iK (em)*e "" >'.=ePuest)
{
Oml9)*e n)< " *<.electingle9)*e("33s)ap,.ea*er"6 nm);
n)< " n)<.Dirst#(il*.Dirst#(il*;
abc("$$$$$$$$$$$$$$$$" C n)<.4nner:ext);
ctype " n)<.4nner:ext;
}
iK ( ctype "" "0>")
{
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
#rypt)tream cs " ne/ #rypt)tream(ms<6 *e.#reate>ncrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
)u " ms<.:)1rray();
}
else
{
=#@#rypt)ervice-r)vi*er *e " ne/ =#@#rypt)ervice-r)vi*er();
#rypt)tream cs " ne/ #rypt)tream(ms<6 *e.#reate>ncrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
)u " ms<.:)1rray();
}
tringMuil*er s " ne/ tringMuil*er();
K)r(int i"7; i<)u.!engt(; iCC)
{
iK(i""()u.!engt(G<))
s.1ppen*()u&i+);
else
s.1ppen*()u&i+ C " ");
}
n).4nner:ext " s.:)tring();
'em)rytream ms " ne/ 'em)rytream();
*<.ave(ms);
ms.-)siti)n " 7;
n " ms;
}
:ext=ea*er r " ne/ tream=ea*er(n);
:extWriter / " ne/ treamWriter());
244025452.doc 166 od 274
string sE " r.=ea*:)>n*();
/.Write!ine(sE);
/.Dlus(();
}
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eserialize " C *m)*e.:)tring());
'em)rytream *s " ne/ 'em)rytream();
iK ((*m)*e "" 0'.=ePuest) YY (*m)*e "" 0'.=esp)nse))
{
abc("MeK)re0eserialize iK");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(*s);
string sI " r.=ea*:)>n*();
/.Write!ine(sI);
/.Dlus(();
*s.-)siti)n " 7;
Oml:ext=ea*er r7 " ne/ Oml:ext=ea*er(*s);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(r7);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
string sB " n).4nner:ext;
c(ar&+ c " {U U};
string&+ ss " sB.plit(c);
byte&+ b " ne/ byte&ss.!engt(+;
K)r(int i"7; i<b.!engt(; iCC)
{
b&i+ " Myte.-arse(ss&i+);
}
byte&+ inp " b;
'em)rytream ms< " ne/ 'em)rytream();
byte&+ )u " null;
abc(ctype);
iK ( ctype "" "0>")
{
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
#rypt)tream cs " ne/ #rypt)tream(ms<6*e.#reate0ecrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
)u " ms<.:)1rray();
}
else
{
=#@#rypt)ervice-r)vi*er *e " ne/ =#@#rypt)ervice-r)vi*er();
#rypt)tream cs " ne/ #rypt)tream(ms<6*e.#reate0ecrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
)u " ms<.:)1rray();
}
string s< " >nc)*ing.2:D8.?ettring()u);
n).4nner:ext " s<;
'em)rytream ms " ne/ 'em)rytream();
iK ( *m)*e "" 0'.=ePuest)
*<.ave("c,FFz.txt");
else
*<.ave("c,FFy.txt");
*<.ave(ms);
ms.-)siti)n " 7;
244025452.doc 167 od 274
:ext=ea*er r< " ne/ tream=ea*er(ms);
:extWriter /< " ne/ treamWriter(n);
/<.Write!ine(r<.=ea*:)>n*());
/<.Dlus(();
}
else
{
abc("MeK)re0eserialize else");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(n);
/.Write!ine(r.=ea*:)>n*());
/.Dlus(();
}
n.-)siti)n " 7;
}
}
public )verri*e tream #(aintream( tream stream )
{
33abc("#(aintream");
) " stream;
n " ne/ 'em)rytream();
return n;
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
}

Output
vi2a' !i
vi2a' :'e
a)t,t
Initiali3e vi2a' 4esponse 4e5uest
A.terSeriali3e 4e5uest =6@
A.terSeriali3e i.
///////////////////4C7
WWWWWWWWWWWWWWWW4C7
Initiali3e vi2a' 4e5uest 4esponse
:e.oreEeseriali3e 4e5uest
:e.oreEeseriali3e i.
4C7
A.terSeriali3e 4esponse 6@=
A.terSeriali3e i.
///////////////////4C7
:e.oreEeseriali3e 4esponse
:e.oreEeseriali3e i.
4C7
Initiali3e vi2a' 4esponse 4e5uest
A.terSeriali3e 4e5uest =6I
A.terSeriali3e i.
///////////////////4C7
WWWWWWWWWWWWWWWWEES
Initiali3e vi2a' 4e5uest 4esponse
:e.oreEeseriali3e 4e5uest
:e.oreEeseriali3e i.
EES
A.terSeriali3e 4esponse 6@D
A.terSeriali3e i.
244025452.doc 168 od 274
///////////////////EES
:e.oreEeseriali3e 4esponse
:e.oreEeseriali3e i.
EES

a.txt
4nitialize vijay =esp)nse =ePuest
1Ktererialize =ePuest HBI
1Ktererialize iK
GGGGGGGGGGGGGGGGGGG=#@
$$$$$$$$$$$$$$$$=#@
4nitialize vijay =ePuest =esp)nse
MeK)re0eserialize =ePuest
MeK)re0eserialize iK
=#@
1Ktererialize =esp)nse BIH
1Ktererialize iK
GGGGGGGGGGGGGGGGGGG=#@
MeK)re0eserialize =esp)nse
MeK)re0eserialize iK
=#@
4nitialize vijay =esp)nse =ePuest
1Ktererialize =ePuest HBA
1Ktererialize iK
GGGGGGGGGGGGGGGGGGG=#@
$$$$$$$$$$$$$$$$0>
4nitialize vijay =ePuest =esp)nse
MeK)re0eserialize =ePuest
MeK)re0eserialize iK
0>
1Ktererialize =esp)nse BIE
1Ktererialize iK
GGGGGGGGGGGGGGGGGGG0>
MeK)re0eserialize =esp)nse
MeK)re0eserialize iK
0>

a.bat
*el c,Fa.txt
*el R.*ll
csc 3t,library aaa.cs
csc 3t,library zzz.cs 3r,aaa.*ll

;1- rePuest<
<s)ap,.ea*er%
G <yyy xmlns""(ttp,33tempuri.)rg3"%
<type%=#@<3type%
<3yyy%
<3s)ap,.ea*er%
G <s)ap,M)*y%
G <abc xmlns""(ttp,33tempuri.)rg3"%
<a%@<H H7 @7J <88 JI 8 JA H@<3a%
<3abc%
<3s)ap,M)*y%

;1- resp)nse<
<s)ap,M)*y%
G <abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%<IH IJ @<J @ B 8 E8 HB <AE <HA EB IH <<@ <AI <E <8<<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%

;1- rePuest@
244025452.doc 169 od 274
<s)ap,.ea*er%
G <yyy xmlns""(ttp,33tempuri.)rg3"%
<type%0><3type%
<3yyy%
<3s)ap,.ea*er%
G <s)ap,M)*y%
G <abc xmlns""(ttp,33tempuri.)rg3"%
<a%<AB <B< <@7 J< A@ <8E <8E @7I<3a%
<3abc%
<3s)ap,M)*y%


;1- resp)nse@
<s)ap,M)*y%
G <abc=esp)nse xmlns""(ttp,33tempuri.)rg3"%
<abc=esult%<7I I@ <7E J7 <@H <B< IB <@8 I @B7 B@ <B7 8E B <HJ <<J<3abc=esult%
<3abc=esp)nse%
<3s)ap,M)*y%

In the aspx fle, two objects named w and w1, of type zzz, are created. While the object
is being created, the constructor is furnished with the specifc encryption algorithm
type, which the object supports. The object w utilizes the RC2 encryption algorithm,
while the object w1 employs the DES algorithm.

Resultantly, the SOAP payload displays bytes encrypted with the RC2 algorithm in the
frst case, and with the DES algorithm in the second case. Thereafter, the function abc
is called, using both the objects, but with a distinct parameter value.

While creating the objects, the a.aspx fle calls code from the zzz.cs fle. In the earlier
program, we had made use of the attributes to supply values, whereas in the present
case, this task has been undertaken by the constructor.

A new instance of the class yyy is created in the zzz object. The class yyy, which is
derived from SoapHeader, has only one member called 'type'. This member, i.e. 'type' is
initialized to the encryption method, which is supported by the object in the zzz
constructor. This information is then sent across, in the form of a header value.

In one of the earlier chapters, we were enlightened about the fact that the headers can
be sent across, using the attribute of SoapHeaderAttribute. We implement the same
attribute here, and assign it the variable 'b', to stores the contents of the attribute.

The SOAP Request displays two messages, wherein, the frst request header has the
element type as RC2, and the second request header has the element type as DES.
Once the header is created and sent across, the AfterSerialize event is called in the dll,
which pertains to the 'vijay' attribute. Here, the value of emode is set to Request.
In the dll, contingent to the value displayed in the header, a specifc encryption method
is used. The ctype variable is declared static in nature, and assigned a value of "RC2" in
the frst round. This is for the reason that, a static variable is available, as long as the
application is alive. Therefore, even though there may be numerous instances of the
'mukhi' class in memory, there will be only one copy of the ctype variable. Had the
variable been an instance variable, it would have lost its previous value, and would have
attained a fresh value every time.

244025452.doc 170 od 274
Once the header packet arrives at the server, the BeforeDeserialize event is triggered-of
in the extension dll. This is because, the asmx fle contains the attribute of 'vijay'. The
process explicated in the previous program, is relevant in this context too, i.e. the data
is decrypted before the function abc is called, and the return value is encrypted
thereafter. This encrypted packet is then sent back to the client, to be decrypted.

It is pertinent to note that there exists no header packet, to notify the client as to which
algorithm is to be used for decrypting the packet. This could cause complications
during the transfer of data, using headers. The answer to this quagmire is, to use
headers both ways. However, we have implemented a distinct method to deal with this
exigency, i.e. we ascertain the value contained in the ctype variable. The details are
given below.

When the packet arrives from the client, the value contained in the emode variable is
Request. Thus, the 'if' statement becomes true. To access the headers tag in the SOAP
packet, we utilize the SelectSingleNode function from the document class. The node
named 'no1' now represents this header node.

Thereafter, using the property FirstChild twice, the node 'no1' is initialized to represent
the content, i.e. InnerText, of the type element. The value that is retrieved is RC2. To
substantiate our claim, we have written it to the fle a.txt, on disk. The ctype variable is
initialized to the value contained in the header. Thereafter, the algorithm of RC2 is
implemented, for encrypting the data.


Once the data has been encrypted, the packet is sent across. When the server receives
the packet, the BeforeDeserialize event in the dll gets triggered-of. Herein lies the
beauty of the static variable. The constructor could be called a million times, but the
static variable retains its value as RC2. We could have easily examined the header again
(as was done in the client), however, we prefer to use the value of the ctype variable,
instead. The packet data is decrypted, using the valid algorithm.

Next, the AfterSerialize event is called from the server side. Since the value in the ctype
variable has not been altered, there is no requirement for deciphering the value
enclosed in the variable. Bear in mind that no header is present at the time, when the
packet is being sent over. When the packet reaches the client, the BeforeDeserialize
event is triggered. Since no header information has been sent from the server to client,
there is no option, but to refer to the value in the ctype variable.

When the function abc is called from the second instance of the zzz object, the header
element at the client end contains the value of DES. This alters the ctype variable to
DES. Thus, the encryption algorithm that is employed here is DES. The whole process
is then iterated with the algorithm of DES.

Thus, the header feld is used only once in the client, basically to determine the value of
the type feld. We could even have used the headers in the server, and then, tasked the
server for sending the header to the client. There are many ways to skin a cat, but we
have the fexibility to choose what suits us the best.

244025452.doc 171 od 274
Compression and Decompression

Very often, we encounter certain characters that make repeated appearances in a data
sequence. This recurrence leads to dilation in the size of the data packet, thereby,
adding to the web trafc. A thought that crosses the mind at this point is, why not
pluck out this character and insert some indication instead, which signals that the
specifc character has been fltered out?


In a sense, this is the basis for the concept of compression of a data packet and its
subsequent transmission. The receiver, who would be clued-up about this procedure,
could then decompress the data, prior to processing it.

One variant of this approach is, the (Small Messaging System) SMS language, used in
mobile communication. Although it doesn't work exactly on the guidelines specifed
above, its utilization has gained popular acceptance by users of mobile phones. In SMS,
specifc characters are simply fltered out from the message.

Let us consider the case wherein we wish to flter out the 'space' character from the
SOAP Payload. We have specifcally chosen the 'space' character, since it is the most
commonly recurring character in the entire packet. On eradicating the character from
the parameters of the payload, there is a substantial decrease in the size of the payload,
thus introducing the concept of compression.

At the other end, these spaces are simply inserted back into the positions from where
they were removed earlier. To implement this, information relating to the number of
spaces that have been removed, and their original positions, has to be retained, to
facilitate subsequent restoration of the original data.

Here, we present to you a diminutive .cs program. It has nothing to do with SOAP or
client server. It merely contains code that strips the spaces from the text, and
subsequently, reinserts them into their original positions. You can work in any sub-
directory, but we have chosen the ddd subdirectory.

a.cs
using ystem.:ext;
public class zzz
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string s " "1 M #";
byte &+ b6c;
byte &+ *;
c " >nc)*ing.1#44.?etMytes(s);
K)r ( int 55"7; 55 < c.!engt( ; 55CC)
ystem.#)ns)le.Write(c&55+.:)tring() C " ");
ystem.#)ns)le.Write!ine();
b " a.c)mpress(c);
K)r ( int 55"7; 55 < b.!engt( ; 55CC)
ystem.#)ns)le.Write(b&55+.:)tring() C " ");
ystem.#)ns)le.Write!ine();
* " a.*ec)mpress(b);
K)r ( int 55"7; 55 < *.!engt( ; 55CC)
244025452.doc 172 od 274
ystem.#)ns)le.Write(*&55+.:)tring() C " ");
ystem.#)ns)le.Write!ine();
ystem.#)ns)le.Write!ine(>nc)*ing.1#44.?ettring(*));
}
public byte &+ c)mpress(byte &+ *)
{
byte &+ t " ne/ byte&*.!engt(+;
int i6j"7;
K)r ( i " 7; i < *.!engt( ; iCC)
{
iK ( *&i+ "" B@)
{
t&j+ " *&i C <+ ;
t&j+ C" <@8;
iCC;
}
else
t&j+ " *&i+;
jCC;
}
byte &+ t< " ne/ byte&j+;
K)r ( int 5 " 7 ; 5 < j ; 5CC)
t<&5+ " t&5+;
return t<;
}
public byte &+ *ec)mpress(byte &+ *)
{
byte &+ t " ne/ byte&*.!engt(R@+;
int i6j"7;
K)r ( i " 7; i < *.!engt( ; iCC)
{
iK ( *&i+ %" <@8)
{
t&j+ " B@;
j " j C <;
t&j+ " *&i+;
t&j+ G" <@8;
}
else
t&j+ " *&i+;
jCC;
}
byte &+ t< " ne/ byte&j+;
K)r ( int 5 " 7 ; 5 < j ; 5CC)
t<&5+ " t&5+;
return t<;
}
}

*csc a)cs

Output
@D 67 @@ 67 @I
@D 1A= 1AD
@D 67 @@ 67 @I
A : C

The above program, which expounds the concept of compression and decompression, is
applicable only to ASCII text. ASCII text is defned as characters that represent
numbers from 0 to 128. The characters constituting the SOAP payload are all ASCII
244025452.doc 173 od 274
based. The program removes the spaces from the text, and subsequently, inserts them
back into place.

Any number ranging from 0 to 255, occupies one byte, i.e. 8 bits. The number 200
takes up the same amount of space as the number 10.

We start with the string "A B C", containing spaces between its characters. Then we
create three byte arrays named 'b', 'c' and 'd'.

The GetBytes function converts the string 's' into an array of bytes, which is stored in
the array 'c'. This array is then displayed, using a 'for' loop. We see the following:
65 - the ASCII value of 'A'.
32 - the ASCII value of 'space'.
66 - the ASCII value of 'B'.
32 - the ASCII value of 'space'.
67 - the ASCII value of 'C'.

This byte array, which has a size of 5, is then passed to the compress function.

The compress function, as its name indicates, initiates a reduction in the number of
bytes. First, it creates an array 't', which is of the same size as the array 'd'. The array
'd' is passed as a parameter to the function. It contains the original uncompressed
string. The Length property of an array returns the size of an array.

Using a 'for' loop, each and every member of the byte array 'd' is checked, in order to
determine whether it is a 'space' character or not. If it is not, the array member is
copied to the freshly created array 't'. The variable 'i' is used as an index to the array 'd',
and the variable 'j' is used as an index to the array 't'.

If we come across a space in the array, the 'if' statement gets activated. In the 'if' block,
we merely move on to the next number in the byte array 'd'. Then, we store this number
in the array 't', using 'j' as the index, but only after adding 128 to this number.

Thus, when we encounter a 'space' character after the character 'A' has been copied, the
next value 66, which is the ASCII value of B, gets picked. The value of 128 is then added
to the ASCII value of B, i.e. 66 + 128, resulting in the number 194. This number is then
inserted into the array 't'.

Thus, the algorithm or rule is quite plain and simple, i.e. if you encounter a 'space'
character, add 128 to the next number. This works without any complexity, since each
of the numbers 66 and 194, occupy just a single byte. Thus, the spaces are
compressed.

Then, we copy the array 't' into a new byte array named 't1', whose size is determined by
the variable 'j'. This array t1 is then returned and displayed. Thus, whenever we chance
upon a number greater than 128, it signifes the presence of a 'space' character, before
this particular character.

Now, to decompress the data, in the decompress function, an array 't' is created, which
is twice the size of the original array. This is to cater for the anticipated increase in the
244025452.doc 174 od 274
number of bytes. The same process is repeated again, except for the variations made to
the 'if' statement. In the 'if' statement, the number is verifed, to determine if it is larger
than 128. If it is so, the following actions get executed:
A space is added to the array t.
The index variable is increased by 1.
The value 128 is subtracted from the number.
Finally the subtracted value is copied into the new array.

For instance, when the number 194 is sighted, a space is frst inserted into the array.
Then, the number 128 is subtracted from 194, to obtain the original number i.e. 66.
Thereafter, the number 66 is stored in the new array. Thus, by applying this
mechanism, spaces are reinserted into their original positions.

We have employed the most elementary method available. However, in real life, the
method that is employed, allocates diferent bits to a character, based upon the
frequency of occurrence of the character. Thus, if the character 'A' occurs most often, a
smaller number of bits would be assigned to represent it, whereas, if the character 'Z'
occurs the least number of times, a larger number of bits maybe allocated to represent
it.

The next program is an extension of the encryption/decryption program. The client
compresses the bytes prior to encrypting them. On the other side, the server decrypts
the bytes and then decompresses them.

a.aspx
<.:'!%
<.>10%
<script language""c$" runat"server%
public v)i* -ageT!)a*()
{
zzz / " ne/ zzz();
l.4nner.tml " /.abc("1 M #");
}
<3script%
<3.>10%
<M;0S%
<b i*""l" runat""server"3%
<3.:'!%

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*+
&vijay(>nc">'.=esp)nse60ec"0'.=ePuest)+
public string abc( string a)
{
return "0 > D" C a;
}
}

zzz.cs
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
244025452.doc 175 od 274
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame"".ell)W)rl*)ap"6
9amespace""(ttp,33tempuri.)rg3")+
public class zzz, ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public zzz()
{
t(is.2rl " "(ttp,33l)cal()st,87873a.asmx";
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc")+
&vijay(>nc">'.=ePuest60ec"0'.=esp)nse)+
public string abc(string a)
{
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&+{a});
return ((string)(results&7+));
}
}

aaa.cs
using ystem;
using ystem.4;;
using ystem.Oml;
using ystem.:ext;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.ecurity.#rypt)grap(y;
&1ttribute2sage(1ttribute:argets.'et()*)+
public class vijay , )ap>xtensi)n1ttribute
{
>' em)*e" >'.9)ne;
0' *m)*e" 0'.9)ne;
public )verri*e :ype >xtensi)n:ype
{
get
{
return type)K(mu5(i);
}
}
public )verri*e int -ri)rity
{
get
{
return 7;
}
set
{
}
}
public >' >nc
{
get
{
return em)*e;
}
set
{
em)*e" value;
}
}
public 0' 0ec
{
get
{
244025452.doc 176 od 274
return *m)*e;
}
set
{
*m)*e" value;
}
}
}
public enum 0'
{
9)ne6
=esp)nse6
=ePuest
}
public enum >'
{
9)ne6
=esp)nse6
=ePuest
}
public class mu5(i , )ap>xtensi)n
{
tream );
tream n;
0' *m)*e;
>' em)*e;
Myte&+ 5 " {<6 @6 B6 H6 E6 I6 A6 8};
Myte&+ 5< " {<76<< 6 <@6 <B6 <H6 <E6 <I6 <A};
public mu5(i()
{
abc("#)nstruct)r");
}
public )verri*e )bject ?et4nitializer(!)gical'et()*4nK) m6 )ap>xtensi)n1ttribute a)
{
abc("?et4nitializer " C m.:)tring());
return a;
}
public )verri*e )bject ?et4nitializer(:ype t)
{
abc("?et4nitializer <");
return type)K(mu5(i);
}
public )verri*e v)i* 4nitialize()bject i)
{
vijay a " (vijay) i;
*m)*e " a.0ec;
em)*e " a.>nc;
abc("4nitialize " C i.:)tring() C " " C a.0ec.:)tring() C " " C a.>nc.:)tring());
return;
}
public )verri*e v)i* -r)cess'essage()ap'essage m)
{
iK ( m.tage "" )ap'essagetage.1Ktererialize)
{
abc("1Ktererialize " C em)*e.:)tring() C " " C n.-)siti)n );
n.-)siti)n " 7;
iK ((em)*e "" >'.=ePuest) YY (em)*e "" >'.=esp)nse))
{
abc("1Ktererialize iK");
n.-)siti)n " 7;
Oml:ext=ea*er rr " ne/ Oml:ext=ea*er(n);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(rr);
244025452.doc 177 od 274
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
abc(n).4nner:ext);
byte&+ inp< " >nc)*ing.2:D8.?etMytes(n).4nner:ext);
byte &+ inp " c)mpress(inp<);
'em)rytream ms< " ne/ 'em)rytream();
#rypt)tream cs " ne/ #rypt)tream(ms<6 *e.#reate>ncrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
byte&+ )u " ms<.:)1rray();
tringMuil*er s " ne/ tringMuil*er();
K)r(int i"7; i<)u.!engt(; iCC)
{
iK(i""()u.!engt(G<))
s.1ppen*()u&i+);
else
s.1ppen*()u&i+ C " ");
}
n).4nner:ext " s.:)tring();
'em)rytream ms " ne/ 'em)rytream();
*<.ave(ms);
ms.-)siti)n " 7;
n " ms;
}
:ext=ea*er r " ne/ tream=ea*er(n);
:extWriter / " ne/ treamWriter());
string sE " r.=ea*:)>n*();
abc(sE);
/.Write!ine(sE);
/.Dlus(();
}
iK ( m.tage "" )ap'essagetage.MeK)re0eserialize)
{
abc("MeK)re0eserialize " C *m)*e.:)tring());
'em)rytream *s " ne/ 'em)rytream();
iK ((*m)*e "" 0'.=ePuest) YY (*m)*e "" 0'.=esp)nse))
{
abc("MeK)re0eserialize iK");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(*s);
string sI " r.=ea*:)>n*();
/.Write!ine(sI);
abc(sI);
/.Dlus(();
abc("-)siti)n )K *s " C *s.-)siti)n);
*s.-)siti)n " 7;
Oml:ext=ea*er r7 " ne/ Oml:ext=ea*er(*s);
Oml0)cument *< " ne/ Oml0)cument();
*<.!)a*(r7);
Oml9amespace'anager nm " ne/ Oml9amespace'anager(*<.9ame:able);
nm.1**9amespace("s)ap"6 "(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3");
Oml9)*e n) " *<.electingle9)*e("33s)ap,M)*y"6 nm);
n) " n).Dirst#(il*.Dirst#(il*;
0>#rypt)ervice-r)vi*er *e " ne/ 0>#rypt)ervice-r)vi*er();
string sB " n).4nner:ext;
abc(sB);
c(ar&+ c " {U U};
string&+ ss " sB.plit(c);
byte&+ b " ne/ byte&ss.!engt(+;
244025452.doc 178 od 274
abc(ss.!engt(.:)tring());
K)r(int i"7; i<b.!engt(; iCC)
{
b&i+ " Myte.-arse(ss&i+);
}
byte&+ inp " b;
'em)rytream ms< " ne/ 'em)rytream();
#rypt)tream cs " ne/ #rypt)tream(ms<6*e.#reate0ecrypt)r( 56 5< )6
#rypt)tream')*e.Write);
cs.Write(inp6 76 inp.!engt();
cs.Dlus(DinalMl)c5();
byte&+ )u< " ms<.:)1rray();
byte&+ )u " *ec)mpress()u<);
string s< " >nc)*ing.2:D8.?ettring()u);
n).4nner:ext " s<;
abc(s<);
'em)rytream ms " ne/ 'em)rytream();
iK ( *m)*e "" 0'.=ePuest)
*<.ave("c,FFz.txt");
else
*<.ave("c,FFy.txt");
*<.ave(ms);
ms.-)siti)n " 7;
:ext=ea*er r< " ne/ tream=ea*er(ms);
:extWriter /< " ne/ treamWriter(n);
/<.Write!ine(r<.=ea*:)>n*());
/<.Dlus(();
}
else
{
abc("MeK)re0eserialize else");
:ext=ea*er r " ne/ tream=ea*er());
:extWriter / " ne/ treamWriter(n);
/.Write!ine(r.=ea*:)>n*());
/.Dlus(();
}
n.-)siti)n " 7;
}
}
public )verri*e tream #(aintream( tream stream )
{
abc("#(aintream");
) " stream;
n " ne/ 'em)rytream();
return n;
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public byte &+ c)mpress(byte &+ *)
{
byte &+ t " ne/ byte&*.!engt(+;
int i6j"7;
K)r ( i " 7; i < *.!engt( ; iCC)
{
iK ( *&i+ "" B@)
{
t&j+ " *&i C <+ ;
244025452.doc 179 od 274
t&j+ C" <@8;
iCC;
}
else
t&j+ " *&i+;
jCC;
}
byte &+ t< " ne/ byte&j+;
K)r ( int 5 " 7 ; 5 < j ; 5CC)
t<&5+ " t&5+;
return t<;
}
public byte &+ *ec)mpress(byte &+ *)
{
byte &+ t " ne/ byte&*.!engt(R@+;
int i6j"7;
K)r ( i " 7; i < *.!engt( ; iCC)
{
iK ( *&i+ %" <@8)
{
t&j+ " B@;
j " j C <;
t&j+ " *&i+;
t&j+ G" <@8;
}
else
t&j+ " *&i+;
jCC;
}
byte &+ t< " ne/ byte&j+;
K)r ( int 5 " 7 ; 5 < j ; 5CC)
t<&5+ " t&5+;
return t<;
}
}

a.txt
1Ktererialize =ePuest B@J
IE B@ II B@ IA
GGGGGGGGG
IE <JH <JE
MeK)re0eserialize =ePuest
MeK)re0eserialize iK
-)siti)n )K *s BEA
8 IE B@ II B@ IA
1 M #
1Ktererialize =esp)nse BII
I8 B@ IJ B@ A7 IE B@ II B@ IA
GGGGGGGGG
I8 <JA <J8 IE <JH <JE
MeK)re0eserialize =esp)nse
MeK)re0eserialize iK
-)siti)n )K *s B8J
8 I8 B@ IJ B@ A7 IE B@ II B@ IA
0 > D1 M #

SOAP re5uest
abc ,mlns%&!ttp:11tempuri)org1&*
"a*711 I= 1IA 76= 710 1@1 =1 1I7"1a*
"1abc*
SOAP 4esponse
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
244025452.doc 180 od 274
"abc4esult*6- 1A7 71A 66 7-@ 1=- 7=6 7D7"1abc4esult*
"1abc4esponse*

Output in :rowser
E E UA : C

a)bat
del c:Ra)t,t
del V)dll
csc 1t:librar' aaa)cs
csc 1t:librar' 333)cs 1r:aaa)dll

In the aspx fle, the function abc is called with a string parameter. The only modifcation
made to this fle is that, the string now contains spaces. The a.asmx fle and the zzz.cs
fle remain unchanged. However, the return value in the a.asmx fle, now has the string
"D E F" concatenated with the parameter value of 'a'.

There are some modifcations made to the aaa.cs fle. Before the bytes can be encrypted,
the text embodied in the frst node, needs to be compressed. So frstly, the bytes in the
original text are displayed from the byte array inp1. Then, the compress function is
called, which actually compresses the byte array, by uprooting all the spaces.

The new byte array is also displayed. The exercise of compression is carried out prior to
the event of bytes being sent out to the other side, each time. Thereafter, the data
packet is encrypted.

In the BeforeDeserialize event, the bytes are frst decrypted. After decryption, this byte
array is handed over to the decompress function. The resultant bytes have been
displayed at every stage, so that you can visually determine the result of every
individual process.

An alternative to DES is the Triple DES Encryption, which is a great deal more
sophisticated, but works along similar lines. The above method can also be modifed, by
employing an asymmetrical algorithm, such as, a public key and a private key.

A program can be downloaded of the RSA site, and executed to generate two keys, viz. a
public key and a private key. A byte stream that is encrypted with a public key, can only
be decrypted with the private key, and vice versa. The public key, as the name suggests,
is meant for the public. Therefore, it can be unveiled to the whole world. A private key is
meant for private use. Hence, as the saying goes, it should not be divulged even to your
spouse!

The client keeps the private key close to its heart, and distributes the public key to the
interested parties. Then, it encrypts the fle that is to be sent across, using its private
key. On receiving the packet, the server decrypts it, using the public key of the client.
In the reverse procedure, the server uses the public key of the client to encrypt the
packet that is to be sent over to the client. It is only the client's sole prerogative to
decrypt this packet, since it is in possession of the private key. So, it uses the private
key to decrypt it. In this manner, the issue of security is taken care of.

Since the public key is made public, it could pose a problem in the sense that, it could
fall into wrong hands. So, in order to plug this loophole, the client frst encrypts the
244025452.doc 181 od 274
packet with its private key, followed by one more layer of encryption using the public key
of the destination server. Now, only the designated can decrypt it, since it alone holds
the private key to the packet. In the next step, the server would use the client's public
key to decrypt the data.

Along the same lines, while sending the packet back to the client, the server frst
encrypts it using its private key, and then, encrypts it further, by using the client's
public key. On similar lines, when the packet is received, the client frst decrypts the
data using its private key, followed by further decryption, using the server's public key.

This procedure ensures that only the genuine client and server have access to the SOAP
payload, since the private keys are not to be shared with anyone. The above
methodology is assigned the nomenclature of a 'digital envelope'.

Message Digests

a.cs
using ystem.:ext;
using ystem.ecurity.#rypt)grap(y;
public class zzz
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string s " "1M#";
byte &+ c;
c " >nc)*ing.1#44.?etMytes(s);
'0E m " ne/ '0E#rypt)ervice-r)vi*er ();
byte&+ * " m.#)mpute.as((c);
K)r ( int i"7; i < *.!engt( ; iCC)
ystem.#)ns)le.Write(*&i+.:)tring() C " ");
}
}

Output
1== =I 10A 71- 1II 776 17 IA 117 10- 1@D 71- D6 6I 766 D-

After creating an object 'a' of type zzz, the string 's' is initialized to the string "ABC". The
string is then converted into a byte array and stored in 'c', using the GetBytes function.
Now, we use a new wrapper class called MD5CryptoServiceProvider, which is derived
from the class MD5. From this class, a function ComputeHash is called, which accepts
a byte array, as well as, returns a byte array. The return value is stored in 'd'.

The byte array, when displayed, reveals a series of unintelligible numbers. The output is
depicted above. Now, change the string value to "AB". On doing so, there will be a
drastic change in the output, which is also refected below.

Output
10= 111 1A0 1I@ 01 7=@ @1 11D 777 60 =D I@ D7 77I 1@- 1@A

Even a slight mutation in a single character, results in an altogether diferent set of
values.

244025452.doc 182 od 274
A Message Digest is a series of numbers that represents some data. The algorithm used
above is called MD5. In this method, a unique number is generated to represent the
document. Thus, throughout time and space, the string "AB" would be represented by
the above Message Digest number.

The document is sent over by the client, subsequent to its Message Digest number being
calculated. At the server end, on receipt of the message, the Message Digest Number is
recalculated. In the eventuality of the numbers not matching, it is safe to conclude that,
the document has been tampered with. We leave it as an exercise for you to implement a
SOAP extension that uses MD5.

a.cs
using ystem.:ext;
using ystem.ecurity.#rypt)grap(y;
public class zzz
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string s " "1M";
byte &+ c;
c " >nc)*ing.1#44.?etMytes(s);
byte &+ 5 ;
5 " ne/ byte&8+{<6@6B6H6E6I6A68};
.'1#.1< ( " ne/ .'1#.1<(5);
byte &+ * " (.#)mpute.as((c);
K)r ( int i"7; i < *.!engt( ; iCC)
ystem.#)ns)le.Write(*&i+.:)tring() C " ");
ystem.#)ns)le.Write!ine();
5 " ne/ byte&8+{<6@6B6H6E6I6A6J};
( " ne/ .'1#.1<(5);
* " (.#)mpute.as((c);
K)r ( int i"7; i < *.!engt( ; iCC)
ystem.#)ns)le.Write (*&i+.:)tring() C " ");
}
}

Output
167 1-6 77A 766 777 D1 1A- 1AD A@ 11@ 716 70 107 7D6 777 DI 77A 11I 10- 16-
77= 711 10D 771 I= 17= @7 7-6 7D1 1-= A@ 0@ 1=D 1-I DA DI 7-- 1@I 106 A-

Though the Message Digests algorithm and the checksum methodology appear to be
secure, they are not completely reliable.

Every TCP/IP packet has two checksums; one is for TCP, while the other is for IP. Just
anyone can change a byte of the SOAP payload, and simultaneously, recalculate the
TCP/IP checksums. This change could go undetected. So, checksums are not very
dependable, as they are susceptible to manipulation. The same is true for the Message
Digest computation.

It would be a sagacious move to encrypt the SOAP payload, and then, recalculate the
new MD5 hash value. Over and above this, it would make sound sense to encrypt the
MD5 hash also, before transmitting the packet across, or else, the hash loses its
sanctity.

244025452.doc 183 od 274
In the above program, we have a class called HMACSHA1, where HMAC is an acronym
for "Hash based Message Authentication Code", and SHA1 represents the hashing
algorithm. This class calculates a hash value and uses a key or password, which is
passed to the constructor.

The hash value that gets generated at this stage, not only depends upon the input data,
but also on the key. In the next round, we keep the input byte array the same, with the
exception of the last byte of the key. It is changed to 9 from 8. As a result of this
modifcation, the entire hash changes dramatically.
Thus, it is advisable to use the HMACSHA1 class, because when the hash value is sent
across, only those with the password can compute or recompute the hash value.

0nother ro)le* with s&**etrical encr&tion al+orith*s is that o! >2e& *ana+e*ent>. @ow
can we trans!er the 2e& to the other side, in a secure *annerA /ne ossi)ilit& is to i*le*ent
the u)lic 2e& ? ri'ate 2e& lo+ic. :ut then, the al+orith* slows down the rocessin+. #i+ital
si+natures are )ased on Messa+e #i+est al+orith*s and 1u)lic 2e&sB1ri'ate 2e&s.
A
Attributes

This chapter rivets around those attributes, which can be placed upon entities, such as-
functions, classes, properties etc. in both, the asmx fle, as well as, the proxy program.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Oml.erializati)n;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public int i;
public xxx 5;
public int j;
}
public class xxx {
public int x<6x@;
}
a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
yyy b " ne/ yyy();
xxx c " ne/ xxx();
b.i " <7;b.j " @7;
b.5 " c;
c.x< " <77; c.x@ " @77;
a.abc(b);
244025452.doc 184 od 274
}
}

3)bat
del V)e,e
del V)dll
del 333)cs
wsdl aa)wsdl
csc 1t:librar' 333)cs
csc a)cs 1r:333)dll
a

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
"a*
"i*1-"1i*
"k*
",1*1--"1,1*
",7*7--"1,7*
"1k*
"2*7-"12*
"1a*
"1abc*

In the asmx fle, the function abc in class zzz accepts a parameter 'a', of type yyy. The
class yyy has two int variables, i and j, and a third variable 'k', of type xxx. The class
xxx contains two variables, x1 and x2.


In the browser, enter the url as http://localhost/a.asmx?WSDL and then, save the
output in a fle named aa.wsdl. Since, our very core of concern is the data encompassed
in the SOAP packet that fows to and fro, we alter the port number of localhost to 8080,
and banish the inane or worthless characters. Thereafter, the client proxy is generated,
courtesy - the wsdl program. As the WSDL fle and proxy introduce nothing that is
really innovative, we give them the slip for a while.

The client program named a.cs, creates three objects, viz. xxx, yyy and zzz. The creation
of a yyy object does not result in the creation of an xxx object automatically. In fact, it
has to be created expressly.

Thereafter, using object 'b' of type yyy, the 'k' member of type xxx is initialized to 'c',
which is an xxx object. The other members of the yyy object are also initialized. The
object 'b' is then passed as a parameter to the function abc.

As is customary, the SOAP request originates with the parameter 'a', which encloses its
three members viz. i, j and k. Since the variable 'k' is also an object, it becomes the
parent tag of the two members x1 and x2, which it embodies. Therefore, objects that are
enclosed within other objects, carry their children together with them.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Oml.erializati)n;
public class zzz
{
&Web'et()*+
244025452.doc 185 od 274
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public int i;
public xxx &+ 5;
public int j;
}
public class xxx
{
public int x<6x@;
}

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
yyy b " ne/ yyy();
b.i " <7;b.j " @7;
xxx &+ c " ne/ xxx&@+;
c&7+ " ne/ xxx();
c&7+.x<" @7;c&7+.x@" @<;
c&<+ " ne/ xxx();
c&<+.x<" @77;c&<+.x@" @7<;
b.5 " c;
a.abc(b);
}
}

SOAP re5uest
"abc ,mlns%&!ttp:11tempuri)org1&*
/ "a*
"i*1-"1i*
/ "k*
/ ",,,*
",1*7-"1,1*
",7*71"1,7*
"1,,,*
/ ",,,*
",1*7--"1,1*
",7*7-1"1,7*
"1,,,*
"1k*
"2*7-"12*
"1a*
"1abc*


In the asmx fle, the variable 'k' is an array of xxx objects. Earlier, it had been declared
as a simple variable. With the exception of this modifcation, everything else remains
unaltered. The WSDL fle and the client proxy are both generated as before.

Firstly, in the client program, an array called 'c', of xxx objects, is created. It has a size
of 2. Both the arrays are initialized, by being referred to as c[0] and c[1]. The data
displayed in the SOAP request is comprised of the three variables i, j and k. The variable
244025452.doc 186 od 274
'k', being an array of two objects, contains two child elements called xxx. It is these
child elements, which accommodate the array contents.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Oml.erializati)n;
public class zzz
{
&Web'et()*+
public v)i* abc(yyy a)
{
}
}
public class yyy
{
public int i;
&Oml1ttribute()+
public int j;
}

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
yyy b " ne/ yyy();
b.i " <7;b.j " @7;
a.abc(b);
}
}

aa./s*l
<s,c)mplex:ype name""yyy"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" type""s,int" 3%
<3s,sePuence%
<s,attribute name""j" type""s,int" 3%
<3s,c)mplex:ype%

zzz.cs
public class yyy
{
public int i;
&ystem.Oml.erializati)n.Oml1ttribute1ttribute()+
public int j;
&ystem.Oml.erializati)n.Oml4gn)re1ttribute()+
public b))l jpeciKie*;
}

SOAP re5uest
"a*
"i*1-"1i*
"1a*

In the world of XML Serialization, we retain the prerogative to elect and settle upon the
methodology, by means of which, the XML data shall be sent across the wire. By placing
an attribute named XmlAttribute on the variable j in the wsdl fle, it becomes evident
244025452.doc 187 od 274
that the complexType yyy has only one element called i. The variable j assumes the form
of an attribute, instead of an element.

Thus, the WSDL honours the attribute. The a.cs fle is not really plagued about whether
'j' is an attribute or an element. The client program remains absolutely unchanged. The
proxy that is generated, has the attribute XmlAttributeAttribute placed on it, along with
another member called jSpecifed, with an attribute of XmlIgnoreAttribute on it.

Despite of our having assigned a value to variable 'j', it never gets refected in the SOAP
request. We were of the notion, that the value contained in 'j', would be sent out as an
attribute. However, at this stage, it has completely been snubbed by the System.
Now, we just add another line to the a.cs fle.

a.cs
b.i " <7;b.j " @7;
b.jpeciKie* " true;
a.abc(b);

SOAP re5uest
"a 2%&7-&*
"i*1-"1i*
"1a*

On initializing the jSpecifed member to 'true', the SOAP request that is sent across,
displays 'j' as an attribute to the parameter name 'a', with a value of 20. The default
value assigned to the jSpecifed variable is 'false'. Hence, it is for this reason that 'j' was
not sent over the wire earlier on; in other words, it was not serialized.

If you replace the XmlAttribute with the attribute of SoapAttribute, the attribute would
throw the following error:

Output
a)cs>0F1B: error CS-11I: J'''J does not contain a dePnition .or J2SpeciPedJ

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Oml.erializati)n;
public class zzz {
&Web'et()*+
public v)i* abc(yyy a) { }
}
public class yyy
{
&)ap1ttribute()+
public int i;
&Oml1ttribute(1ttribute9ame""***")+
public int j;
}

aa./s*l
<s,attribute name""***" type""s,int" 3%

zzz.cs
public class yyy
{
244025452.doc 188 od 274
public int i;
&ystem.Oml.erializati)n.Oml1ttribute1ttribute()+
public int ***;
&ystem.Oml.erializati)n.Oml4gn)re1ttribute()+
public b))l ***peciKie*;
}

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
yyy b " ne/ yyy();
b.i " <7;
b.*** " @7;
b.***peciKie* " true;
a.abc(b);
}
}

SOAP re5uest
"a ddd%&7-&*
"i*1-"1i*
"1a*

The AttributeName property is employed here, since our intention is to change the name
of the variable, from 'j' to 'ddd'. Therefore, on generating the WDSL fle, the name
assigned to the attribute is 'ddd', and not 'j'.

In the proxy that is generated, the SoapAttribute is not afected. However, the name
assigned to the bool variable is 'dddSpecifed', thereby, reafrming the change of the
variable name to 'ddd'.


Both, the client program and the SOAP payload, refer to the variable as 'ddd', and not
as 'j'. Thus, we can exercise absolute authority over the variables' names written in the
SOAP payload.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz {
&Web'et()*(0escripti)n""vijay mu5(i")+
public v)i* abc()
{
}
}

aa./s*l
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<*)cumentati)n%vijay mu5(i<3*)cumentati)n%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%

a.cs
244025452.doc 189 od 274
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
a.abc();
}
}

The WebMethod attribute that remotes a function, contains a property called
Description, which facilitates certain amount of documentation in the function abc. The
wsdl fle generated from the asmx fle, has the portType element, which contains the
operation element of abc. This is followed by the element documentation, which carries
the name of 'vijay mukhi'.


In essence, this is what the Description property is all about. However, there is no
mention of Description in the proxy that is generated, since the wsdl utility disregards
the element completely.

Application and Session Objects

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz , Webervice
{
&Web'et()*()+
public int abc()
{
iK (1pplicati)n&"zzz"+ "" null)
1pplicati)n&"zzz"+ " <;
else
1pplicati)n&"zzz"+ " ((int) 1pplicati)n&"zzz"+) C <;
return (int) 1pplicati)n&"zzz"+;
}
}

In the above asmx fle, the class zzz is derived from the WebService class. This class has
a property called Application, which is of type HttpApplicationState. The variables are
created using the indexer. These are not variables in the real sense of the term, but they
boast of all functionalities of a variable.

Thus, Application["zzz"] creates a variable named 'zzz'. Since it is not initialized, it has a
value of null. When the abc function is invoked for the frst time, the value of zzz gets
set to 1. This may be ascertained by specifying the address
http://localhost/a.asmx/abc? in the browser window.

The question mark at the end of the URL is optional, and is used when parameters are
required to be supplied to the function abc. Now, click on the refresh button in the
browser. This invokes the same function again.Since the Application object has the
value of 1, it saves this last value of the zzz state variable, increments it by 1, and then,
restores the new value. Therefore, the number 2 is displayed in the browser.
244025452.doc 190 od 274
Leave the browser window as it is and open a new copy of IE. Then, enter the same Url.
Now, the value that would be displayed is 3.

The HTTP protocol is referred to as 'stateless'. This is so because, as soon as the
connection between the server and the client cleaves, all the activities and information
related to the client and the server get obliterated. As a consequence, when we request
the server for a new page, it entails re-establishment of connection between the two
ends.

Thus, the process starts anew each time, proving to be irksome. The Application object
is primarily utilized to maintain 'state', thereby, enabling the web server to keep track of
the events that have transpired at its end.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz , Webervice
{
&Web'et()*(#ac(e0urati)n"I7776>nableessi)n"true)+
public int abc()
{
iK (essi)n&"zzz"+ "" null)
{
essi)n&"zzz"+ " <;
}
else
{
essi)n&"zzz"+ " ((int) essi)n&"zzz"+) C <;
}
return (int) essi)n&"zzz"+;
}
}

In the case of the Application property, the state is maintained as per the requirement
of the machine, and not as per the browser. Consequently, the session object, with the
variables by its side, is used to start the browser afresh each time. When we initiate a
new copy of the browser, the count also starts with 1.

The state object zzz is restored with the copy of the browser. So, when a new browser
instance is loaded, the variable zzz begins with the value of 1. The lacuna in this
approach is that, the web server is bound to run into rough weathers and slow down
considerably. The speed of the web server is trammeled because, there would be
innumerable copies of the browser interacting with the server, and the server would
have no choice but to maintain an equal number of copies of the variable zzz.

Thus, by default, the Session property is disabled. To enable it, we utilize the property
of the WebMethod attribute, and activate EnableSession. The Session property uses
Cookies to maintain state, or to uniquely identify an instance of a browser. The
CacheDuration property determines the duration in seconds, for which the page should
linger in the cache, before the system reads it again from its hard disk.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
244025452.doc 191 od 274
public class zzz , Webervice
{
&Web'et()*('essage9ame""vijay")+
public int abc()
{
return <77;
}
&Web'et()*('essage9ame""mu5(i")+
public int abc(int i )
{
return i;
}
}

!ttp:11local!ost1a)asm,1vi2a'
!ttp:11local!ost1a)asm,1muk!i+i%176

In an asmx fle, no two functions can share the same name. However, with the help of
the MessageName property, a new name may be assigned to a common function.

The frst abc function in the asmx fle is named 'vijay', whereas, the second one is
named 'mukhi'. Therefore, the frst url contains 'vijay', and not 'abc'. The second
function of 'abc' accepts a parameter. Therefore, the function abc named 'vijay' is
ignored, and the new name assigned to abc is 'mukhi'.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
&Webervice1ttribute(0escripti)n""vijay mu5(i")+
public class zzz , Webervice
{
&Web'et()*()+
public v)i* abc()
{
}
}

aa./s*l
<service name""zzz"%
<*)cumentati)n%vijay mu5(i<3*)cumentati)n%
Z..
<3service%

Unlike the WebMethod attribute, which is placed on a function, the WebServiceAttribute
is placed on a class. The Description property is employed to document the WebService.
Therefore, at the end of the WSDL fle, we encounter the last element service,
containing the name of the class zzz. The Description property becomes the element
documentation for the zzz service.

a.asmx
&Webervice1ttribute(9ame""vijay")+

Modify the parameter of the WebServiceAttribute to the one depicted above, and observe
the changes in the WSDL fle.

In the WSDL fle, since the name of the class is zzz, most elements begin with zzz.
However, we would be able to modify the name of the service to 'vijay', by using the
244025452.doc 192 od 274
Name property. This would result in a change in the other elements too. The name of
the proxy that is generated, would also change to vijay.cs, with the class name displayed
as 'vijay'. Thus, we would be able to infuse a considerable amount of fexibility, by the
use of attributes.

a.asmx
&Webervice1ttribute(9amespace""vijay")+

aa./s*l
xmlns,s7""vijay" target9amespace""vijay"

The WSDL fle sets out with the defnitions, which defne and delineate a large number
of namespace prefxes. This situation can be suitably altered, by using the Namespace
property. The targetNamespace attribute ensures that a targetNamespace called 'vijay' is
created, which relates to all the entities created in the fle. You would have discerned
that, the browser does not display any text on loading the asmx fle, unlike the case of
the earlier output.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.#)llecti)ns.pecialize*;
using ystem.Web;
&WeberviceMin*ing()+
public class zzz , Webervice
{
&Web'et()*()+
public string abc()
{
string s " "";
int i;
9ameQalue#)llecti)n c;
.ttp=ePuest r " #)ntext.=ePuest;
c"r..ea*ers;
string&+ s< " c.1llLeys;
K)r (i " 7; i<s<.!engt(; iCC)
{
s " s C "Ley, " C s<&i+ C """;
string&+ s@"c.?etQalues(s<&i+);
s " s C s@&7+ C ".";
}
return s;
}
}


Output
Ce': Connection%Ceep/Alive)
Ce': Accept%V1V)Ce': Accept/Encoding%g3ipF deKate)
Ce': Accept/9anguage%en/us)
Ce': ;ost%local!ost)
Ce': 4e.erer%!ttp:11local!ost1a)asm,+op%abc)
Ce': <ser/Agent%Mo3illa1=)- >compatible? MSIE @)-b? Windows ( D)-? )(E C94
1)-)7A1=B)

This book primarily converges around the concepts of SOAP and XML. Hence, we do not
submerge ourselves any deeper into the details of the Webservice class. Nonetheless, we
244025452.doc 193 od 274
have presented an artless yet efective example, which highlights the infuence exerted
by the properties contained in the class.

It is possible for us to access every aspect of the web server, by using the WebService
class. One such property in this class is the Context property, which is of type
HttpContext. This property has a host of other properties of type HttpRequest, each
prefxed with the word 'Request'. Moreover, there exists a member called Headers, which
returns the headers received by a Web Server. The data type of this return value is a
NameValueCollection object.

The object c' has a property called AllKeys, which returns an array of strings. The
values contained in the array are the keys that arrive at the web server. A key is the
word, placed before the 'equal to' sign in a name-value pair. With the assistance of a 'for'
loop, every key in the array is accessed. Thereafter, using the GetValues function, the
value of each key is returned.

Each key can have multiple values, but we have confned ourselves merely to the frst
value. The key and its corresponding value are placed in a huge string, and then, they
are sent across. These values are displayed, when the asmx fle is loaded in the browser.


Thus, by harnessing the abilities of the properties of the Context object, the information
sent to the web server can be accessed with considerable ease.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public int abc(int i 6 int j)
{
return iCj;
}
}

a.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string b;
b " a.abc(<76@7);
ystem.#)ns)le.Write!ine(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public string abc(int i 6 int j)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject&+ results " 4nv)5e("abc"6 ne/ )bject&@+{i6j});
return (string)results&7+;
}
}

*csc a)cs
244025452.doc 194 od 274
*a

The asmx fle and the .cs fle are analogous to the ones encountered in the earlier
chapters. The function abc in the asmx fle, returns the sum of the two ints that are
supplied to it as parameters. In the client program, the function abc is called with the
two values of 10 and 20. Thereafter, everything else works with clockwork precision.

Now, carry out a minor modifcation to the above program, by eliminating the attribute
of SoapDocumentMethodAttribute. On doing so, the following exception is thrown:

Output
<n!andled E,ception: S'stem)ArgumentE,ception: abc Web Service met!od name is
not valid)

Thus, this corroborates our credence that, it is the SoapDocumentMethodAttribute that
introduces code, when we are remoting functions from the client end.

a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(1cti)n""s)nal")+

Output
<n!andled E,ception: S'stem)Web)Services)Protocols)SoapE,ception:
S'stem)Web)Services)Protocols)SoapE,ception: Server did not recogni3e t!e value o.
;P ;eader SOAPAction: sonal)
at S'stem)Web)Services)Protocols)SoapServerProtocol)Initiali3e>B

The frst property that is employed with SoapDocumentMethodAttribute is 'Action'. It is
used to set only the Http header SOAPAction, which has been added by the SOAP
specifcations. This header spells out the intentions of the SOAP request. The default
value is http://tempuri.org, followed by the function name 'abc'.

The SOAP specifcation is not rigid with respect to the contents of this value. Therefore,
frewalls can exploit this function to flter out unwanted SOAP requests. In our case, the
server throws an exception, indicating the fact that it cannot recognize or comprehend
'sonal'. It is the Invoke function that triggers of the Exception. The server generates a
SOAP fault, since it does not recognize the SOAPAction header at all.


a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(;neWay"true)+

Output
2n(an*le* >xcepti)n, ystem.>xcepti)n, 'et()* zzz.abc can n)t be reKlecte*. GGG%
ystem.>xcepti)n, ;neG/ay met()*s cann)t (ave return values.
at ystem.Web.ervices.-r)t)c)ls.)ap=eKlect)r.=eKlect'et()*(!)gical'et()*4nK) met()*4nK)6
M))lean client6 Oml=eKlecti)n4mp)rter xml4mp)rter6 )ap=eKlecti)n4mp)rter s)ap4mp)rter6 tring
*eKault9s)

The next property to be implemented is the OneWay property. Its value is set to 'true',
although, its default value is 'false'.

By throwing an exception, it acquaints us with the fact that, the OneWay function
cannot have a return value. The exception is generated by the RefectMethod, and not by
244025452.doc 195 od 274
the Invoke function. You would have observed that, no bytes are visible in the Trace
output.

a.cs
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices.0escripti)n;
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
a.abc(<76@7);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(;neWay"true)+
public v)i* abc(int i 6 int j)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
4nv)5e("abc"6 ne/ )bject&@+{i6j});
}
}

SOAP response
;P11)1 1-- Continue
Server: Microso.t/IIS1D)-
Eate: WedF 1I Oct 7--1 -7:60:-1 HM

;P11)1 7-- OC
Server: Microso.t/IIS1D)-
Eate: WedF 1I Oct 7--1 -7:60:-1 HM
Cac!e/Control: privateF ma,/age%-
Content/'pe: te,t1,ml? c!arset%ut./0
Content/9engt!: 6D0
"+,ml version%&1)-& encoding%&ut./0&+*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance& ,mlns:,sd%&!ttp:1
1www)w6)org17--118M9Sc!ema&*
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*6-"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

In place of 'formatted', set the trace output to 'unformatted', and take a look at the bytes
that contain this header data.

The above example has no return value in either of the two functions, i.e. abc and Main.
An HTTP response always starts with the HTTP version number 1.1 and a success or
error code, followed by the description of the status code. For instance -
200 is followed by 'OK'.
404 is followed by 'File Not found'.
100 is followed by 'Continue'.

The status is followed by headers, such as- Date, Cache-Control, Content-type and
length.

244025452.doc 196 od 274
The OneWay property, as specifed in the client program, indicates that the client would
not wait for the web server to complete the processing of the Web Service method.
Therefore, the client sends the header "Expect: 100 Continue".

On receiving the request, the server too frst sends across an HTTP header. Thereafter,
it sends the entire SOAP payload, together with the reply.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(;neWay"true)+
public v)i* abc(int i 6 int j)
{
}
}

SOAP response
;P11)1 1-- Continue
Server: Microso.t/IIS1D)-
Eate: WedF 1I Oct 7--1 -7:D1:76 HM

;P11)1 7-7 Accepted
Server: Microso.t/IIS1D)-
Eate:WedF 1I Oct 7-- 1 -7:D1:7= HM
Cac!e/Control: private
Content/9engt!: -

An alternative approach would be, to set the Attribute OneWay on the WebService
method, on the server. On doing so, the server will frst send an HTTP/1.1 100 packet,
followed by a "202 Accepted" response. This response packet, when received by the
client, will ascertain that the client does not have to wait for the server to dispatch the
result packet. However, in this case, there is no SOAP response at all.

Thus, the WebService will frst deserialize the SOAP message, and then send the 202
response over. This is done with the primary aim of apprising the client about the fact
that, the server is in receipt of the message, and has started processing it. Thereafter,
the client will receive no further intimation of the activities taking place on the server.
This is the reason why we have not specifed any return values or parameters. However,
if an exception is thrown, a return packet specifying the exception, would defnitely be
sent across.

In the frst example of the asmx fle, the function abc returns an int. However, in the
a.cs fle, the value is accepted in a string. By default, no data types are sent across.
Thus, we need to be exceedingly cautious about the parameters that are dispatched or
received, since an XML fle is capable of incorporating only the textual data.

If you were to change the trace design to a 'formatted' trace, no return packet would be
perceptible at all. Now, undo the changes made in the a.cs and a.asmx fles, and revert
them back to their original position, i.e. at the start of the attribute. The code contained
in the .cs fle is shown below.

244025452.doc 197 od 274
a.cs
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices.0escripti)n;
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
a.abc(<76@7);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute
(-arametertyle"ystem.Web.ervices.-r)t)c)ls.)ap-arametertyle.Mare)+
public string abc(int i 6 int j)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject&+ results " 4nv)5e("abc"6 ne/ )bject&@+{i6j});
return (string)results&7+;
}
}

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute()+
public int abc(int i 6 int j)
{
return iCj;
}
}

SOAP re5uest
"soap::od'*
"i ,mlns%&!ttp:11tempuri)org1&*1-"1i*
"2 ,mlns%&!ttp:11tempuri)org1&*7-"12*
"1soap::od'*

SOAP response
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*-"1abc4esult*
"1abc4esponse*
"1soap::od'*

Earlier, when we had sent a SOAP request, we had frst specifed an element called abc,
which is the name of the function, followed by the names of the parameters. This was
imperative, since the ParameterStyle property had a default value of 'Wrapped'.
Moreover, the return value was depicted as zero. This option ensures that the
parameters are wrapped within the method name, beneath the Body element.

When the value of 'Bare' is specifed in the ParameterStyle, as an outcome, the method
name is wiped out completely. These are the only two styles that are available.
a.asmx
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(-arametertyle"
ystem.Web.ervices.-r)t)c)ls.)ap-arametertyle.Mare)+

SOAP response
244025452.doc 198 od 274
"soap::od'*
"abc4esult ,mlns%&!ttp:11tempuri)org1&*6-"1abc4esult*
"1soap::od'*
Modifying the style to 'Bare' in the asmx fle, results in an answer of 30. However, the
abcResponse element is not visible in the output. You may repeat this process in the
client program too.

a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
=ePuest>lement9ame""abc<")+

SOAP re5uest
"abc1 ,mlns%&!ttp:11tempuri)org1&*

SOAP response
"abc4esult*-"1abc4esult*

The RequestElementName property alters the name of the function. So, the function
abc is now known as 'abc1'. Resultantly, the element name in the SOAP request packet
also becomes abc1. Since there exists no function called abc1, no error is generated,
but the answer has a value of zero.

a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
=ePuest9amespace""mu5(i")+

SOAP re5uest
"abc ,mlns%&muk!i&*

SOAP response
"abc4esult*-"1abc4esult*

Next, we alter only the RequestNamespace property to 'mukhi'. Yet again, no answer is
obtained, since the function abc belongs to the namespace tempuri.org, in the asmx
fle.

a.asmx
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
=ePuest9amespace""mu5(i")+

SOAP response
"abc4esult*6-"1abc4esult*

Now, if we were to modify the attribute in the asmx fle, so that it may contain the same
value, the correct answer would be obtained. It is so because, both the XML entities, i.e.
the functions abc, belong to the same namespace of 'mukhi'.

a.asmx
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
=esp)nse9amespace""mu5(i"6=esp)nse>lement9ame""vijay")+

SOAP response
"vi2a' ,mlns%&muk!i&*X
"abc4esult*-"1abc4esult*
"1vi2a'*

244025452.doc 199 od 274
The same set of rules is applicable to the return packet too. In the asmx fle, the
namespace and the name are both set to 'mukhi' and 'vijay', using the
ResponseNamespace and ResponseElementName, respectively.

Ensure that the same attribute values are specifed in the .cs fle also. If this is not
done, the SOAP response goes on to confrm that the changes have been implemented,
however, the client gets thoroughly confused. It happens because, the client expects an
abcResult within an abcResponse parent, in a particular namespace.

a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
=esp)nse9amespace""mu5(i"6=esp)nse>lement9ame""vijay")+

Output
6-

On introducing the same attribute to the client, the result of '30' is obtained. Thus, it
would be a judicious move to efect similar amendments on both sides, the client side
and the server, since they are generally located on disparate machines, which could be
geographically separated by millions of miles.
a.asmx
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.>nc)*e*)+
a.cs
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.>nc)*e*)+

SOAP re5uest
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:soapenc%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:tns%&!ttp:11tempuri)org1& ,mlns:t'pes%&!ttp:11tempuri)org1encoded'pes &
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od' soap:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&*
"t'pes:abc*
"i ,si:t'pe%&,sd:int&*1-"1i*
"2 ,si:t'pe%&,sd:int&*7-"12*
"1t'pes:abc*
"1soap::od'*
"1soap:Envelope*

SOAP response
"+,ml version%&1)-& encoding%&ut./0& +*
"soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:soapenc%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:tns%&!ttp:11tempuri)org1& ,mlns:t'pes%&!ttp:11tempuri)org1encoded'pes&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
"soap::od' soap:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&*
"t'pes:abc4esponse*
"abc4esult ,si:t'pe%&,sd:int&*6-"1abc4esult*
"1t'pes:abc4esponse*
"1soap::od'*
"1soap:Envelope*

244025452.doc 200 od 274
The client program and the asmx fle on the server are now introduced to a property
called Use, which is initialized to a value of 'Encoded', using the enum
SoapBindingsUse. The only other value that can be assigned is 'Literal'.

The two values, 'Literal' and 'Encoded', have been determined by the WSDL standard.
The Use property sets the parameter encoding for the SOAP payload.

The 'Literal' option encodes parameters, using a predefned XSD schema for each
parameter, whereas, the 'Encoded' method uses the rules mentioned in Section 5 of the
SOAP specifcation. To cut the story short, the Envelope element now has 6
namespaces, instead of the 3 earlier ones. The attribute encodingStyle, from the soap
namespace, explicitly specifes a style encoding. We do not bump into any method with
the name of abc, however, we do come across the method name, containing the 'types'
namespace prefx, which refers to the URI of http://tempuri.org/encodedTypes.

Within the child elements i and j, we overtly specify a type, using the type attribute
from either the xsd or XML Schema namespaces. The individual types that are used,
are defned by the XML Schema world. Thus, by employing the encoding style, the
process of transmitting the data types and the contents of the parameters, gets
simplifed. The return value also comports itself in a similar fashion. This encoding
behavior is preferred over the default behaviour. It is because, the other end becomes
cognisant of the data type that it has received.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public v)i* abc()
{
}
}

a.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
yyy b " ne/ yyy();
b.i"<7;b.5"@7;
xxx c " ne/ xxx();
c.x " <77;
b.j " c;
a.abc(b);
}
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute(
2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.>nc)*e*)+
public v)i* abc(yyy a)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
4nv)5e("abc"6 ne/ )bject&<+{a});
}
}
public class yyy {
public int i;
244025452.doc 201 od 274
public xxx j;
public int 5;
}
public class xxx
{
public int x;
}

SOAP re5uest
"soap::od' soap:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&*
"t'pes:abc*
"a !re.%&Wid1& 1*
"1t'pes:abc*
"t'pes:''' id%&id1& ,si:t'pe%&t'pes:'''&*
"i ,si:t'pe%&,sd:int&*1-"1i*
"2 !re.%&Wid7& 1*
"k ,si:t'pe%&,sd:int&*7-"1k*
"1t'pes:'''*
"t'pes:,,, id%&id7& ,si:t'pe%&t'pes:,,,&*
", ,si:t'pe%&,sd:int&*1--"1,*
"1t'pes:,,,*
"1soap::od'*

In the above C# program, a yyy object that contains two int members, i and k, is sent
across. It also contains a class xxx member j. The xxx class has only one int x.

The yyy object is now passed as a parameter to the function abc. The asmx fle neither
accepts any parameters, nor does it return any values. As was mentioned earlier, this
does not result in the generation of any exceptions.

The SOAP request is much more complex than before. A type abc is created, which uses
a href to a type id1. The type yyy has an id of id1, and its type attribute refers to the
type yyy, in other words, it refers to itself. In addition to this, there are three variables i,
j, k, which are followed by their data types and content.

The salient point to remember is that, since j is of another type, there is an href to id2.
The 'id2' is an id, i.e. a name for an xxx type, enclosing a parameter of type int, and
encompassing the value of 100. This is akin to the methodology used to store types in a
WSDL fle. Using the Encoded style, the information about types can be sent over. Send
an array over, and scrutinize the SOAP packet that is generated.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
&ystem.Web.ervices.-r)t)c)ls.)ap=pc'et()*1ttribute()+
public int abc(int i)
{
return i;
}
}

a.cs
public class zzz , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l
{
244025452.doc 202 od 274
public static v)i* 'ain()
{
zzz a " ne/ zzz();
int j " a.abc(<7);
ystem.#)ns)le.Write!ine(j);
}
&ystem.Web.ervices.-r)t)c)ls.)ap=pc'et()*1ttribute()+
public int abc(int i)
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
)bject&+ results " 4nv)5e("abc"6 ne/ )bject&<+{i});
return (int)results&7+;
}
}

SOAP re5uest
"soap::od' soap:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&*
"tns:abc*
"i ,si:t'pe%&,sd:int&*1-"1i*
"1tns:abc*
"1soap::od'*

(he last attri)ute that we touch uon is, the Soa3cMethod0ttri)ute. (his attri)ute )eha'es
in a *anner si*ilar to the attri)ute *entioned a)o'e, aart !ro* the encodin+ st&le, which is
>6ncoded> in this case. (hus, it is the S/01 a&load that carries the t&e in!or*ation and the
content. Most o! the exlanations rendered a)o'e, are e8uall& rele'ant in this context too.
1-
SOAP Uaults

We all have weaknesses, and SOAP is no exception. SOAP has certain inherent lacunae,
which are termed as SOAP fault codes. In all, there are four fault codes:
ClientFaultCode
ServerFaultCode
MustUndersatndCode
VersionMismatchFaultCode.

In this chapter, we shall discuss these fault codes threadbare, and delve upon details
such as- when and why these faults occur.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Oml;
&WeberviceMin*ing()+
public class zzz , Webervice
{
&Web'et()*()+
public v)i* abc()
{
t(r)/ ne/ )ap>xcepti)n("vijay"6 )ap>xcepti)n.#lientDault#)*e);
}
}

a.cs
class aaa
244025452.doc 203 od 274
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
try
{
a.abc();
}
catc( ( ystem.>xcepti)n e)
{
ystem.#)ns)le.Write!ine(e.:)tring());
}
}
}

3)bat
del V)e,e
del V)dll
wsdl aa)wsdl
csc 1t:librar' 333)cs
csc a)cs 1r:333)dll
a

Output
S'stem)Web)Services)Protocols)SoapE,ception:
S'stem)Web)Services)Protocols)SoapE,ception: vi2a'
at 333)abc>B

SOAP response
"soap::od'*
"soap:Uault*
".aultcode*soap:Client"1.aultcode*
".aultstring*S'stem)Web)Services)Protocols)SoapE,ception: vi2a' at
333)abc>B"1.aultstring*
"detail 1*
"1soap:Uault*
"1soap::od'*
The function abc in the asmx fle, throws an exception called SoapException. The
exception is generated by calling the SoapException constructor with two parameters:
The frst parameter is a message, which specifes the error that occurred.
The second parameter reveals the type of error that occurred.

The second parameter can have four possible values, out of which, we have specifed the
value of 'ClientFaultCode'.

The value of ClientFaultCode represents a SOAP fault code, and not an error. It mainly
signifes that the client SOAP payload is neither properly formatted, nor does it contain
all the requisite data. This could occur in situations where a user id and password are
expected, but are not contained in the SOAP packet. The client is also forewarned not to
rebound the same packet, since it contains errors. In the client program, the exception
is caught in 'e', which is an instance of the Exception class.

The SOAP trace depicts the SOAP response packet, which holds all the details related to
the exception. The exception thrown by the asmx fle is sent across the net, in the form
of a SOAP fault. The Body element is followed by the Fault element, which in turn, has a
child element called soap:Client. This child element reveals the exception code as
ClientFaultCode.
244025452.doc 204 od 274

The faultstring element frst specifes the name of the Exception, followed by the string
'vijay', which is supplied as the frst parameter to the SoapException constructor. This is
followed by the class and function names that have thrown the exception.

a.asmx
t(r)/ ne/ )ap>xcepti)n("vijay"6)ap>xcepti)n.erverDault#)*e);

SOAP response
"soap:Uault*
".aultcode*soap:Server"1.aultcode*
".aultstring*
S'stem)Web)Services)Protocols)SoapE,ception: vi2a' at 333)abc>B
"1.aultstring*
"detail 1*
"1soap:Uault*

The parameter value of ServerFaultCode notifes us that a fault has occurred on the
server, while the SOAP payload that was sent by the client, was being processed. In this
case, the error did not occur because the data carried by the SOAP packet is faulty. In
fact, the error could be attributed to any one of the myriad problems, such as- the
network being down, the server being busy, et al. The client is expected to retransmit
the same data, after just a short time gap.

The third fault code that we shall be analyzing is, the MustUndersatndCode. Since the
SOAP element carries an element with an attribute of MustUnderstand set to 1, the
server is unable to decipher the element on receiving it; and resultantly, it throws an
error. Thus, the exception is thrown by the server, and not by the client. Under these
circumstances, the client must not resend the payload, and even if it does, the
MustUnderstand attribute must be set to 0.

The last fault code that we shall examine is VersionMismatchFaultCode, which occurs
whenever an invalid namespace is sighted in the Envelope element. Using this fault
code, the server sends a signal to the client, indicating that an error has occurred.

The Invoke function has adequate potency to distinguish between a normal packet and
a Soap Fault. So, whenever it encounters a fault, it throws an exception.

a.asmx
t(r)/ ne/ ystem.>xcepti)n("vijay");

SOAP response
"soap:Uault*
".aultcode*
soap:Server
"1.aultcode*
".aultstring*
S'stem)Web)Services)Protocols)SoapE,ception: Server was unable to process re5uest)
///* S'stem)E,ception: vi2a' at 333)abc>B
"1.aultstring*
"detail 1*
"1soap:Uault*

244025452.doc 205 od 274
In the asmx fle, instead of a SoapException, it is a normal Exception that is thrown.
The .Net framework is extremely smart, in that, it converts this Exception into a
SoapException, and assigns the value of ServerFaultCode to the fault Code.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Oml;
&WeberviceMin*ing()+
public class zzz , Webervice
{
&Web'et()*()+
public Oml9)*e abc()
{
Oml0)cument * " ne/ Oml0)cument();
Oml9)*e n " *.#reate9)*e(Oml9)*e:ype.>lement6"s)nal"6 "mu5(i");
Oml9)*e c " *.#reate9)*e(Oml9)*e:ype.>lement6 "vijay"6 "(ell");
n.1ppen*#(il*(c);
Oml1ttribute a " *.#reate1ttribute("a<"6 "ba*");
a.Qalue " "g))*";
c.1ttributes.1ppen*(a);
return n;
}
}

SOAP response
"abc4esult*
"sonal ,mlns%&muk!i&*
"vi2a' n1:a1%&good& ,mlns:n1%&bad& ,mlns%&!ell& 1*
"1sonal*
"1abc4esult*

Many of you may consider XML to be a gobbledy-gook or a mere verbiage! Hence, we
have taken a slight detour into the realm of the XmlNode class.
In this program, we start by creating an empty XmlDocument object 'd', and then,
utilizing the CreateNode function, we create an element called 'sonal', within the
namespace called 'mukhi'.

The frst parameter of the CreateNode function specifes the type of entity that must be
created. The last parameter to this function refers to the namespace that the entity
generates. This function then returns an XmlNode object, which is stored in the object
n.

Thereafter, another node named 'c', containing the element 'vijay' in the namespace
'hell', is created. Since we want this element to be the child of the element 'sonal', the
AppendChild function of node 'n' is used, with the parameter of 'c'.

Then, the CreateAttribute function is used to associate attributes to the elements. This
function creates an attribute a1, and places it in the n1 namespace. It is for this reason
that the attribute a1 has a prefx n1, pointing to the uri named 'bad', which is our
second parameter. Every attribute requires a value. Therefore, the Value property of the
attribute class is initialized to the specifc value of 'good'.

244025452.doc 206 od 274
Finally, to associate this property with the node c, the collection property named
Attributes is used. The Append function of this collection adds the attribute. Since the
return value of the function abc is specifed as 'n', the abcResult element in the SOAP
element displays the entire XmlNode.

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Oml;
&WeberviceMin*ing()+
public class zzz , Webervice
{
&Web'et()*()+
public v)i* abc()
{
Oml0)cument * " ne/ Oml0)cument();
Oml9)*e n " *.#reate9)*e(Oml9)*e:ype.>lement6"s)nal"6 "mu5(i");
Oml9)*e c " *.#reate9)*e(Oml9)*e:ype.>lement6 "vijay"6 "(ell");
n.1ppen*#(il*(c);
Oml1ttribute a " *.#reate1ttribute("a<"6 "ba*");
a.Qalue " "g))*";
c.1ttributes.1ppen*(a);
Oml0)cument *< " ne/ Oml0)cument();
Oml9)*e n< " *<.#reate9)*e(Oml9)*e:ype.>lement6"s)nal<"6 "mu5(i<");
Oml9)*e c< " *<.#reate9)*e(Oml9)*e:ype.>lement6 "vijayB" 6 "");
n<.1ppen*#(il*(c<);
Oml0)cument *@ " ne/ Oml0)cument();
Oml9)*e n@ " *@.#reate9)*e(Oml9)*e:ype.>lement6"s)nal@"6 "mu5(i@");
Oml9)*e &+ m " ne/ Oml9)*e&@+;
m&7+ " n<;
m&<+ " n@;
ystem.>xcepti)n e " ne/ ystem.>xcepti)n("(a(a");
t(r)/ ne/ )ap>xcepti)n("vijay"6)ap>xcepti)n.erverDault#)*e 6"s)nal"6 n 6 m 6 e);
}
}

SOAP response
"soap::od'*
/ "soap:Uault*
".aultcode*soap:Server"1.aultcode*
".aultstring*S'stem)Web)Services)Protocols)SoapE,ception: vi2a' ///*
S'stem)E,ception: !a!a at 333)abc>B"1.aultstring*
".aultactor*sonal"1.aultactor*
/ "sonal ,mlns%&muk!i&*
"vi2a' n1:a1%&good& ,mlns:n1%&bad& ,mlns%&!ell& 1*
"1sonal*
/ "sonal1 ,mlns%&muk!i1&*
"vi2a'6 ,mlns%&& 1*
"1sonal1*
"sonal7 ,mlns%&muk!i7& 1*
"1soap:Uault*
"1soap::od'*

Using the same analogy, we frst create a simple XmlNode named 'n'. Thereafter, we
create two more XmlNodes named 'n1' and 'n2'. One child node is added to the node n1,
whereas, no child nodes are appended to the node n2. Once this is done, an array of
XmlNodes named 'm', with a size of 2 is created, and its two members are initialised to
n1 and n2, respectively.
244025452.doc 207 od 274

The SoapException that gets thrown at this stage, has six parameters:
The frst parameter that contains the value of 'vijay', is the name of the message,
which eventually gets converted to the fault string.
The second parameter is the fault code named SoapException.ServerFaultCode.
The third parameter is the Actor. The element is called 'faultactor', and the value
assigned is 'sonal'. The actor is the cause of the fault. Normally, it should contain the
line number or some other information, which helps in identifying the error.
The fourth parameter is the XmlNode object. This object must contain the detailed
specifcs of the error that occurred. Here, the actual lines of code or variables that
caused the error, may be specifed. Since an XmlNode is required, supplying an entire
formatted XML document would also sufce.
The ffth parameter is an array of XmlNodes, which can be initialized to any content
that we desire. Normally, the contents of the body element are embodied in the
parameters discussed so far. However, for this parameter, the specifcs not related to the
body, are laid down. Thus, we encounter 'sonal1' and 'sonal2' at the end of the Body
element. The 'detail' tag is missing at this stage.
The sixth parameter is the Exception, whose constructor value gets merged into the
fault string.

a.cs
class aaa
{
public static v)i* 'ain()
{
zzz a" ne/ zzz();
try
{
a.abc();
}
catc( ( ystem.Web.ervices.-r)t)c)ls.)ap>xcepti)n e)
{
ystem.#)ns)le.Write!ine(e.1ct)r);
ystem.#)ns)le.Write!ine(e.#)*e);
iK ( e.0etail "" null)
ystem.#)ns)le.Write!ine("0etail is null");
ystem.#)ns)le.Write!ine(e.;t(er>lements&7+.4nnerOml);
ystem.#)ns)le.Write!ine(e.;t(er>lements&<+.4nnerOml);
ystem.#)ns)le.Write!ine(e.:)tring());
}
}
}

Output
sonal
!ttp:11sc!emas),mlsoap)org1soap1envelope1:Server
Eetail is null
"vi2a' n1:a1%&good& ,mlns:n1%&bad& ,mlns%&!ell& 1*
"vi2a'6 ,mlns%&& 1*
S'stem)Web)Services)Protocols)Soap;eaderE,ception:
S'stem)Web)Services)Protocols)SoapE,ception: vi2a' ///* S'stem)E,ception: !a!a
at 333)abc>B

The asmx fle remains unaltered for this program. Here, we have attempted to display all
the members of the SoapException object 'e'. The 'Actor' property displays the value of
'sonal', followed by the Fault code member Code. The value of Code is not merely
'Server', but is preceded by a lengthy URI and a colon.
244025452.doc 208 od 274

This evinces the fact that the SOAP Fault payload content is copied into properties,
such as Actor, by the Invoke function. However, for reasons unknown to us, the 'detail'
property does not get flled up at all. Since the 'if' statement is true, the value of the
property is not displayed; instead, a text string is displayed.

The OtherElements property is an array of 2 XmlNodes. Thus, we use the InnerXml
property to display the entire node, using an index element. As was the case earlier, the
Exception carries the strings of 'vijay' and 'haha'. Thus, all the data that we enclose and
dispatch in the Exception, is made available to the client.

a.asmx
t(r)/ ne/ )ap.ea*er>xcepti)n("vijay"6)ap>xcepti)n.erverDault#)*e 6"s)nal"6 m 6 e);

SOAP response
"soap:Uault*
".aultcode*soap:Server"1.aultcode*
".aultstring*S'stem)Web)Services)Protocols)Soap;eaderE,ception: vi2a' ///*
S'stem)E,ception: !a!a at 333)abc>B"1.aultstring*
"1soap:Uault*

"hene'er an 6xcetion occurs within the S/01 headers, a Soa@eader6xcetion should )e
thrown. 6'er&thin+ re*ains unchan+ed, )ut !or the 6xcetion na*e, which +ets altered. 0lso,
the S/01 resonse disla&s the chan+es !ro* Soa6xcetion to Soa@eader6xcetion in the
6xcetion.
11
ASP)(et WebServices

The very purpose of this chapter is to introduce the use of complex regular expressions,
to specify the content that should be selected in an HTML fle. People have invested
millions of dollars in building the html infrastructure. Hence, it cannot be simply
wished away.

An html fle could contain stock prices, which needs to be extracted with minimal efort.
Besides, there are web sites like Barnes and Noble or Amazon, which run a bookshop
online.

These servers contains a script written in any scripting language, which accepts a
parameter, such as- an ISBN number, and retrieves a book that tallies with this
number, from its database. Thus, it is essential to command the ability to pass
parameters to a program, which is running on the web server. The custom extensions
are one of the various ways of using the already existent infrastructure.

This modus operandi is termed as screen or html scrapping, wherein, the contents of
an html fle are accessed, and the values are extracted as per our bidding.

A Web site can now be converted into a Web Service by employing the extant logic and
data. Thus, the knowledge of ASP.NET is put to efective use, thereby, evading the
compulsion to dabble around with protocols of HTTP.
244025452.doc 209 od 274

a.aspx
<(tml%
<script language""#$" runat""server"%
public v)i* -ageT!)a*(;bject )6 >vent1rgs >)
{
try
{
zzz m" ne/ zzz();
abc<'atc(es n " m.abc<();
a<.4nner.tml " n.aa;
a@.4nner.tml " n.cc;
}
catc( (>xcepti)n e)
{
aB.4nner.tml " ">rr)r " C e.:)tring();
}
}
<3script%
<K)rm runat""server"%
<span i*""a<" runat""server"3%
<p%
<span i*""a@" runat""server"3%
<p%
<span i*""aB" runat""server"3%
<3K)rm%
<3b)*y%
<3(tml%

aa./s*l
<Nxml versi)n""<.7"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3<JJJ3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema target9amespace""(ttp,33tempuri.)rg3" attributeD)rm0eKault""PualiKie*"
elementD)rm0eKault""PualiKie*"%
<s,element name""s<" type""s,string" nullable""true"3%
<3s,sc(ema%
<3types%
<message name""i<"3%
<message name"")<"%
<part name""M)*y" element""s7,s<"3%
<3message%
<p)rt:ype name""p<"%
<)perati)n name""abc<"%
<input message""s7,i<"3%
<)utput message""s7,)<"3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""b<" type""s7,p<"%
<(ttp,bin*ing verb""?>:"3%
<)perati)n name""abc<"%
<(ttp,)perati)n l)cati)n""3a.(tml"3%
<input%
<(ttp,url>nc)*e*3%
<3input%
<)utput%
<text xmlns""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"%
<matc( name"UaaU pattern"UbbWgt;(.RN)Wlt;U3%
244025452.doc 210 od 274
<matc( name"UccU pattern"U**Wgt;(.RN)Wlt;U3%
<3text%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt bin*ing""s7,b<"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

zzz.cs
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class zzz , ystem.Web.ervices.-r)t)c)ls..ttp?et#lient-r)t)c)l {
public zzz()
{
t(is.2rl " "(ttp,33l)cal()st";
}
&ystem.Web.ervices.-r)t)c)ls..ttp'et()*1ttribute
(type)K(ystem.Web.ervices.-r)t)c)ls.:ext=eturn=ea*er)6
type)K(ystem.Web.ervices.-r)t)c)ls.2rl-arameterWriter))+
public abc<'atc(es abc<() {
return ((abc<'atc(es)(t(is.4nv)5e("abc<"6 (t(is.2rl C "3a.(tml")6 ne/ )bject&7+)));
}
}
public class abc<'atc(es
{
&ystem.Web.ervices.-r)t)c)ls.'atc(1ttribute ("bb%(.RN)<")+
public string aa;
&ystem.Web.ervices.-r)t)c)ls.'atc(1ttribute("**%(.RN)<")+
public string cc;
}

a.(tml
<.:'!%
<.>10%
<bb%vijay<3bb%
<3.>10%
<M;0S%
<**%'u5(i<3**%
<3M;0S%
<3.:'!%

a)bat
del V)dll
del 333)cs
wsdl aa)wsdl
csc 1t:librar' 333)cs

Output
Qi2a'
Muk!i

When the aspx fle is loaded in the browser, the code specifed in the Page_Load
function is called frst. Here, we frst create an object 'm', as an instance of class zzz.
This class is present in the dll, which gets created in the bin folder. Once the object has
244025452.doc 211 od 274
been created, we call a function named abc1, from this class. The return value of this
function, which is an abc1Matches object, is stored in the object 'n'.

The abc1Matches class is present in the proxy dll. It contains two members named aa
and cc, both of type string. The function abc1 frst initializes the two members, and
thereafter, returns this object. The values contained in them are then displayed, using
the two spans, viz.a1 and a2. If an error occurs, the text of the error is displayed, using
the span a3.

If you attempt to load the aspx fle without creating the dll, an error would be generated.
To create these two classes in the dll, the presence of a WSDL fle is inescapable. So, we
create the wsdl fle manually, and then, run the WSDL program on it. Once the .cs fle
is created, the library is formed, by employing the services of the csharp compiler.

As usual, the wsdl fle has the root tag defnitions embedded in it, containing countless
namespace prefxes. Then, we encounter the type element, which simply defnes an
element s1. Its type belongs to the string type in the XML schema world. Since this is
our second rendezvous with the wsdl fle, we will elude delving into the minute details,
for instance- the types referring to a schema document, et al. Next, we fnd two
messages:
i1 - It is an empty message.
o1 - It has one part called Body, which has the likeness to an element of a string
type.

Messages use the portType element. Notwithstanding the fact that the messages are
blank, the element must be specifed. The part name is called Body, although any other
name would also have sufced, since it is not referred to anywhere in the program. This
message contains a string text. Had we so desired, we could have completely omitted the
types section; and instead, we could have inserted the part element with the following:

<part type""s,string"3%

However, this is an allusive way or a convoluted way of stating the same thing.
Messages are the foot soldiers for the portType, and they defne an operation. Thus, the
message element called p1 defnes an operation abc1, which is to be performed.

An operation expects an input and an output type. The messages assign the contents to
these types. The message i1 assigns a value of 'null' to the input type, whereas, the
message o1 assigns a string to the output type. The binding b1 accepts the details from
a portType, and it conjoins the verb GET to it. The verb cannot have arbitrary names
like 'vijay', POST, PUT, etc.

Assigning an incorrect value to the verb will bring the WSDL to a grinding halt. As a
consequence of this, the zzz.cs fle that gets generated, would be erroneous.

The operation element specifes the name of the html fle that we want to work with.
The / symbol is of utmost signifcance, since it indicates that, the fle will be found in
the root of the web server's directory, i.e. at c:\inetpub\wwwroot. The input is specifed
as http:urlencoded. As a result of this, all values that are sent across, shall be URL
encoded. It is the http specifcation, which fnally determines the url.
244025452.doc 212 od 274

Thus, if we have two textboxes named a1 and a2, containing 'vijay' and 'mukhi'
respectively, the URL shall contain the following: a1=vijay&a2=mukhi.

The vital component of the above exercise is the output element. The text element
specifes the default namespace for the elements that follow, and it is well nigh
impossible to mutate these URIs. They are hard-wired into the WSDL program. However,
when we go to the above URI's, we do not chance upon anything of interest. In this case,
the URI informs us that there is no valid page at the Microsoft site.

Next, we come across the two match elements, named aa and cc. These are the two
elements that are referred to, in the aspx fle. We will elucidate the pattern in due
course.

Finally, there is a service called zzz, which is the name of our class. It is followed by the
port bindings, which specify the newly created binding known as b1. The address of
a.html is also present on the server, i.e. localhost. When we run the WSDL program on
this wsdl fle, it will result in the creation of a fle called zzz.cs, embodying a class called
zzz.

The above WSDL fle is grossly deviant from what we have utilized so far, since SOAP is
conspicuous by its absence right now. The class zzz is derived from the class
HttpGetClientProtocol. The Url property does not specify either the asmx fle or any
other fle; it only contains the machine name.

In the proxy, the attribute of HttpMethodAttribute that has been specifed, has never
been sighted so far, since the client had been using SOAP. This attribute is pressed into
action only when clients begin to use the HTTP-GET or HTTP-POST methods. This
attribute is responsible for determining the following:
The serialization that would occur, for parameters that are sent across the wire to a
WebService.
The manner in which the result that has been returned, would be received.

Most of these attribute classes cannot be inherited, since they are sealed classes. The
frst parameter to the constructor is a Type, which embodies a class that is used to
deserialize the response from the web service.

There is no help or documentation available for the class TextReturnReader. Hence, we
are not in a position to elaborate on it. The second parameter in the attribute is the
UrlParameterWriter class, which serializes the parameters for the web service. In this
case too, we feel stranded, since the help pages for this class appear to be either stolen,
or misplaced. There could also be a distant possibility that Microsoft never got around
to fabricating them.

The attribute applies to the function abc1, which corresponds with the name of the
operation. The return type consists of the name of the function 'abc1', with the word
'Matches' appended to it. The return value, i.e. class abc1Matches, contains two string
variables, viz. aa and cc. This is because, there exist two match elements with identical
names.
244025452.doc 213 od 274

The fucntion abc1 then calls the familiar Invoke function, with the frst parameter as
abc1. The second parameter is a string, which fnally crystallizes into
http://localhost/a.html. The third parameter indicates that no parameters exist.

When abc is called, it returns an object, which looks like 'abc1Matches'. The two spans
are initialized, with the help of these two variables. In the class abc1Matches, each of
the variables contains an attribute of MatchAttribute. As is evident from the name, the
attributes that are to be matched, have been specifed. The singular parameter to the
constructor is a regular expression, which locates a string in the html fle, a.html.

The html fle contains two tags named bb and dd. The two variables in the abc1Matches
object, i.e. aa and cc, are assigned the values 'vijay' and 'Mukhi', respectively. This
happens since these words are enclosed in the tags 'bb' and 'dd', correspondingly.
Finally, these variables are displayed in the span elements.

Thus, the contents placed between the tags in an html fle are picked up, merely by
creating a WSDL fle with a match element.

HE 4e5uest
HE 1a)!tml ;P11)1
<ser/Agent Mo3illa1=)- >compatible? MSIE @)-? MS Web Services Client Protocol
1)-)7A1=)1@B
Connection: Ceep/Alive
;ost:local!ost

HE 4esponse
;P11)1 7-- OC
Server: Microso.t/IIS1D)-
Eate: UriF 1A Oct 7- -1 -7:D=:-I HM
Content/'pe: te,t1!tml
Accept/4anges: b'tes
9ast/ModiPed: WedF 1I Oct 7--1 -A:==:7- HM
Eag: &-.7@7=b.-D@c11:Aca&
Content/9engt!: 06
";M9*
";EAE*
"bb*vi2a'"1bb*
"1;EAE*
":OEO*)
"dd*Muk!i"1dd*)
"1:OEO*
"1;M9*

aa./s*l
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st,8787" 3%

In order to ameliorate our understanding of the above example, we efect a minute
alteration to the WSDL fle. This is done by way of modifying the port number to 8080 in
the address element; subsequent to which, we run the fle a.bat. The SOAP trace
program is set to 'unformatted trace', since we are interested in deciphering the HTTP
headers, which are transported to and fro.

The formatted option only gives the SOAP payload, which does not get generated in the
above case. The trace, very clearly and cogently reveals that the Get request asks for the
244025452.doc 214 od 274
a.html fle from the server. The web server concedes to this request, and in doing so,
returns the entire HTML fle. The SOAP data is nowhere in sight at the moment!

When the Invoke function scrutinizes the parameters, it awakens to the fact that, this
function is distinct from the Invoke function that used to get called earlier. It is privy to
the fact that it has to pick up the html fle using the HTTP protocol, and that, an object
has to be returned in another object, which is an instance of abc1Matches.

Now, in order to assign values to the two variables 'aa' and 'cc', the pattern is matched
in the html fle. The variable 'aa' contains a pattern that begins with the name of tag
'bb'. This tag is followed by the > and < symbols, which enclose a pattern that is in
accordance with the rules governing a regular expression. We will not sermonize on the
topic of regular expressions. We shall only divulge the following:
The . symbol matches a single character.
The * symbol matches one or more characters.
If we remove the quantifer?, all characters will be matched, because the ? symbol
chooses the least match.
In the WSDL fle, the pattern attribute is written as bb&gt;(.*?)&lt;.

We commence with the tag name 'bb'. Since we cannot insert the < and > symbols in an
XML fle, as these are reserved symbols, we use the more elaborate form, i.e. &gt;. The
open and close symbols are part and parcel of the syntax. An error will be generated if
they are dispensed with. The actual pattern eventually matches the smallest content in
the tag 'bb'. The value 'vijay' is then supplied to the variable aa.

The pattern matching is fashioned by the Invoke function, after it receives the html fle.
In this manner, we can access the content of any tag in an html fle, with the least
amount of efort.

a.(tml
<bb%vijay is g))*<3bb%
<bb%vijay<<3bb%
<***%'u5(i<<3***%
<**%'u5(i<3**%

Output
vi2a' is good
Muk!i1

The a.html fle is now modifed to encompass only the required tags. All the other tags,
like Body, can be eradicated with efortless ease.

The fle now contains two occurrences of the tag bb. However, the output displays only
the frst occurrence of the tag. Resorting to the same analogy, the second tag name has
been modifed from dd to ddd. Furthermore, treading close on the heels of ddd, there
subsists another tag named dd. However, the content of ddd is displayed, since it works
on the basis of 'frst come frst served'.

a.aspx
<%@ -age !anguage""c$" %%
<%@ 4mp)rt 9amespace""ystem.9et" %%
244025452.doc 215 od 274
<cript runat""server"%
public v)i* abc(;bject s6 >vent1rgs e)
{
zzz a " ne/ zzz();
abc<'atc(es m;
m " a.abc<(t<.:ext6"Mye");
l<.:ext " m.aa;
}
<3cript%
<asp,!abel i*"l< runat""server" 3%
<3K)nt%<3-%<D;9: Kace"arial%<M%
<-%
<K)rm runat""server"%
<asp,:extM)x i*"t< runat""server" 3%<-%
<asp,Mutt)n runat""server" :ext""#lic5" ;n#lic5""abc" 3%
<3K)rm%

a.(tml
<.:'!%
<:4:!>%Qijay.c)m,name,O'! .9>:<3:4:!>%
<3(tml%

aa./s*l
<message name""i<"%
<part name""mu5(i" type""s,string"3%
<part name""s)nal" type""s,string"3%
<3message%

<text xmlns""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"%
<matc( name""aa" pattern"":4:!>Wgt;vijay.c)m.name.(.RN)Wlt;" ign)re#ase""true"3%
<3text%

zzz.cs
public abc<'atc(es abc<(string mu5(i6 string s)nal)
{
return ((abc<'atc(es)(t(is.4nv)5e("abc<"6 (t(is.2rl C "3a.(tml")6 ne/ )bject&+ {mu5(i6 s)nal})));
}
public class abc<'atc(es {
&ystem.Web.ervices.-r)t)c)ls.'atc(1ttribute(":4:!>%vijay.c)m.name.(.RN)<"6 4gn)re#ase"true)+
public string aa;
}

SOAP re5uest
HE 1a)!tml+muk!i%16Ysonal%:'e ;P 1)1

Output
8M9)(et

In the above aspx fle, the function abc creates the zzz object as before, with one
exception, i.e. the abc1 function accepts two parameters, both of which are strings.
Therefore, in the wsdl fle, we must incorporate a mechanism of specifying parameters
to the function. To facilitate this, we carry out the requisite revisions to the WSDL fle.

In the earlier program, the message named i1 was devoid of any content or parts. But
now, we inset two parts in the message, viz. 'mukhi' and 'sonal'. In a GET method, these
parts merely comport themselves as parameters to the operation, which consumes this
part. The operation abc1 then simply creates a function abc1, which accepts two string
parameters, 'vijay' and 'mukhi'.

244025452.doc 216 od 274
The second change incorporated in the wsdl fle relates to the match element. Here, the
pattern attribute is specifed in the form of a Regular Expression, which would be
employed to extract data. We intend to extract data contained in the tag TITLE, which
has static or boilerplate text in the following format:
the word 'vijay',
followed by any single character,
followed by the word 'com',
followed by any character,
followed by the word 'name',
and fnally, followed by any character.

Thus, the resultant pattern that is specifed is as follows:

TITLE&gt;vijay.com.name.(.*?)&lt
Thus, the variable aa would contain the text that follows the pattern, upto the end of
the tag. There are books aplenty on the topic of expressions. Therefore, we have decided
to refrain from developing it any further.

Since the extra attribute ignoreCase is 'true', the casing will be ignored completely.
Thus, it is of no consequence whether we specify 'vijay' in capitals or in small letters in
the html fle.

In the zzz.cs fle, the function abc1 contains two string parameters, viz. 'mukhi' and
'sonal'. Further, the abc1Matches class copies not only the regular expression, but also
the attributes. The SOAP request simply appends the values of the variables 'mukhi'
and 'vijay' to the URL, as though they were names of html elements. The variables are
separated by the & symbol, in accordance with the rules of URL encoding.

b.aspx
<%@ -age !anguage""c$" %%
<cript runat""server"%
public v)i* -ageT!)a*(;bject s6 >vent1rgs e)
{
iK ( =ePuest&"mu5(i"+ "" "<B" )
=esp)nse.Write("<.:'!%<:4:!>%Qijay.c)m,name,O'! .9>:<<3:4:!>%<3.:'!%");
else
=esp)nse.Write("<.:'!%<:4:!>%Qijay.c)m,name,O'! .9>:@<3:4:!>%<3.:'!%");
}
<3cript%

aa./s*l
<(ttp,bin*ing verb""?>:"3%
<)perati)n name""abc<"%
<(ttp,)perati)n l)cati)n""3b.aspx"3%
<input%

We have made a singular change to our aa.wsdl fle. The name of the fle, or location in
the operation element, has been changed from a.html to b.aspx. This location could be
any one of these- an aspx fle or a pl (PERL) program, or any other script fle.
The fle b.aspx will now send across a diferent TITLE content, depending upon the
contents of the parameter named 'mukhi'.

244025452.doc 217 od 274
Now, if we run the program by typing 13 into the textbox, the fle b.aspx, will be called.
It is for the frst time that the Request, with the name of the parameter 'mukhi' enclosed
within square brackets [ ], representing the indexer, will hold a value of 13.

Hence, the 'if' statement will transmit the HTML fle containing NET1. In the second
round, the result will contain NET2, which would then be sent across.

a.aspx
<%@ -age !anguage""#$" 0ebug""true" %%
<%@ 4mp)rt 9amespace""mmm"%%
<%@ 4mp)rt 9amespace""ystem.Web.ervices.-r)t)c)ls" %%
<script runat"server%
public v)i* -ageT!)a*() {
s<.4nner.tml " "";
s@.4nner.tml " "";
}
public v)i* abc(;bject sen*er6 >vent1rgs e)
{
sss s " ne/ sss();
aaa a " ne/ aaa();
a.2ser " u.Qalue;
a.-ass/)r* " p.Qalue;
s.a< " a;
try
{
string r " s.abc();
s<.4nner.tml " r;
}
catc( ()ap>xcepti)n s))
{
s@.4nner.tml " s).'essage;
}
}
<3script%
<K)rm runat"server%
2sername,
<input type"text i*"u runat"server 3%
<M=%
-ass/)r*,
<input type"text i*"p runat"server 3%
<-%
<input type"submit runat"server ;nerver#lic5""abc" value""#lic5" 3%
<3K)rm%
<span i*"s< runat"server 3%
<span i*"s@ runat"server 3%

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""e<"%
<s,c)mplex:ype 3%
<3s,element%
244025452.doc 218 od 274
<s,element name""abc=esp)nse"%
<s,c)mplex:ype%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""abc=esult" nillable""true" type""s,string" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""a<" type""s7,aaa" 3%
<s,c)mplex:ype name""aaa"%
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""2ser" nillable""true" type""s,string" 3%
<s,element min;ccurs""<" max;ccurs""<" name""-ass/)r*" nillable""true" type""s,string" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,sc(ema%
<3types%
<message name""i<"%
<part name""parameters" element""s7,e<" 3%
<3message%
<message name"")<"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<message name""Qa"%
<part name""aaa" element""s7,a<" 3%
<3message%
<p)rt:ype name""pt"%
<)perati)n name""abc"%
<input message""s7,i<" 3%
<)utput message""s7,)<" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""b<" type""s7,pt"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<s)ap,(ea*er n<,rePuire*""true" message""s7,Qa" part""aaa" use""literal"
xmlns,n<""(ttp,33sc(emas.xmls)ap.)rg3/s*l3" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""sss"%
<p)rt bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873PPPs3a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

sss.cs
namespace mmm
{
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame""b<"6
9amespace""(ttp,33tempuri.)rg3")+
public class sss , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
244025452.doc 219 od 274
public aaa a<;
public sss()
{
t(is.2rl " "(ttp,33l)cal()st,87873PPPs3a.asmx";
}
&ystem.Web.ervices.-r)t)c)ls.)ap.ea*er1ttribute("a<")+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc"6
=ePuest>lement9ame""e<"6 2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.!iteral6
-arametertyle"ystem.Web.ervices.-r)t)c)ls.)ap-arametertyle.Wrappe*)+
public string abc() {
)bject&+ results " t(is.4nv)5e("abc"6 ne/ )bject&7+);
return ((string)(results&7+));
}
}
&ystem.Oml.erializati)n.Oml=))t1ttribute("a<"6 9amespace""(ttp,33tempuri.)rg3"6
4s9ullable"Kalse)+
public class aaa , )ap.ea*er {
public string 2ser;
public string -ass/)r*;
}
}

#lient a.bat
*el R.*ll
*el R.cs
/s*l aa./s*l 3namespace,mmm
csc.exe 3t,library sss.cs
c)py sss.*ll .Fbin

/eb.c)nKig
<c)nKigurati)n%
<system./eb%
<c)mpilati)n%
<assemblies%
<a** assembly""ystem.ecurity"3%
<3assemblies%
<3c)mpilati)n%
<(ttp')*ules%
<a** name""/<" type""yyy6 zzz" 3%
<3(ttp')*ules%
<3system./eb%
<3c)nKigurati)n%

gl)bal.asax
<%@ !anguage""#$" %%
<%@ 4mp)rt 9amespace""ystem.ecurity.-rincipal" %%
<%@ 4mp)rt 9amespace""ystem.4;" %%
<script runat"server%
public v)i* /<T;n1ut(enticate()bject )6 eee e) {
abc("gl)bal.asax /<T;n1ut(enticate");
iK ((e.2s "" "vijay") WW (e.-ass "" "mu5(i"))
{
string &+ s " ne/ string&<+;
s&7+ " "#ust)mer";
e.PPP(s);
}
}
public v)i* abc(string s) {
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
244025452.doc 220 od 274
}
<3script%

a.asmx
<%@ Webervice !anguage""#$" #lass""ttt" %%
using ystem;
using ystem.4;;
using ystem.Web.ervices;
using ystem.Web.ervices.-r)t)c)ls;
public class a< , )ap.ea*er {
public string 2ser;
public string -ass/)r*;
}
public class ttt , Webervice {
public a< a;
&Web'et()*+
&)ap.ea*er("a")+
public string abc()
{
abc("asmx abc");
iK (2ser.4s4n=)le("#ust)mer"))
return "=)le cust)mer";
iK (2ser.4*entity.4s1ut(enticate*)
return "Qali* user";
return "9)t 1ut(enticate*";
}
public v)i* abc(string s) {
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
}

zzz.cs
using ystem;
using ystem.Web;
using ystem.ecurity.-rincipal;
using ystem.4;;
using ystem.Oml;
using ystem.Oml.O-at(;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.#)llecti)ns.pecialize*;
public class eee, >vent1rgs {
4-rincipal pu;
.ttp#)ntext c;
string u;
string p;
public eee(.ttp#)ntext c)6 string us6 string pass)
{
abc("eee <");
c " c);
u " us;
p " pass;
}
public .ttp#)ntext #)nt
{
get {
abc("#)ntext ");
return c;
}
}
244025452.doc 221 od 274
public 4-rincipal -rin
{
get {
abc("get -rincipal ");
return pu;
}
set {
abc("set -rincipal ");
pu " value;
}
}
public v)i* PPP(string&+ r)les)
{
abc("PPP <");
?eneric4*entity i " ne/ ?eneric4*entity(2s);
-rin " ne/ ?eneric-rincipal (i6 r)les);
}
public string 2s
{
get {
abc("get 2ser ");
return u;
}
set {
abc("set 2ser ");
u " value;
}
}
public string -ass
{
get
{
abc("get -ass/)r*");
return p;
}
set
{
abc("set -ass/)r*");
p " value;
}
}
public v)i* abc(string s)
{
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
}
public *elegate v)i* ***(;bject sen*er6 eee e);
public seale* class yyy , 4.ttp')*ule
{
*** e " null;
public event *** 1ut(enticate
{
a**
{
abc("yyy 1ut(enticate 1**");
e C" value;
}
rem)ve
{
244025452.doc 222 od 274
e G" value;
abc("I");
}
}
public v)i* 4nit(.ttp1pplicati)n a)
{
abc("yyy 4nit");
a.1ut(enticate=ePuest C" ne/ >vent.an*ler(xyz);
}
v)i* xyz(;bject )6 >vent1rgs ev)
{
abc("yyy xyz");
.ttp1pplicati)n a " (.ttp1pplicati)n));
.ttp#)ntext c) " a.#)ntext;
tream s " c).=ePuest.4nputtream;
l)ng p " s.-)siti)n;
abc(p.:)tring());
string sB " "";
int i;
9ameQalue#)llecti)n c;
.ttp=ePuest r " c).=ePuest;
c"r..ea*ers;
string&+ s< " c.1llLeys;
abc(s<.!engt(.:)tring());
K)r (i " 7; i<s<.!engt(; iCC)
{
sB " "Ley, " C s<&i+ C """;
string&+ s@"c.?etQalues(s<&i+);
abc(sB C s@&7+);
}
iK (c).=ePuest.erverQariables&".::-T;1-1#:4;9"+ "" null)
return;
Oml0)cument *< " ne/ Oml0)cument();
string u;
string pa;
try
{
*<.!)a*(s);
s.-)siti)n " p;
*<.ave("#,FFb.txt");
s.-)siti)n " p;
Oml9)*e!ist n) " *<.?et>lementsMy:ag9ame("2ser");
Oml9)*e n " n)&7+;
u " n.4nner:ext;
pa " *<.?et>lementsMy:ag9ame("-ass/)r*").4tem(7).4nner:ext;
abc(u C " " C pa);
}
catc( (>xcepti)n ee)
{
s.-)siti)n " p;
Oml[ualiKie*9ame na " ne/ Oml[ualiKie*9ame(")nal");
)ap>xcepti)n s) " ne/ )ap>xcepti)n( ">rr)r in ;1-"6 na6 ee);
t(r)/ s);
}
eee e<;
e< " ne/ eee(c)6 u 6 pa);
e(t(is6 e<);
iK (e<.2s \" null)
e<.#)nt.2ser " e<.-rin;
return;
}
public v)i* abc(string s)
{
244025452.doc 223 od 274
Diletream Ks " ne/ Diletream("c,FFa.txt"6 Dile')*e.1ppen*6 Dile1ccess.Write);
treamWriter / " ne/ treamWriter(Ks);
/.Write!ine(s);
/.Dlus(();
/.#l)se();
}
public v)i* 0isp)se()
{
}
}

erver a.bat
csc 3t,library zzz.cs
c)py zzz.*ll .Fbin

a.txt
yyy 4nit
yyy 1ut(enticate 1**
yyy xyz
7
I
Ley, #)ntentG!engt("HH@
Ley, #)ntentG:ype"text3xml; c(arset"utKG8
Ley, >xpect"<77Gc)ntinue
Ley, .)st"l)cal()st
Ley, 2serG1gent"')zilla3H.7 (c)mpatible; '4> I.7; ' Web ervices #lient -r)t)c)l <.7.@J<H.<I)
Ley, ;1-1cti)n""(ttp,33tempuri.)rg3abc"
vijay mu5(i
eee <
gl)bal.asax /<T;n1ut(enticate
get 2ser
get -ass/)r*
PPP <
get 2ser
set -rincipal
get 2ser
#)ntext
get -rincipal
asmx abc
yyy xyz
vijay mu5(i<<<
eee <
gl)bal.asax /<T;n1ut(enticate
get 2ser
get -ass/)r*
get 2ser
#)ntext
get -rincipal
asmx abc

b.txt
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<s)ap,>nvel)pe xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3"
xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<s)ap,.ea*er%
<a< xmlns""(ttp,33tempuri.)rg3"%
<2ser%vijay<32ser%
<-ass/)r*%mu5(i<3-ass/)r*%
<3a<%
<3s)ap,.ea*er%
<s)ap,M)*y%
<e< xmlns""(ttp,33tempuri.)rg3" 3%
244025452.doc 224 od 274
<3s)ap,M)*y%
<3s)ap,>nvel)pe%

SOAP re5uest
"+,ml version%&1)-& encoding%&ut./0& +*
/ "soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
/ "soap:;eader*
/ "a1 ,mlns%&!ttp:11tempuri)org1&*
"<ser*vi2a'"1<ser*
"Password*muk!i"1Password*
"1a1*
"1soap:;eader*
/ "soap::od'*
"e1 ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*
"1soap:Envelope*

SOAP response
"+,ml version%&1)-& encoding%&ut./0& +*
/ "soap:Envelope ,mlns:soap%&!ttp:11sc!emas),mlsoap)org1soap1envelope1&
,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema&*
/ "soap::od'*
/ "abc4esponse ,mlns%&!ttp:11tempuri)org1&*
"abc4esult*4ole Customer"1abc4esult*
"1abc4esponse*
"1soap::od'*
"1soap:Envelope*

This is our single largest program so far, which is a reason enough for you to follow our
instructions to the T. Firstly, create a folder qqq in the root, and then within it, create
two more folders named 'client' and 'server'. Stay put! Now, you need to create a bin
folder within each of the 'client' and 'server' subdirectories.

After having created the required physical subdirectories, we then have to create two
virtual directories:
qqqc - it points to folder c:\qqq\client
qqqs - it points to c:\qqq\server

The screens displayed below would facilitate the creation of these virtual directories.

244025452.doc 225 od 274
Screen 11.1

Screen 11.2

244025452.doc 226 od 274
Screen 11.3 Screen 11.4

Screen 11.5 Screen 11.6

244025452.doc 227 od 274
Screen 11.7 Screen 11.8

Then, write the above a.aspx program in the c:\qqq\client subdirectory. First of all, we
set the 'debug' mode to 'true', in order that the error messages, if any, become visible.

Almost the entire code is placed in namespaces. Here, the namespace mmm contains
the code. Hence, we import a namespace called mmm. Finally, at the end of the aspx
fle, exist two spans:
The frst called s1, which displays the return value.
The second s2, which displays the error message, if any.

The Page_Load function gets called immediately, prior to the page being sent across. It
merely initializes the InnerHtml property of the spans to 'null', so that they do not
display anything.

Then, there exist two textboxes named 'u' and 'p', together with a button. The user is
required to enter the username and password, and then, click on the button. When the
button is clicked, the function abc gets called. This function gets executed on the server,
and creates two objects:
One is an instance of the class sss.
The other is an instance of the class aaa.

As is evident, these classes are user-defned classes that are present in a dll, which is
placed in the bin folder, within the client subdirectory. The aaa class has two members
named User and Password, which are initialized to the values entered in the textboxes
'u' and 'p'. Thereafter, the 'a1' member of the sss class is initialized to this object 'a',
which is an instance of the class aaa. The abc function is called next from sss, and the
return value is stored in a string named 'r'. The InnerHtml property of the span is then
set to 'r', to facilitate the value to be fnally displayed in the browser window.

244025452.doc 228 od 274
If an exception is thrown by the function abc, the code in the 'catch' block gets called,
whereupon, the exception message is displayed using the span, with the id of s2. Thus,
it is either the return value of the function abc or the exception message which is
displayed in the browser.


The aa.wsdl fle generates the code for the function abc. So, let us scurry through the
wsdl fle. Most of it has already been expounded earlier. As always, the fle begins with
the root element defnitions, which are followed by a number defned namespaces. Then,
an element e1 is created, which is empty in nature. Another element abcResponse is
also created, containing a single element named abcResult.

The element a1 of type aaa contains two elements, viz. User and Password. The type aaa
is responsible for initiating the class aaa in the client, which is eventually employed to
send across the header. The message i1 has one part, containing an element e1. Since
this element is devoid of any contents, the part and the message have no contents,
whatsoever. The other part is assigned to the second message o1, which represents the
return packet from the server. The element of the second part is abcResponse, which is
a string.

The header is represented by the message va, which has an element called a1. This in
turn, contains the two header elements. The portType 'pt' represents the operation abc,
where the input is represented by the message i1, and the output is represented by the
message o1. To summarize, abc does not accept any input, and returns its output in the
form of a string.

The binding b1 accepts the portType pt. The style of the binding is 'document', and a
literal is used for the input body element. Thus, in the input element, the SOAP packet
is designed to hold a Body, as well as a header that contains the message named Va.
Finally, the service is assigned the name 'sss'. Therefore, the names assigned to the
client fle and the class will also be sss. The binding used is 'b1', and the address
element specifes the complete url of the code, which is as follows:
http://localhost:8080/qqqs/a.asmx.

There are no surprises in store for you in sss.cs, or in the client program generated by
the WSDL program. The header class is aaa, and the variable that carries the header is
a1.

The abc function is bestowed with a million attributes from the SoapDocumentMethod
attribute; however currently, none of these are of any signifcance, since the function
abc has been called without any parameters. Resultantly, the encoding that is used, is
also meaningless. The batch fle a.bat merely calls the wsdl program, in order to
generate the proxy fle named sss.cs.

The csc compiler compiles the sss.cs fle into a dll. This dll is then copied into the bin
folder, since it is peremptory for the entire code that is called from the aspx fle, to dwell
in the bin subdirectory. We reiterate it yet again, that the following fles should reside in
the folder c:\qqq\client, and the dll should be placed in the bin subdirectory. Thus, the
fles and their corresponding paths are as follows:
244025452.doc 229 od 274

R555RclientRa)asp,
R555RclientRaa)wsdl
R555RclientRbinRsss)dll

Having dealt with the client, let us now progress on to the fles that are required at the
server's side. The following fles will reside in the folder c:\qqq\server:

R555RserverRweb)conPg
R555RserverRglobal)asa,
R555RserverRa)asm,
R555RserverR333)cs
R555RserverRbinR333)dll

The very frst fle that we anatomize is the web.confg fle. This fle is a pure XML fle,
and contains settings that determine the confguration that the web server would use.
The fle must be present in the root directory of the web server, since the server utilizes
the settings that are located in the fle. So, this fle is created in the directory
c:\qqq\server.

The root tag confguration is followed by a system.web element. This element boasts of
two children, viz. a compilation section and an httpModules section. As the name itself
suggests, the compilation section contains all the compilation settings. However, in this
case, there is only one setting named 'assemblies'. The 'assemblies' section signals the
need for an assembly System.Security, as it is a point of reference for the code included
in any fle. Then, we encounter the httpModules element, which provides succor in
confguring the HttpModules that have been used in the application. One of these
modules gets added to our application.

The type attribute has two entities, separated by a comma. The frst is the name of a
class, i.e. yyy, while the second is the name of the dll, i.e. zzz.dll. The fle zzz.dll
contains the code and encloses the class yyy within it. This arrangement is termed as a
class/assembly combo. The attribute name is specifed as w1, which is used to refer to
code in the assembly zzz.dll.

We would be examining the fle global.asax in a short while from now.

Now, let us investigate the output fle a.txt, which comprises of the particulars about
the functions that are called, and the details as regards when they get called. The frst
function to be called is Init, which belongs to the class yyy, and resides in zzz.cs. The
zzz.dll fle is located in the server\bin folder. The class yyy is fabricated as a sealed
class, since we do not want anyone to derive from it.

This class is derived from the Interface IHttpModule, which contains only two methods,
Init and Dispose. The Init function prepares the yyy class to receive requests, while the
Dispose function is used for the winding up tasks.

The Init function is passed an object of type HttpApplication as a parameter. This class
has methods, properties and events that are required for representing application
objects in the ASP.Net world. All that we do in the Init function is, to set the event
244025452.doc 230 od 274
AuthenticateRequest to the function xyz. Thus, whenever a request needs to be
authenticated, the function xyz gets called.

Next, we have a property called Authenticate, which is called by the framework. Since
this property is of type event, it does not have a 'get' or 'set' accessor, instead, it has an
'add' and a 'remove'.

Whenever a function is to be added to the event, the add accessor is called. When a
function is to be removed, the remove accessor is called. The value member contains the
function that is to be added or removed. Before long, we would be able to discern which
function is being added to the accessor.

The property has a type ddd, which is a delegate that takes two parameters, viz. an
Object and an eee class. The eee class is derived from EventArgs, and is the frst class
in the zzz.cs fle. None of the functions would ever get called, if the code in the Init
function was placed within comments.

After Init and Authenticate, the next function to be called is xyz. The frst parameter to
this function is an HttpApplication object, and the second parameter is an object, which
is derived from EventArgs. This parameter is seldom accessed.

The HttpApplication object has a member Context, which represents the HTTP context
in which we operate. The value of the context is stored in a variable called 'co'. It is
indeed possible for us to write an entire book with efortless ease, expounding all the
workings of an HttpContext object; however, we have chosen to refrain from it. What we
require is a property Request of type HttpRequest, which contains a property named
InputStream, of type Stream. This stream object is stored in 's', and it is used for
reading the entire SOAP payload passed to the function.

But prior to that, we determine the current position of the fle pointer by displaying the
Position parameter. The a.txt fle unravels the fact that, the pointer is located at the very
beginning. We store this value zero in a variable p, which we would be using
subsequently.

The code that is inserted next, is very similar to the program that was used to display
the headers, when an HttpRequest object was supplied. There are a total of six headers,
whose names and values are entered into the fle a.txt.

The header HTTP_SOAPACTION confrms the fact that the payload is actually a SOAP
payload. Using the name of the header as an indexer to the ServerVariables property, we
ascertain the value embodied in it. If the value is null, the request is not regarded as a
SOAP formatted request; instead, it is treated as a normal HTTP request.
A SOAP payload is an XML document. Therefore, an empty XmlDocument object d1 is
created. Then, the data that is associated with the Stream 's' or the SOAP payload, is
loaded with the help of the Load function. The Position property of the XML document
is reverted back to the starting position.

Finally, using the Save function, the SOAP payload is written to disk in the fle b.txt.
This fle, when viewed, is espied to be identical to the SOAP request that is sent across.
244025452.doc 231 od 274
The SOAP request has a header that contains the user name and password instead of it
being shown in the body.

Now, we use a deviant approach to retrieve the values, since we do not intend to
implement the method that was used earlier.

The function GetElementsByTagName accepts a parameter that signifes the name of
the element that we are interested in, viz. User. This function returns a list of nodes in
XmlNodeList, which contains the element User. Since there is only one element called
User, we use the indexer to access this XmlNode object 'n'.

The InnerText property then facilitates access to the content. The value retrieved is
stored in the variable u. By using a similar mechanism, the contents of the element
password are retrieved. The values that are displayed, provide ample evidence of our
treading the right track. However, if things go adrift; for instance, if the User and
Password elements do not exist in the header, a full-fedged SOAP Exception will be sent
across.

Next, we create an object that bears a resemblance to class eee. This class is derived
from the class EventArgs, and hence, it can be used as the second parameter in all the
event handling code, which needs an object derived from EventArgs. The object which
looks like eee, is created by calling its constructor and assigning it three parameters,
the HttpContext object 'co', the strings 'u' and 'pa' .

They contain the user name and password, both of which have been extracted from the
header. Please note that the code in the asmx fle will not be called anywhere in the
near future.

The constructor of the class eee, stores the values passed in the three variables c, u and
p. The variables are also used in the properties of Cont, Us and Pass. The variables
merely act as fronts for the properties.

Along the same lines, the variable 'p' is used for the property Prin. If we so desire, we
can make the variables public, and replace the property Us with u. But, it has been
reiterated time and again that, it is the properties that are to be used, and not
variables. Albeit, a variable could have served our purpose equally well, in the above
case. As the saying goes, " Old habits die hard!"

Now, one of the functions is called, using the event e.

So far, we were oblivious to the identity of the function that was passed in the value
parameter. However, it is about time that we lifted the veil of the mystery. The
function's name is w1_OnAuthenticate, and it is located in the fle global.asax. This
function is called with two parameters:
The frst is the sender, the class 'yyy'.
The second is the 'eee' object, which stores the HttpContext object, the user name
and the password.

244025452.doc 232 od 274
This fle is called the ASP.NET application fle. It contains code that responds to
application level events that occur.

As was the case with the confg fle that was discussed earlier, the global.asax fle ought
to be residing in the root directory of the web server, in order to get a right output of
the application. This fle is compiled into the class generated by the framework. Since
the web server completely forbids access to this fle, no one can gain access to its
contents by using a URL. This fle contains all the application or session handlers.

The function name in the asax fle has to begin with the name 'w1', followed by the
underscore symbol, fnally followed by the name of the event 'OnAuthenticate'. The
second parameter 'eee' is used to verify the user name and password, using the
properties Us and Pass. These in turn, refer to the properties of Us and Pass.

If the SOAP header contains the user name 'vijay' and the password 'mukhi', then and
only then, does the function qqq get called in the 'eee' class. To put it diferently, it
implies that if the user name and password are any diferent from the ones that have
been specifed above, the qqq function will not be called. This function is passed an
array of strings, having a size of 1, since it contains only a solitary string named
Customer.

In the qqq function, we create an object i, which is an instance of class GenericIdentity.
This class is derived from the interface Iidentity and it represents a user, on behalf of
whom, certain code gets executed. We pass the name of the user ('vijay' in this case),
to the constructor of the GenericIdentity class.

Another class named GenericPrincipal is created, whose sole task is to check the
membership of the user, in a set of roles. Thus, the constructor is provided with an
array of role names that the user belongs to. Our user belongs to a single role of
'Customer'. The Principal is then stored in the property Prin.
Now, let us refocus on the class yyy and the function xyz. Here, the property Us, which
contains the user name, is verifed to determine if it is null or not. In this case, the user
name is not null. Therefore, the principal object that we created in the qqq function is
frst retrieved. Thereafter, using the Cont property, the HttpContext object that is
passed to the eee object, through the eee constructor, is retrieved. This Context object
has a property User of type IPrincipal, which stipulates the security information for the
HTTP request. This IPrincipal object belongs to the singular role named Customer.

Once the function xyz accomplishes its task, the function abc gets called from the asmx
fle. Thus, it is the fnal function to be called in the sequence. Here, we merely use the
same User object, which is set to the IPrincipal object, and call the function IsInRole. As
the role is Customer, the 'if' statement results in true. Then, the password is changed to
'mukhi11'.

At this stage, the qqq function does not get called. Hence, the IsInRole function returns
false. Also, since the Authenticated property is not set to true, the second 'if' statement
returns false. In the a.txt fle, he second call after the HTTP headers is no more visible.
244025452.doc 233 od 274
If we had so desired, we could have changed the IsAuthenticated property to true, and
depending upon the user name, attached the user to more than one group.

(he 'ital oint that we intend to con'e& throu+h this ro+ra* is that, )e!ore the as*x !ile
aears on the scene, the code in the dll !ile and the asax !ile, +ets called. 0lso, an& chan+es
*ade to the roert& +et re!lected onl& in the as*x !ile.

17
WSE9 and EISCO

DISCO

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

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public string abc(string i 6 string j)
{
return iCj;
}
}

*disco !ttp:11local!ost1a)asm,
Microso.t >4B Web Services Eiscover' <tilit'
SMicroso.t >4B )(E UrameworkF Qersion 1)-)7A1=)1@T
Cop'rig!t >CB Microso.t Corp) 1AA0/7--1) All rig!ts reserved)

Eisco .ound documents at t!e .ollowing <49s:
!ttp:11local!ost1a)asm,+disco
!ttp:11local!ost1a)asm,+wsdl

!e .ollowing Ples !old t!e content .ound at t!e corresponding <49s:
)Ra)disco "/ !ttp:11local!ost1a)asm,+disco
)Ra)wsdl "/ !ttp:11local!ost1a)asm,+wsdl
!e Ple )Rresults)discomap !olds links to eac! o. t!ese Ples)

The a.wsdl fle 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 fle can also be
generated by specifying the URL of http://localhost/a.asmx?disco in the browser.

a.*isc)
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*isc)very xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema" xmlns"" (ttp,33sc(emas.xmls)ap.)rg3*isc)3
"%
<c)ntract=eK reK""(ttp,33l)cal()st3a.asmxN/s*l" *)c=eK""(ttp,33l)cal()st3a.asmx"
xmlns""(ttp,33sc(emas.xmls)ap.)rg3*isc)3scl3" 3%
<s)ap a**ress""(ttp,33l)cal()st3a.asmx" xmlns,P<""(ttp,33tempuri.)rg3" bin*ing""P<,zzz)ap"
xmlns""(ttp,33sc(emas.xmls)ap.)rg3*isc)3s)ap3" 3%
244025452.doc 234 od 274
<3*isc)very%

results.*isc)map
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<0isc)very#lient=esultsDile xmlns,xsi""(ttp,33///./B.)rg3@77<3O'!c(emaGinstance"
xmlns,xs*""(ttp,33///./B.)rg3@77<3O'!c(ema"%
<=esults%
< 0isc)very#lient=esult reKerence:ype""ystem.Web.ervices.0isc)very.#)ntract=eKerence"
url""(ttp,33l)cal()st3a.asmxN/s*l" Kilename""a./s*l" 3%
<0isc)very#lient=esult
reKerence:ype""ystem.Web.ervices.0isc)very.0isc)very0)cument=eKerence"
url""(ttp,33l)cal()st,87873a.asmxN*isc)" Kilename""a.*isc)" 3%
<3=esults%
<30isc)very#lient=esultsDile%

The disco fle 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 signifcance here. The ref
attribute refers to the WSDL fle, while the docRef attribute refers to the asmx fle. 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 fle on the
server, and the binding refers to zzzSoap. Using this binding, the WebService is located
from within the WSDL fle. The results.discomap fle 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 fles
named a.wsdl and a.disco, which have been created by the DISCO program. The url
attribute contains the url that creates these fles.

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

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public string abc(string i 6 string j)
{
return iCj;
}
}

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns
xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(
ttp3" xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype%
244025452.doc 235 od 274
<s,sePuence%
<s,element min;ccurs""<" max;ccurs""<" name""i" nillable""true" type""s,string" 3%
<s,element min;ccurs""<" max;ccurs""<" name""j" nillable""true" type""s,string" 3%
<3s,sePuence%
<3s,c)mplex:ype%
<3s,element%
<s,element name""string" nillable""true" type""s,string" 3%
<3s,sc(ema%
<3types%
<message name""abc.ttp-)st4n"%
<part name""i" type""s,string" 3%
<part name""j" type""s,string" 3%
<3message%
<message name""abc.ttp-)st;ut"%
<part name""M)*y" element""s7,string" 3%
<3message%
<p)rt:ype name""zzz.ttp-)st"%
<)perati)n name""abc"%
<input message""s7,abc.ttp-)st4n" 3%
<)utput message""s7,abc.ttp-)st;ut" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz.ttp-)st" type""s7,zzz.ttp-)st"%
<(ttp,bin*ing verb""-;:" 3%
<)perati)n name""abc"%
<(ttp,)perati)n l)cati)n""3abc" 3%
<input%
<mime,c)ntent type""applicati)n3xG///GK)rmGurlenc)*e*"3%
<3input%
<)utput%
<mime,mimeOml part""M)*y" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt bin*ing""s7,zzz.ttp-)st"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

zzz.cs
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
public class zzz ,
ystem.Web.ervices.-r)t)c)ls..ttp-)st#lient-r)t)c)l
{
public zzz()
{
2rl " "(ttp,33l)cal()st,87873a.asmx";
}
&ystem.Web.ervices.-
r)t)c)ls..ttp'et()*1ttribute(type)K(ystem.Web.
ervices.-r)t)c)ls.Oml=eturn=ea*er)6
type)K(ystem.Web.ervices.-r)t)c)ls..tmlD)rm-arameterWriter))+
&return, ystem.Oml.erializati)n.Oml=))t1ttribute("string"6 9amespace""(ttp,33tempuri.)rg3"6
4s9ullable"true)+
public string abc(string i6 string j)
{
return ((string)(t(is.4nv)5e("abc"6 (t(is.2rl C "3abc")6 ne/ )bject&+ {i6j})));
244025452.doc 236 od 274
}
}

b.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
string b " a.abc("(i"6"bye");
ystem.#)ns)le.Write!ine(b);
}
}

a.bat
W0! 3pr)t)c)l,.ttp-)st aa./s*l
#sc 3t,library zzz.cs
#sc b.cs 3r,zzz.*ll
b

Uormatted race
SOAP re5uest
i%!iY2%b'e

SOAP response
"+,ml version%&1)-& encoding%&ut./0& +*
"string ,mlns%&!ttp:11tempuri)org1&*!ib'e"1string*

<n.ormatted race
SOAP re5uest
POS 1a)asm,1abc ;P11)1

i%!iY2%b'e

Output
;ib'e

The asmx fle 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 fle.

In the wsdl fle seen above, we will lay emphasis only that portion which deals with a
POST request. A POST request is diferent from a GET in one signifcant 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 fle begins with the defnitions 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.

244025452.doc 237 od 274
The client program is generated by running the wsdl program as:

WSE9 1protocol:;ttpPost 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: specifes 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 t'pe%&te,t1,ml& 1*

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
defning 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 specifed, 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 specifed 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 1server aa)wsdl

244025452.doc 238 od 274
zzz.cs
using ystem.0iagn)stics;
using ystem.Oml.erializati)n;
using ystem;
using ystem.Web.ervices.-r)t)c)ls;
using ystem.Web.ervices;
&ystem.Web.ervices.WeberviceMin*ing1ttribute(9ame""zzz)ap"6
9amespace""(ttp,33tempuri.)rg3")+
public abstract class zzz , ystem.Web.ervices.Webervice
{
&ystem.Web.ervices.Web'et()*1ttribute()+
&ystem.Web.ervices.-r)t)c)ls.)ap0)cument'et()*1ttribute("(ttp,33tempuri.)rg3abc"6
2se"ystem.Web.ervices.0escripti)n.)apMin*ing2se.!iteral6
-arametertyle"ystem.Web.ervices.-r)t)c)ls.)ap-arametertyle.Wrappe*)+
public abstract string abc(string i6 string j);
}

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

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public v)i* abc()
{
}
}

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

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<message name""m" 3%
<p)rt:ype name""pt"%
<)perati)n name""abc"%
<input message""s7,m" 3%
<)utput message""s7,m" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""b<" type""s7,pt"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" 3%
<input%
<s)ap,b)*y 3%
<3input%
<)utput%
<s)ap,b)*y3%
<3)utput%
<3)perati)n%
244025452.doc 239 od 274
<3bin*ing%
<service name""zzz"%
<p)rt bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

b.cs
public class aaa
{
public static v)i* 'ain()
{
zzz a " ne/ zzz();
a.abc();
}
}

a.bat
*el R.*ll
*el R.exe
/s*l aa./s*l
csc 3t,library zzz.cs
csc b.cs 3r,zzz.*ll
b

SOAP re5uest
"soap::od' 1*

SOAP response
"soap::od'*
"abc4esponse ,mlns%&!ttp:11tempuri)org1& 1*
"1soap::od'*

Here, we encounter the smallest possible WSDL fle, 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 specifcations exhaustively.

At the bottom of the aa.wsdl fle, 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 fle 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./s*l
<service name""aaa"%
<p)rt bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

zzz.cs
public class b< , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {

public class b<< , ystem.Web.ervices.-r)t)c)ls.)ap.ttp#lient-r)t)c)l {
244025452.doc 240 od 274

We now add one more service called aaa, to the end of the wsdl fle. Multiple service
elements are permissible in the WSDL fle. 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./s*l
<service name""zzz"%
<p)rt name""p<" bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<p)rt name""p@" bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%

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 diferent port names, such as p1 and p2. However, the two classes
that get created in the zzz.cs fle, 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 ofers a
binding for SOAP 1.1 endpoints. This is because, a major part of the WSDL
specifcations converges around SOAP. In a sense, the specifcations 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
specifcations keep evolving on a continuous basis, thereby, resulting in amendments
and enhancements to the WSDL specifcations.
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 indiferent 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.

244025452.doc 241 od 274
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 frst 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
fnally 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 specifed.

For SOAP protocol bindings other than HTTP, such as SMTP, a value cannot be
specifed. 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 specifes 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 specifed 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 fle 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 fle. If it is absent,
the name of the class becomes Item, while the name of the fle 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
244025452.doc 242 od 274
names of the classes. The frst service name is used for the name of the fle. 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
diferent bindings or addresses, these ports are to be used as alternatives.

Once again, compared to the binding, the service and the port appear insignifcant. This
is because, the port defnes 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
specifcations, a port cannot specify more than one address. However, if we do hold two
address elements, only the frst 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 specifes a protocol for transport. We can have more
than one binding, derived from the same port type. Then, an operation is defned 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
specifes 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, specifes the binding
information for an operation. The name assigned here must be the same, as the one
specifed for the operation that is created in the port type. It is incorrect to use diferent
names for the operation in the binding and the port type. If more than one protocol is
specifed, 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 defne 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.

244025452.doc 243 od 274
The operation element name must match with the name in the bindings element.
Resorting to diferent names in each of the operation elements may result in whopping
errors, as an outcome of which, the zzz.cs fle may refuse to be written at all!

a.asmx
<%@ Webervice !anguage""#$" #lass""zzz" %%
using ystem.Web.ervices;
public class zzz
{
&Web'et()*()+
public v)i* abc()
{
}
&Web'et()*()+
public v)i* pPr()
{
}
}

aa./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<types%
<s,sc(ema attributeD)rm0eKault""PualiKie*" elementD)rm0eKault""PualiKie*"
target9amespace""(ttp,33tempuri.)rg3"%
<s,element name""abc"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""abc=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""pPr"%
<s,c)mplex:ype 3%
<3s,element%
<s,element name""pPr=esp)nse"%
<s,c)mplex:ype 3%
<3s,element%
<3s,sc(ema%
<3types%
<message name""abc)ap4n"%
<part name""parameters" element""s7,abc" 3%
<3message%
<message name""abc)ap;ut"%
<part name""parameters" element""s7,abc=esp)nse" 3%
<3message%
<message name""pPr)ap4n"%
<part name""parameters" element""s7,pPr" 3%
<3message%
<message name""pPr)ap;ut"%
<part name""parameters" element""s7,pPr=esp)nse" 3%
<3message%
<message name""abc.ttp?et4n" 3%
<message name""abc.ttp?et;ut" 3%
<message name""pPr.ttp?et4n" 3%
<message name""pPr.ttp?et;ut" 3%
<message name""abc.ttp-)st4n" 3%
244025452.doc 244 od 274
<message name""abc.ttp-)st;ut" 3%
<message name""pPr.ttp-)st4n" 3%
<message name""pPr.ttp-)st;ut" 3%
<p)rt:ype name""zzz)ap"%
<)perati)n name""abc"%
<input message""s7,abc)ap4n" 3%
<)utput message""s7,abc)ap;ut" 3%
<3)perati)n%
<)perati)n name""pPr"%
<input message""s7,pPr)ap4n" 3%
<)utput message""s7,pPr)ap;ut" 3%
<3)perati)n%
<3p)rt:ype%
<p)rt:ype name""zzz.ttp?et"%
<)perati)n name""abc"%
<input message""s7,abc.ttp?et4n" 3%
<)utput message""s7,abc.ttp?et;ut" 3%
<3)perati)n%
<)perati)n name""pPr"%
<input message""s7,pPr.ttp?et4n" 3%
<)utput message""s7,pPr.ttp?et;ut" 3%
<3)perati)n%
<3p)rt:ype%
<p)rt:ype name""zzz.ttp-)st"%
<)perati)n name""abc"%
<input message""s7,abc.ttp-)st4n" 3%
<)utput message""s7,abc.ttp-)st;ut" 3%
<3)perati)n%
<)perati)n name""pPr"%
<input message""s7,pPr.ttp-)st4n" 3%
<)utput message""s7,pPr.ttp-)st;ut" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""zzz)ap" type""s7,zzz)ap"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" style""*)cument" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<)perati)n name""pPr"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3pPr" style""*)cument" 3%
<input%
<s)ap,b)*y use""literal" 3%
<3input%
<)utput%
<s)ap,b)*y use""literal" 3%
<3)utput%
<3)perati)n%
<3bin*ing%
<bin*ing name""zzz.ttp?et" type""s7,zzz.ttp?et"%
<(ttp,bin*ing verb""?>:" 3%
<)perati)n name""abc"%
<(ttp,)perati)n l)cati)n""3abc" 3%
<input%
<(ttp,url>nc)*e* 3%
<3input%
<)utput 3%
<3)perati)n%
244025452.doc 245 od 274
<)perati)n name""pPr"%
<(ttp,)perati)n l)cati)n""3pPr" 3%
<input%
<(ttp,url>nc)*e* 3%
<3input%
<)utput 3%
<3)perati)n%
<3bin*ing%
<bin*ing name""zzz.ttp-)st" type""s7,zzz.ttp-)st"%
<(ttp,bin*ing verb""-;:" 3%
<)perati)n name""abc"%
<(ttp,)perati)n l)cati)n""3abc" 3%
<input%
<mime,c)ntent type""applicati)n3xG///GK)rmGurlenc)*e*" 3%
<3input%
<)utput 3%
<3)perati)n%
<)perati)n name""pPr"%
<(ttp,)perati)n l)cati)n""3pPr" 3%
<input%
<mime,c)ntent type""applicati)n3xG///GK)rmGurlenc)*e*" 3%
<3input%
<)utput 3%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt name""zzz)ap" bin*ing""s7,zzz)ap"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<p)rt name""zzz.ttp?et" bin*ing""s7,zzz.ttp?et"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<p)rt name""zzz.ttp-)st" bin*ing""s7,zzz.ttp-)st"%
<(ttp,a**ress l)cati)n""(ttp,33l)cal()st3a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

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

There are three diferent verbs that a wsdl fle 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 fle. The WSDL fle 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 diferent types are created, and which can be referred to by the
elements. Since there are two functions in the asmx fle, namely, abc and pqr, an
element is also defned 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.
244025452.doc 246 od 274

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 fle 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
diference 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 fle. 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 fle. 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 diferent
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 diferent class. Hence, it uses a
diferent 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
specifed 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 specifed here, since many
ports will be created in the WSDL fle. Each of these has to be uniquely identifed.

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 <77;
}

244025452.doc 247 od 274
The wsdl fle has been created manually and represents a One-way operation. If you
examine the fle 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./s*l
<Nxml versi)n""<.7" enc)*ing""utKG8"N%
<*eKiniti)ns xmlns,s""(ttp,33///./B.)rg3@77<3O'!c(ema"
xmlns,(ttp""(ttp,33sc(emas.xmls)ap.)rg3/s*l3(ttp3"
xmlns,mime""(ttp,33sc(emas.xmls)ap.)rg3/s*l3mime3"
xmlns,tm""(ttp,33micr)s)Kt.c)m3/s*l3mime3text'atc(ing3"
xmlns,s)ap""(ttp,33sc(emas.xmls)ap.)rg3/s*l3s)ap3"
xmlns,s)apenc""(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3" xmlns,s7""(ttp,33tempuri.)rg3"
target9amespace""(ttp,33tempuri.)rg3" xmlns""(ttp,33sc(emas.xmls)ap.)rg3/s*l3"%
<message name""m" 3%
<p)rt:ype name""pt"%
<)perati)n name""abc"%
<input message""s7,m" 3%
<3)perati)n%
<3p)rt:ype%
<bin*ing name""b<" type""s7,pt"%
<s)ap,bin*ing transp)rt""(ttp,33sc(emas.xmls)ap.)rg3s)ap3(ttp" 3%
<)perati)n name""abc"%
<s)ap,)perati)n s)ap1cti)n""(ttp,33tempuri.)rg3abc" 3%
<input%
<s)ap,b)*y 3%
<3input%
<3)perati)n%
<3bin*ing%
<service name""zzz"%
<p)rt bin*ing""s7,b<"%
<s)ap,a**ress l)cati)n""(ttp,33l)cal()st,87873a.asmx" 3%
<3p)rt%
<3service%
<3*eKiniti)ns%

SOAP response
"abc4esult*1--"1abc4esult*

This is perfectly legal, as it signifes 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 signifcant 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
specifcations. 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:
244025452.doc 248 od 274
Solicit response, where the endpoint sends a message and then receives a message.
This is diferent from a request response, where the endpoint receives a message and
then sends a message.
Notifcation, 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 specifcation only defnes 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 defned. 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 fle is capable of taking gargantuan dimensions.
Hence, the specifcations recommend that we break this fle up into smaller documents.
Thereafter, these smaller fles can be coalesced into one large fle, by using the import
statement. The documentation element is used to add comments to the code in the
WSDL fle.

The frst 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 defnition 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 specifcation 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 diferent 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.
244025452.doc 249 od 274

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 specifcation, make a mention of two distinct encoding
defnitions. 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 specifcation. 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
specifcations subsist, mainly to defne 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 predefned 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 fnal 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 specifed 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 specifcation.

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 specifes or defnes XSD schemas, using the WSDL fle. The clients and
244025452.doc 250 od 274
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 fexible. All the parameters can be wrapped within one element, and a
default namespace can be created for these parameters.
The beneft of this is, the size of the SOAP payload contracts, since the XML fles 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 specifed in an element that wraps parameters. Thus, each
parameter must be specifed 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
signifcance here. The return value is the name of the web service, followed by the word
'Result'. The WebService method on the server must defne 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.

%n the "S#$ seci!ications, the st&le attri)ute indicates whether the oeration or !unction is
314 or docu*ent. %n a 314 st&le, the *essa+es contain ara*eters and return 'alues5
whereas, in the docu*ent st&le, the *essa+e contains docu*ents. (he soaC)indin+ ele*ent
deter*ines the st&le, where the de!ault is docu*ent, and the >use> attri)ute seci!ies either
>encoded> or >literal>. (his 'alue is then e*lo&ed )& "S#$, to deter*ine the attri)utes that
are to )e used while +eneratin+ the rox&.
16
4emoting

Remoting is the practice of calling code from a dll, located on another machine using a
web server.

Stipulated below are a few programs that unveil the concepts of remoting. After wading
through the basic concept of remoting, we shall explain the same concept in the context
of SOAP.

244025452.doc 251 od 274
In remoting, a program or a client situated in some location in the world, executes a
function or some code contained in a dll, which could be residing on a server, at some
other geographical location in the world.

In order to achieve the above, two sub-directories, i.e. ss for server and cc for the client
need to be created. As we proceed ahead, the programs become progressively
complicated. Hence, we call upon you to create the above mentioned directories, in
exactly the same manner as we have stated. We have explained a few concepts of
remoting in a nutshell, in the earlier chapter. However, there is no harm in re-iterating
the salient features again.

Once the directories have been created, create the fles s.cs and o.cs in the folder ss,
and run the batch fle a.bat. This will produce an exe fle called s.exe, and a dll fle
named o.dll. Then in the folder cc, create two fles named c.cs and o.cs, and again run
the batch fle named a.bat. This would create two more fles, c.exe and o.dll.

Thereafter, open up two DOS console boxes by using the Command Prompt option; and
within one of the consoles, execute the server executable named s.exe, in the ss
subdirectory. The program would neither show any output, nor would it quit.

Next, move on to the cc folder and run the client program c.exe. In this window, the
value of 100 is displayed. Simultaneously, if you switch to the server window, you would
notice that three lines have been displayed.

Server
s.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels.:cp;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel(8787);
#(annelervices.=egister#(annel(c);
=em)ting#)nKigurati)n.=egisterWellLn)/nervice:ype (:ype.?et:ype("yyy6)")6 "abc"6
WellLn)/n;bject')*e.ingle#all);
ystem.#)ns)le.=ea*!ine();
}
}

).cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels.:cp;
public class yyy , 'ars(alMy=eK;bject
{
public yyy()
{
#)ns)le.Write!ine("yyy #)nstruct)r");
}
public int pPr(tring a)
{
244025452.doc 252 od 274
#)ns)le.Write!ine("0!! " C a);
return <77;
}
}

a.bat
*el R.exe
*el R.*ll
csc 3t,library ).cs
csc s.cs 3r,).*ll

Client
c.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel();
#(annelervices.=egister#(annel(c);
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
iK () "" null)
ystem.#)ns)le.Write!ine(">rr)r");
else
{
int i " ).pPr("vijay");
#)ns)le.Write!ine(i);
}
}
}

).cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels.:cp;
public class yyy , 'ars(alMy=eK;bject
{
public yyy()
{
#)ns)le.Write!ine("yyy #)nstruct)r<");
}
public int pPr(tring a)
{
#)ns)le.Write!ine("0!!< " C a);
return <777;
}
}

a.bat
*el R.exe
*el R.*ll
csc 3t,library ).cs
csc c.cs 3r,).*ll

Output in Server
''' Constructor
''' Constructor
E99 vi2a'

244025452.doc 253 od 274
Output in Client
1--

Curtly speaking, the fle o.dll is present in the folder ss. The function pqr gets executed
from this fle. The return value of this function, i.e. 100, is displayed in the client
window. There is a fle named o.dll in the cc folder, but no code is executed from it.

Now, let us attempt at understanding the programs more exhaustively.

We initially grapple with the server program named s.cs. As always, the fle begins with
the namespaces. The concept of namespaces is employed to evade clashes between
names that are freely created and used by people in general. Then, an object c of type
HttpChannel is created. The HttpChannel class uses the HTTP protocol, i.e. the Hyper
Text Transfer Protocol, to transfer messages between the client and the server.

In the networking world, the hierarchy is as follows:
First comes IP, the Internet Protocol.
Next is the TCP or Transmission Control Protocol.
This is followed by HTTP or Hyper Text Transfer Protocol, which is the very
foundation of the World Wide Web.

The two email protocols of SMTP and POP3, and the File Transfer Protocol FTP are at
the same level as HTTP. When two computers talk to each other, every packet that is
transferred to and fro between them, is stamped with a number. This facilitates easy
identifcation by various higher-level protocols. In the TCP/IP world, this number is
known as a port number.

Then, we exploit the services of another class named ChannelServices, which is
responsible for sending and receiving data on the specifed Channel. The static
RegisterChannel function, which accepts an IChannel interface as a parameter, is
assigned a value of 'c'. Thus, we can safely infer that the HttpChannel class is derived
from the IChannel interface. In place of HttpChannel, we could have used a
TcpChannel.

Next, we press into action, another static function named RegisterWellKnowServiceType,
from the class RemotingConfguration. This function unfurls the code that is to be
executed, along with its whereabouts. The frst parameter to this function is a data type
called Type. To place a value in this parameter, we use the static function GetType, with
a class name and a dll name. The values of 'yyy' and 'o' signify that the class yyy has to
be obtained from the library o.dll. Thus, not only do we specify a class name yyy, but
also the name of the dll that contains the class. The comma serves as a delimiter.

Therefore, our server that is listening on port 8080, will permit others to access code
from the class yyy in the dll fle named o. The next parameter identifes and locates the
code that is to be executed.
The URI specifed here is 'abc'. The last parameter that is specifed, can assume any of
the two values of an enum: WellKnownObjectMode, SingleCall or Singleton. The value of
SingleCall specifed in the program, ensures that every time a client calls some code in
the server, the server shall use a new instance of the class yyy. The ReadLine function
freezes execution of all the code. As a consequence, the server does not quit out.
244025452.doc 254 od 274

Let us now shift our focus to the class yyy, which exposes the function pqr.

In the fle o.cs, class yyy is derived from the class MarshalByRefObject. If we fail to
derive from this class, a runtime exception gets generated. This is because of the fact
that, the class MarshalByRefObject is the base class for all objects that are to be
remoted. In the class, we have a constructor yyy, whose sole task is to print a string. We
also have a function pqr, which accepts a string and returns the number 100.

The client c.cs in the cc folder starts with an HttpChannel object c. The constructor
uses the default port number, unlike the case of the server, where we had to specify the
number 8080. As is apparent from the server, a Channel object is registered. The object
yyy that is located on the server machine and which is identifed by the uri, is then
activated on the client.

In our simulation, the client and server are on two diferent dos boxes; although in real
time, they could be located miles apart. Therefore, the object has to be activated on a
remote machine. To accomplish this, the Activator class is used, which fnally returns a
handle to that object.

To rephrase it in simple words, in order to create an object on a local machine, the 'new'
keyword is used. On the other hand, to create an object remotely, so that it can be
accessed on the machine as a local object, we use the static function GetObject from
the Activator. This function accepts two parameters:
The frst is yyy, the type of the object that is to be created.
The second is a URL in a string format, which points to the location of the server.
The URL starts with http, since the transport mechanism used is similar to the http
protocol. After the colon and the two slashes, i.e. ://, the address of the server is
specifed. Since it is on our local machine, we specify the address as 'localhost'. The
number 8080 following the colon symbol, is the port number where the server awaits all
calls. The name of our server or URI is specifed as 'abc'. Therefore, we conclude the
above string with the URI of abc.

The server actually has a URI of abc on port 8080. Thus, it returns a valid object, from
which the function pqr is called. This function pqr is executed of the server, and
returns 100 in the variable i. The value of i is then displayed.

In the server window, the yyy constructor gets called twice, while the pqr function gets
called once. The code in o.dll gets called from the server and not from the client. The
constructor gets called twice on account of the call to the pqr function, and not because
of the GetObject function.

If we comment out the call of the pqr function in the client, no output is witnessed in
the server window. This elucidates the indispensability of o.dll in both the dos boxes.
This is the smallest remoting example possible, but we are not sure if you have been
able to grasp it fully or not. The documentation states that Remoting uses SOAP,
although we still have no clue as to how it does so. The point to be noted here is that,
the client and the server interact with each other. As an upshot of this interaction,
some code gets executed.
244025452.doc 255 od 274

Now, we write our own code, which divulges the communication between the client and
the server. We make no alterations to the code in the client.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz {
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
ystem.#)ns)le.Write!ine(a<);
#)ns)le.=ea*!ine();
}
}

*csc a)cs

Output in t!e pro,'
POS 1abc ;P11)1
<ser/Agent: Mo3illa1=)-Z>compatible? MSIE @)-? Windows D)-)71AD)-? MS )(E
4emoting? MS )(E C94 1)-)7A1=)1@ B
SOAPAction: &!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1oWp5r&
Content/'pe: te,t1,ml? c!arset%&ut./0&
Content/9engt!: =II
E,pect: 1--/continue
Connection: Ceep/Alive
;ost: local!ost

"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/E(Q%&
!ttp:11sc!emas),mlsoap)org1soap1envelope1 & SOAP/E(Q:encodingSt'le %&
!ttp:11sc!emas),mlsoap)org1soap1encoding1 & ,mlns:i7%&
!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a id%&re./6&*vi2a'"1a*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*
In addition to the existing folders, we now create one more folder named 'p', to
accommodate the above program named a.cs. Then, we compile it to generate the fle
a.exe. Now, we would like you to run this program frst, followed by the client.

After a few seconds, press Control-C in the client dos box and quit out of the waiting
client. Now, switch over to the dos box where the a.exe program is running in the 'p'
244025452.doc 256 od 274
folder. You will notice the junk displayed above. Press enter and quit out of this program
too.

The folder 'p' contains code for the proxy. The output seen in the dos box is a SOAP
message. Before we launch forth into the SOAP world, a salient point to be noted is that,
the server program was never executed.

We shall not dig any deeper and dissect the workings of the proxy program, as most of it
has been expounded in the frst chapter, while understanding the spy program. The
client too has been explained earlier on. Hence, we shall not mull over it again.

It sufces to say that, the name of the function to be executed is pqr, and there also
exists a tag with the same name. Now, to enable others to execute a function called pqr,
the tag is prefaced with the unique namespace i2, created earlier in the code.

The pqr tag so formed, is now unique across the seven seas. It takes an attribute id,
which has been assigned a value of ref-1. The id attribute is used to furnish the tag
with a unique name. The function takes one parameter named 'a', with a value of 'vijay'.
Therefore, there exists a child tag 'a' with an id attribute of ref-3. It appears as if they
have missed out ref-2 ;-). The content given to this tag 'a' is 'vijay', because the function
pqr is called with this value. Following this tag, are the three closing tags for pqr, Body
and Envelope.

Thus, to call any function, a tag with the name of the function is created, and the
parameter values are passed as content between tags accepting the parameter name.
This assists in identifying the diferent parameter values in a function.


s.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels.:cp;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel(878<);
#(annelervices.=egister#(annel(c);
=em)ting#)nKigurati)n.=egisterWellLn)/nervice:ype(:ype.?et:ype("yyy6)")6 "abc"6
WellLn)/n;bject')*e.ingle#all);
ystem.#)ns)le.=ea*!ine();
}
}

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz {
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
244025452.doc 257 od 274
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
ystem.#)ns)le.Write!ine(a<);
:cp#lient t< " ne/ :cp#lient();
t<.#)nnect("<@A.7.7.<"6 878<);
9et/)r5tream s< " t<.?ettream();
s<.Write(b676(<);
s<.Write(c6 76(@ );
byte &+ * " ne/ byte&<777+;
int (B " s<.=ea*(*676<777);
tring a@ " >nc)*ing.1#44.?ettring(*);
ystem.#)ns)le.Write!ine(a@);
byte &+ *< " ne/ byte&<777+;
(B " s<.=ea*(*<676<777);
a@ " >nc)*ing.1#44.?ettring(*<);
ystem.#)ns)le.Write!ine(a@);
byte &+ *@ " ne/ byte&<777+;
int (H " s<.=ea*(*@676<777);
a@ " >nc)*ing.1#44.?ettring(*@);
ystem.#)ns)le.Write!ine(a@);
s.en*(*<6(B6)c5etDlags.9)ne);
s.en*(*@6(H6)c5etDlags.9)ne);
}
}

Output
POS 1abc ;P11)1
<ser/Agent: Mo3illa1=)-Z>compatible? MSIE @)-? Windows D)-)71AD)-? MS )(E
4emoting? MS )(E C94 1)-)7A1=)1@ B
SOAPAction: &!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1oWp5r&
Content/'pe: te,t1,ml? c!arset%&ut./0&
Content/9engt!: =II
E,pect: 1--/continue
Connection: Ceep/Alive
;ost: local!ost

"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a id%&re./6&*vi2a'"1a*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*
;P11)1 1-- Continue

;P11)1 7-- OC
Content/'pe: te,t1,ml? c!arset%&ut./0&
Server: MS )(E 4emotingF MS )(E C94 1)-)7A1=)1@
Content/9engt!: =A-
"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
244025452.doc 258 od 274
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r4esponse id%&re./1&*
"return*1--"1return*
"1i7:p5r4esponse*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

In the server program, the port number in the HttpChannel constructor has been
changed to 8081. Thus, the server will now accept all packets that are destined for the
port number 8081.

Now, to run the above program, we open up three dos boxes. The frst one is for the
proxy server called a.exe, in the folder p. The server program s.exe will be executed from
the ss directory, in the second dos box. These two programs do not show any output at
all. In the third dos box, we move on to the client folder cc and run the program c.exe,
which initiates some process and generates the above output.

The proxy console displays additional data that was not visible earlier. The newly
introduced output is the SOAP message sent by the server to the client.

As is essentially the case, the SOAP payload sent by the server starts with the Envelope
root, containing all the namespace defnitions. The Envelope tag is followed by the Body
tag, and since this is the Response of the pqr function, the tag is pqrResponse. It takes
an id of ref-1. There can be only one return value, which is placed in the return tag. The
value enclosed in this tag is the return value of 100. The namespace, as usual, is i2.

In the proxy server, a considerable amount of code has been introduced. The proxy
resembles the spy program that we had examined in the earlier chapter. In case you
need to refresh your memory, you can fip through the pages and revise it once again.
The program has been introduced to prove that, in the world of remoting, the client and
server chat with each other using SOAP.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz
{
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
244025452.doc 259 od 274
ystem.#)ns)le.Write!ine(a<);
tring s< " ".::-3<.< @77 ;LFn#)ntentG:ype, text3xml; c(arset"F"utKG8F"Fnerver, ' .9>:
=em)ting6 ' .9>: #!= <.7.@J<H.<IFn#)ntentG!engt(, HJ<FnFn";
Myte&+ *< " >nc)*ing.1#44.?etMytes(s<);
tring s@;
s@ " "<;1-G>9Q,>nvel)pe xmlns,xsi"F"(ttp,33///./B.)rg3@77<3O'!c(emaGinstanceF"
xmlns,xs*"F"(ttp,33///./B.)rg3@77<3O'!c(emaF" xmlns,;1-G
>9#"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3F" xmlns,;1-G
>9Q"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3F" ;1-G
>9Q,enc)*ingtyle"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3F"
xmlns,i@"F"(ttp,33sc(emas.micr)s)Kt.c)m3clr3nsassem3yyy3)F"%<;1-G
>9Q,M)*y%<i@,pPr=esp)nse i*"F"reKG<F"%<return%<77<3return%<3i@,pPr=esp)nse%<3;1-G
>9Q,M)*y%<3;1-G>9Q,>nvel)pe%";
Myte&+ *@ " >nc)*ing.1#44.?etMytes(s@);
s.en*(*<);
s.en*(*@);
}
}

Output
POS 1abc ;P11)1
<ser/Agent: Mo3illa1=)-Z>compatible? MSIE @)-? Windows D)-)71AD)-? MS )(E
4emoting? MS )(E C94 1)-)7A1=)1@ B
SOAPAction: &!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1oWp5r&
Content/'pe: te,t1,ml? c!arset%&ut./0&
Content/9engt!: =II
E,pect: 1--/continue
Connection: Ceep/Alive
;ost: local!ost

"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a id%&re./6&*vi2a'"1a*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

Client Output
1--

Modify the proxy code in a.cs and then run the executable. There is no requirement of
running the server. Therefore, we go ahead and run the client program 'c' from the
folder cc.


The output shown in the proxy dos box is the message, sent by the client to the server.
Surprisingly, in spite of not having a server running, the client console still exhibits a
value of 100. This is due to the fact that the proxy code introduced here, deceives the
client into believing that it is actually a remoting server, which in reality, it is not.

Let us unravel the code in the proxy program.
The TcpListener, as always, listens on port 8080, which is the same port that the client
wants to connect to. Then, there is a wait for a connection at the blocking function
244025452.doc 260 od 274
AcceptSocket. The data dispatched by the client is then displayed on the console,
though it is not used anywhere.

The program introduces two strings, s1 and s2, which are initialized to values shown in
the output of the earlier program. These were the bytes that the server had sent across,
when it received a packet from the client. After these two strings have been initialised,
the packet is sent across to the client. As a result, the value of 100 is displayed on the
screen, since it is enclosed within the return tag.

Therefore, there is no need for the client to be familiar with the identity of the sender of
the packets. In any case, there is no way of determining this. The server could be a Java
program, for all that the client cares.

Clients and servers talk to each other via SOAP. Therefore, they are not required to be
cognizant of the intricacies of programming languages, Operating Systems, etc. SOAP
messages are sent over HTTP, and software at the endpoint is of no prime concern. This
is one of the several reasons why people are of the opinion that SOAP is revolutionizing
the world of Distributed Computing.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz {
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
string sE;
sE " "<;1-G>9Q,>nvel)pe xmlns,xsi"F"(ttp,33///./B.)rg3@77<3O'!c(emaGinstanceF"
xmlns,xs*"F"(ttp,33///./B.)rg3@77<3O'!c(emaF" xmlns,;1-G
>9#"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3F" xmlns,;1-G
>9Q"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3envel)pe3F" ;1-G
>9Q,enc)*ingtyle"F"(ttp,33sc(emas.xmls)ap.)rg3s)ap3enc)*ing3F"
xmlns,i@"F"(ttp,33sc(emas.micr)s)Kt.c)m3clr3nsassem3yyy3)F"%Fn<;1-G>9Q,M)*y%Fn<i@,pPr
i*"F"reKG<F"%Fn<a i*"F"reKGBF"%vijay<3a%Fn<3i@,pPr%Fn<3;1-G>9Q,M)*y%Fn<3;1-G
>9Q,>nvel)pe%FnFnFnFnFnFnFnFn";
Myte&+ l< " >nc)*ing.1#44.?etMytes(sE);
tring ss< " >nc)*ing.1#44.?ettring(l<);
byte &+ c " ne/ byte&<777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
:cp#lient t< " ne/ :cp#lient();
t<.#)nnect("<@A.7.7.<"6 878<);
9et/)r5tream s< " t<.?ettream();
s<.Write(b6 76(< );
s<.Write(l<6 76l<.!engt( );
byte &+ * " ne/ byte&<777+;
int (B " s<.=ea*(*676<777);
tring a@ " >nc)*ing.1#44.?ettring(*);
byte &+ *< " ne/ byte&<777+;
(B " s<.=ea*(*<676<777);
244025452.doc 261 od 274
a@ " >nc)*ing.1#44.?ettring(*<);
byte &+ *@ " ne/ byte&<777+;
int (H " s<.=ea*(*@676<777);
a@ " >nc)*ing.1#44.?ettring(*@);
s.en*(*<6(B6)c5etDlags.9)ne);
s.en*(*@6(H6)c5etDlags.9)ne);
}
}
The above-mentioned program is analogous to the frst proxy server in the chapter. The
proxy reads the two packets sent by the client. The only diference being, that the
second packet from the client is not sent across in its original form. Instead, the proxy
creates the packet and sends it to the server. Thus, the client and the server are merely
interested in the SOAP payload, and not in the identity of its creator.

The presence of too many folders, leads to clutter and confusion. Thus, for the next
program we have a single folder named 'rr', where we position the client c.cs, the server
s.cs and the dll o.cs. We place them all in a single folder for the sake of convenience. In
real life, they could be spread over diferent machines. The server program remains the
same, and on careful scrutiny, you would notice that there is no mention of the pqr
function in the server program.

a.cs
using ystem;
using ystem.9et;
using ystem.9et.)c5ets;
using ystem.:ext;
using ystem.4;;
class zzz
{
public static v)i* 'ain()
{
:cp!istener t " ne/ :cp!istener(8787);
t.tart();
)c5et s " t.1ccept)c5et();
byte &+ b " ne/ byte&<777+;
int (< " s.=eceive(b);
tring a " >nc)*ing.1#44.?ettring(b);
ystem.#)ns)le.Write!ine(a);
byte &+ c " ne/ byte&<777+;
int (@ " s.=eceive(c);
tring a< " >nc)*ing.1#44.?ettring(c);
ystem.#)ns)le.Write!ine(a<);
:cp#lient t< " ne/ :cp#lient();
t<.#)nnect("<@A.7.7.<"6 878<);
9et/)r5tream s< " t<.?ettream();
s<.Write(b676(<);
s<.Write(c6 76(@ );
byte &+ * " ne/ byte&<777+;
int (B " s<.=ea*(*676<777);
tring a@ " >nc)*ing.1#44.?ettring(*);
ystem.#)ns)le.Write!ine(a@);
byte &+ *< " ne/ byte&<777+;
(B " s<.=ea*(*<676<777);
a@ " >nc)*ing.1#44.?ettring(*<);
ystem.#)ns)le.Write!ine(a@);
byte &+ *@ " ne/ byte&<777+;
int (H " s<.=ea*(*@676<777);
a@ " >nc)*ing.1#44.?ettring(*@);
ystem.#)ns)le.Write!ine(a@);
244025452.doc 262 od 274
s.en*(*<6(B6)c5etDlags.9)ne);
s.en*(*@6(H6)c5etDlags.9)ne);
}
}

s.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel(878<);
#(annelervices.=egister#(annel(c);
=em)ting#)nKigurati)n.=egisterWellLn)/nervice:ype(:ype.?et:ype("yyy6)")6 "abc"6
WellLn)/n;bject')*e.ingle#all);
#)ns)le.=ea*!ine();
}
}

c.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel();
#(annelervices.=egister#(annel(c);
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
).pPr(<77);
}
}

).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(int a)
{
}
}

a.bat
*el R.exe
*el R.*ll
csc 3t,library ).cs
csc s.cs 3r,).*ll
csc c.cs 3r,).*ll
csc a.cs

Output
POS 1abc ;P11)1
<ser/Agent: Mo3illa1=)-Z>compatible? MSIE @)-? Windows D)-)71AD)-? MS )(E
4emoting? MS )(E C94 1)-)7A1=)1@ B
SOAPAction: &!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1oWp5r&
Content/'pe: te,t1,ml? c!arset%&ut./0&
Content/9engt!: =@=
E,pect: 1--/continue
244025452.doc 263 od 274
Connection: Ceep/Alive
;ost: local!ost
"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a*1--"1a*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

;P11)1 7-- OC
Content/'pe: te,t1,ml? c!arset%&ut./0&
Server: MS )(E 4emotingF MS )(E C94 1)-)7A1=)1@
Content/9engt!: =@0
"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r4esponse id%&re./1&*
"1i7:p5r4esponse*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

This program highlights one of the most important features of SOAP, i.e. functions with
parameters. These parameters are packaged as an XML document and then sent
across. The same process is followed for return values.

Now, we shall demystify the mechanism by which SOAP packages the data types, which
are passed with the parameters.

In our client program, the only change for next couple of programs is, call of the
function pqr with diferent parameter types. In this example, the parameter has the
datatype of int. As of now, there is no return value.

We intend to showcase the varied types of calls that can be made. We will display only
the modifed code in the latter part of the c.cs fle. The dll will have diferent iterations
of the function being called. Also, no output is displayed either in the client, or in the
server, or in the dll. Our objective is to fgure out how the parameters are packaged as
an XML document.

The a.bat fle is a straightforward and an uncomplicated one. It creates the executables
for the client and the server. In the frst dos box, we run the proxy a.exe. Then, in the
second dos box, we run the server 's'. Finally, in the last dos box, the client program 'c'
is run. To quit out of the server, simply press the enter key.

In the proxy console, we shall display the output from the point where the body tag
begins, since everything upto this point, remains the same. The number 100 is
packaged across, without the data type being specifed anywhere.
244025452.doc 264 od 274

As mentioned earlier, only the parameter name is sent across in the form of tag names.
The data type of the parameter is not visible in the XML document. The same holds true
for the response too. Since there is no return value, the return tag is also non-existent.
Hence, the return packet also remains unchanged. Thus, for the time being, we shall
not display the return SOAP payload too.

c.cs
).pPr(<776"vijay"6Kalse);

).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(int a 6 string b6 b))l c)
{
}
}

"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a*1--"1a*
"b id%&re./6&*vi2a'"1b*
"c*.alse"1c*
"1i7:p5r*
"1SOAP/E(Q::od'*

In the client program, function pqr is called with three parameters - an int, a string and
a bool. The int and bool are basic data types, and hence, are bereft of an id. However,
the string being a complexType, has an id of ref-3. The data types follow the rules of
XML Schemas.

The o.dll is modifed to incorporate the parameters, as the parameter names are picked
up from this library. Thus, simple types like int, do not possess any id attributes,
whereas, complex types do.

Out Parameters

c.cs
using ystem;
using ystem.=untime.=em)ting;
using ystem.=untime.=em)ting.#(annels;
using ystem.=untime.=em)ting.#(annels..ttp;
public class zzz
{
public static v)i* 'ain()
{
.ttp#(annel c " ne/ .ttp#(annel();
#(annelervices.=egister#(annel(c);
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int i6j;
i " <777;
).pPr()ut i6 )ut j6 @77);
#)ns)le.Write!ine(i C " " C j);
}
}

).cs
244025452.doc 265 od 274
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr()ut int a6 )ut int b6 int p)
{
a " <7;
b " @7;
}
}

Output
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"p*7--"1p*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

"SOAP/E(Q::od'*
"i7:p5r4esponse id%&re./1&*
"a*1-"1a*
"b*7-"1b*
"1i7:p5r4esponse*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*
Client Output
1- 7-

The above example deals with the 'out' parameter. For those of you who are not well
acquainted with the 'out' parameter, we restate that it does not have to be initialized
while calling the function. It is the responsibility of the function to initializes the 'out'
parameter, or else, an error is generated. The function that is called, is also not entitled
to access the value of the 'out' parameter, since its value does not have to be initialized
before the function is called.

In the fle c.cs, the function pqr has two 'out' parameters, i and j. The value of the
variable i is set to 1000, while j is not initialized. The last parameter is a simple by-value
parameter. In o.dll, the variables of i and j are initialized to the values of 10 and 20,
respectively. If we do not initialize them, an error will be generated.

The output expressly reveals that the initial SOAP Message is under the assumption
that there is a single parameter 'p', with a value of 200. There is no trace of the 'out'
parameters, despite the fact that one of them has been initialized. As a matter of fact,
there is no need for them to contain a value. Hence, sending a value over is merely an
exercise in futility. In the return SOAP payload, the two 'out' parameters named 'a' and
'b' are visible as tags, with their values of 10 and 20.

The 'out' parameters are sent back to the client, unlike the 'in' parameters, which are
sent from the server.

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int i;
i " <777;
).pPr(reK i);
#)ns)le.Write!ine(i);

244025452.doc 266 od 274
).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(reK int a)
{
a " <7;
}
}

Output
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a*1---"1a*
"1i7:p5r*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

"SOAP/E(Q::od'*
"i7:p5r4esponse id%&re./1&*
"a*1-"1a*
"1i7:p5r4esponse*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

Client Output
1-

The 'ref' parameter must be initialized before it is assigned to a function. The called
function may or may not change its value, but it can access it and use its value.

The function pqr takes one ref parameter, which is initialized to 1000. In the server, the
value is changed to 10.

To recapitulate, in the initial SOAP payload, the value of 1000 is sent across; and in the
return packet, the altered value of 10 is seen, with the parameter 'a'.

Thus, the 'in' parameters, which are the default parameters, are present only in the
packet that is sent from client to server. The 'out' parameters are sent from the server to
the client. The 'ref' parameters are the only ones that are transmitted in both directions,
from the client to the server, and also from the server to the client.

Arrays

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int &+ z;
z " ne/ int&B+{<76 BH6 EI};
).pPr(z);

).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(int &+ a )
{
}
}

"SOAP/E(Q::od'*
244025452.doc 267 od 274
"i7:p5r id%&re./1&*
"a !re.%&Wre./6&1*
"1i7:p5r*
"SOAP/E(C:Arra' id%&re./6& SOAP/E(C:arra''pe%&,sd:intS6T&*
"item*1-"1item*
"item*6="1item*
"item*D@"1item*
"1SOAP/E(C:Arra'*
"1SOAP/E(Q::od'*

The function pqr now takes an array of ints. Therefore, in the client program, we create
an array 'z' of three ints, and then assign it as a parameter to the function. In the dll,
the function pqr accepts this array in a parameter called 'a'.

The output reveals that in the Body element, tag 'a' contains an attribute href, with a
value of #ref-3. This is the only information furnished along with the pqr function tag.
Furthermore, for the frst time, the Array tag from the SOAP-ENC namespace has been
used.

The frst attribute of the array tag is an id ref-3, which is used for the href attribute.
Thus, the 'a' tag is now an array with an id of ref-3. The second attribute arrayType,
also from the SOAP-ENC namespace, states that the array has a size of three, and its
data type is an int from the namespace xsd. Following this is the item tag, which
enumerates the three value of the array viz. 10, 34 and 56.

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int &+ z;
z " ne/ int&B+{<76 BH6 EI};
string &+ y;
y " ne/ string&B+{".i"6 "bye"6 "n)"};
).pPr(z6y);

).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(int &+ a 6 string &+ b)
{
}
}

"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a !re.%&Wre./6&1*
"b !re.%&Wre./=&1*
"1i7:p5r*
"SOAP/E(C:Arra' id%&re./6& SOAP/E(C:arra''pe%&,sd:intS6T&*
"item*1-"1item*
"item*6="1item*
"item*D@"1item*
"1SOAP/E(C:Arra'*
"SOAP/E(C:Arra' id%&re./=& SOAP/E(C:arra''pe%&,sd:stringS6T&*
"item id%&re./D&*;i"1item*
"item id%&re./@&*b'e"1item*
"item id%&re./I&*no"1item*
"1SOAP/E(C:Arra'*
"1SOAP/E(Q::od'*

244025452.doc 268 od 274
After having worked with an array of ints, we anatomize the two arrays, one of which is
a string, and the other is an int. Thus, in the client program, we create an array named
y, which has three strings.

Then, we pass these two arrays 'z' and 'y' to the pqr function. In the SOAP payload,
there is a pqr tag, which has an attribute id with a value of ref-1. It contains two child
elements a and b, which correspond to the names of the two parameters. Both of them
have an href attribute each, which states the data type of these parameters that have
been created elsewhere. The frst Array element has an id of ref-3, and it specifes that
the arrayType is an array of three ints.

The second Array element has an id of ref-4. It is an array of three strings. The
diference here is that the item tag now contains a string, an XML Schema complex
type, and thus, has ids of ref-5, ref-6 and ref-7. This is the only known diference
between an array of simple types and that of a complex type.

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int&6+ a " ne/ int&B6 @+ { {<76 @7}6 {B76 H7}6 {E76 I7} };
).pPr(a);

).cs
public class yyy , ystem.'ars(alMy=eK;bject {
public v)i* pPr(int &6+ a)
{
}
}
Output
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a !re.%&Wre./6&1*
"1i7:p5r*
"SOAP/E(C:Arra' id%&re./6& SOAP/E(C:arra''pe%&,sd:intS6F7T&*
"item*1-"1item*
"item*7-"1item*
"item*6-"1item*
"item*=-"1item*
"item*D-"1item*
"item*@-"1item*
"1SOAP/E(C:Arra'*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

Illustrated above is an example of a multi-dimensional array. A multi-dimensional array
of size 3 by 2 is created, and simultaneously, it is initialized to some numbers. While
passing the array to the function pqr, the size of the array is not mentioned. Only the
fact that it is a multidimensional array, is specifed.

The SOAP payload displays a tag 'a', which refers to the array having the id of ref-3. The
Array tag has an array type of int, and its dimensions are 3 by 2. The item tag stores
these values in the sequence, as was used while initializing the array.

Thus, there is not much variation between the handling of single and multi-dimensional
arrays.

244025452.doc 269 od 274
Params parameters

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
).pPr("(i"6<76@76B7);

).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(string a6 params int &+ i)
{
ystem.#)ns)le.Write!ine(i&7+ C " " C i&<+ C " " C i&@+);
}
}

"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a id%&re./6&*!i"1a*
"i !re.%&Wre./=&1*
"1i7:p5r*
"SOAP/E(C:Arra' id%&re./=& SOAP/E(C:arra''pe%&,sd:intS6T&*
"item*1-"1item*
"item*7-"1item*
"item*6-"1item*
"1SOAP/E(C:Arra'*
"1SOAP/E(Q::od'*

In the above example, the function pqr takes one string and three ints. In the dll, the
ints are consumed by a params parameter.

The SOAP payload reveals the fact that the array of three ints is sent across as a single
array, and not as individual int parameters. This is because, the prototype or code of
the function specifes a params parameter.

Thus, the three ints are frst fused together into a single array, and then, the resultant
array is sent across the wire. For some reason, the name ref-2 is never used. Maybe
some people down there are superstitious. The string parameter 'a' has a reference to
ref-3, which is not used at all. The arrayType attribute is made up of a simple array of
three ints.

Jagged arrays

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
int&+&+ a " ne/ int&@+&+ { ne/ int&+ {<6@6B}6 ne/ int&+ {H6E} };
).pPr(a);


).cs
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(int&+&+a)
{
}
}

Output
244025452.doc 270 od 274
"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1&
,mlns:a1%&!ttp:11sc!emas)microso.t)com1clr1ns1S'stem&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a !re.%&Wre./6&1*
"1i7:p5r*
"SOAP/E(C:Arra' id%&re./6& SOAP/E(C:arra''pe%&a1:Int67STS7T&*
"item !re.%&Wre./=&1*
"item !re.%&Wre./D&1*
"1SOAP/E(C:Arra'*
"SOAP/E(C:Arra' id%&re./=& SOAP/E(C:arra''pe%&,sd:intS6T&*
"item*1"1item*
"item*7"1item*
"item*6"1item*
"1SOAP/E(C:Arra'*
"SOAP/E(C:Arra' id%&re./D& SOAP/E(C:arra''pe%&,sd:intS7T&*
"item*="1item*
"item*D"1item*
"1SOAP/E(C:Arra'*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

The client fle now has a jagged array containing two arrays. Once the jagged array has
been created, the other two arrays are created, with each having three and two
members, respectively. Thus, the jagged array has two arrays, which in turn, have
arrays of diferent lengths.
Finally, it is the data type that matters the most. In this case, it is an int. When a
jagged array is specifed, the length parameter is never taken into consideration.

With the introduction of the jagged array, the variation that we encounter is that, in the
Envelope tag, an additional namespace prefx has been created. The namespace points
to a regular namespace at Microsoft. In the body, the array is referred to as ref-3. While
creating this array, the namespace of 'a1', and not 'xsd', is used. The Int32 alias is used
in lieu of int for the data type of the arrayType attribute. The id of ref-3 defnes the frst
or outer array of the two members.

Since there are two members, the SOAP payload shows two item tags, which in turn,
defne two items with a href value of ref-4 and ref-5, respectively. From here onwards,
life proceeds normally. There are two arrays of ints, which have three and two members,
respectively. This makes sense, since a jagged array is merely a collection of individual
arrays of diferent sizes and shapes.

Thus, the frst array defnition specifes the individual arrays, and the other array
defnitions specify the arrays that constitute the jagged array.

Passing Objects

Change one line in the proxy program as given below:
byte &+ c " ne/ byte&<7777+;

244025452.doc 271 od 274
This change has to be initiated because the SOAP payload is extremely bulky. We could
have specifed a bigger number at the initial stage itself, but then, the use of large
numbers, would have resulted in the display of more blank lines.

c.cs
yyy ) " (yyy) 1ctivat)r.?et;bject(type)K(yyy)6 "(ttp,33l)cal()st,87873abc");
ppp b;
b " ne/ ppp();
).pPr(b);
).cs
public class ppp , ystem. 'ars(alMy=eK;bject
{
}
public class yyy , ystem.'ars(alMy=eK;bject
{
public v)i* pPr(ppp a)
{
}
}

Output
"SOAP/E(Q:Envelope ,mlns:,si%&!ttp:11www)w6)org17--118M9Sc!ema/instance&
,mlns:,sd%&!ttp:11www)w6)org17--118M9Sc!ema& ,mlns:SOAP/
E(C%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:SOAP/
E(Q%&!ttp:11sc!emas),mlsoap)org1soap1envelope1& SOAP/
E(Q:encodingSt'le%&!ttp:11sc!emas),mlsoap)org1soap1encoding1& ,mlns:a6%&
!ttp:11sc!emas)microso.t)com1clr1ns1S'stem)4untime)4emoting)C!annels&
,mlns:a1%&!ttp:11sc!emas)microso.t)com1clr1ns1S'stem)4untime)4emoting&
,mlns:i7%&!ttp:11sc!emas)microso.t)com1clr1nsassem1'''1o&*
"SOAP/E(Q::od'*
"i7:p5r id%&re./1&*
"a !re.%&Wre./6&1*
"1i7:p5r*
"a1:Ob24e. id%&re./6&*
"uri id%&re./=&*1cAc7=@D6MII@=M=eeDMa16DMbbccc=I@IAD.11)rem"1uri*
"ob2re.Ulags*-"1ob2re.Ulags*
"t'peIn.o !re.%&Wre./D&1*
"envo'In.o ,si:null%&1&1*
"c!annelIn.o !re.%&Wre./@&1*
"1a1:Ob24e.*
"a1:'peIn.o id%&re./D&*
"server'pe id%&re./I&*pppF oF Qersion%-)-)-)-F Culture%neutralF
PublicCe'oken%null"1server'pe*
"server;ierarc!' ,si:null%&1&1*
"inter.acesImplemented ,si:null%&1&1*
"1a1:'peIn.o*
"a1:C!annelIn.o id%&re./@&*
"c!annelEata !re.%&Wre./0&1*
"1a1:C!annelIn.o*
"SOAP/E(C:Arra' id%&re./0& SOAP/E(C:arra''pe%&,sd:ur/t'peS1T&*
"item !re.%&Wre./A&1*
"1SOAP/E(C:Arra'*
"a6:CrossAppEomainEata id%&re./A&*
"MConte,tIE*17A=0@="1MConte,tIE*
"MEomainIE*1"1MEomainIE*
"MprocessHuid id%&re./
1-&*DaeIcd@DMb0a1M=1b.Ma.ddM7-0.1dA=0-A@"1MprocessHuid*
"1a6:CrossAppEomainEata*
"1SOAP/E(Q::od'*
"1SOAP/E(Q:Envelope*

244025452.doc 272 od 274
In the client, the object 'b' is created as an instance of class ppp. This object is then
passed as a parameter to the function pqr. Efectively, we are passing a real-life object
or a reference type to a function. The fle o.cs defnes the class ppp. It must be derived
from the class MarshalByRefObject, or else, a runtime exception will be thrown. All
remoting objects have to be derived from the above-mentioned class. There is absolutely
no code in the class ppp. Despite this, the size of the SOAP payload increases, as an
actual object is now being sent over.

As usual, the Envelope element shows the namespaces, but now 'a3' and 'a1' are also
present. Unlike the namespace i2, both these namespaces are fxed, and are not related
to the code. The Body element, like before, begins with the pqr element from the i2
namespace, and consists of a single parameter 'a', having a href to ref-3.

This is not an array reference, but an ObjRef datatype, belonging to the namespace 'a1'.
The System.Runtime.Remoting namespace, holding the class called ObjRef, represents
the class ppp across the wire. Thus, an instance of an ObjRef class has been used, to
send across an object of type ppp, from the client to the server.

In remoting terminology, it is described as a transfer across an AppDomain boundary.
Thus, an ObjRef object, as seen in the SOAP payload, represents the serialized version
of the ppp object. This act of sending something over the wire is termed as 'marshaling'.

We are not required to create an ObjRef object, since it is created by the remoting
infrastructure, whenever we have to send across a reference object. This is not
applicable to value objects, such as- int. This ObjRef object contains all the information
about the object being remoted. This information describes entities like, the type and
class of the object, its location and the pathway to reach the object stored on a remote
server.

The class ppp that is derived from MarshalByRefObject, is converted into an ObjRef
object, using a process called 'marshalling'. At the remote server, the ObjRef is
converted into a proxy, or to be more accurate, a 'transparent proxy', which represents
the remoted object. This process is known as 'un-marshaling'. The proxy is termed as a
transparent proxy, since the client is given to believe that the proxy represents the
actual object.

The original object resides only on the remote machine. Therefore, from the client's
point of view, the proxy represents the actual object in its own memory space. It is like
the relationship between a magician and a fool. It is the task of the proxy to forward all
calls made on it, to the original object on the server, using the code provided by the
remoting world.

The child element or a property of the ObjRef class called uri has an id attribute, which
is of no signifcance right now. Its value is of type string, and it represents every unique
instance of the object. We can thus identify every unique instance of the object by using
this feld. It is assigned an id of ref-4, and it contains a very large number, which is
machine-generated.

244025452.doc 273 od 274
In the computer world, in order to represent an entity uniquely across time and space, a
128-bit or a 16-byte number is used.

"uri id%&re./ =&*1e@e=00e-M-e.6M=7-=MAa0-McbAced6Dd.e011)rem" 1uri*
"uri id%&re./ =&*1ed1dc@1.MA11aM=aI=MA77aM0aed-c.==.dI11)rem" 1uri*

Run the same program again, and observe that a diferent value is generated for the uri
feld. The value specifed above becomes a handle, and uniquely represents the ppp
object 'a'. We cannot explain the tag objrefFlags, whose value is 0, since it has not been
documented anywhere. It appears as though the documentation is also at the beta
stage.

Next, we have a tag typeInfo, which has a href to an element with an id of ref-5. This tag
is a TypeInfo, from the 'a1' namespace, and it starts with the capital letter T. This
element TypeInfo has three children or properties, as per the SOAP payload. The
documentation specifes the datatype for this property to be an interface
IremotingTypeInfo, which has only one property TypeName, of type string.

Though we are in no position to explain the above three child members, we shall still
endeavour to do so. The TypeInfo object contains considerable information about the
type of the remote object that the ObjRef represents. In our case, it is of type yyy. Also,
the type hierarchy or the classes that it derives from, as well as the interfaces it
implements, need to be ascertained. The proxy requires this data, to communicate with
the client. The interfacesImplementated does not have any content, since the class ppp
does not implement any interfaces.

The xsi:null attribute determines whether a null value can be used as the value of an
element or not. If yes, then the element can have a value of null.

The serverType element is made up of a list of values, which are delimited by commas,
as follows:
It starts with the class named ppp.
This is followed by the name of the dll fle 'o'.
Next is the version number.
This is followed by a Culture.
After this, comes a Public key value.
The last two values can either be null or they may have no values at all.

The EnvoyInfo element too does not have any content. This class or element of type
IEnvoyInfo contains 'message sinks'. The element is required when runtime support is
to be provided for transactions. The last child of ObjRef is a channelInfo element. This
refers to a ChannelInfo with a capital letter C, having an id of ref-6. Its data type is the
interface IChannelInfo.

This class handles diferent methods to communicate with the other side, using
channels. It has one member channelData, which has a href attribute set to an element,
with an id of href-8. This is an Array of type ur-type, and it has only one member.

An ur-type is the type defned in the XML Schemas world. It is this class that deals with
transport specifc issues. The channel data is copied from the channel into the SOAP
244025452.doc 274 od 274
payload. Subsequently, at the time of un-marshalling at the server end, this data is
required to create a transport sink and manage further transmission of messages
between the proxy and the server.

This array has only one child element item, which leads to the last id of href-9. This
member is of type CrossAppDomainData, and it stores the data for each channel. The
Context creates an environment for objects. The ContextID and DomainID do not
change at all.

The last member processGuid embodies a diferent value, each time the program is
executed.

"MprocessHuid id%&re./ 1-&*eb-d=1@1M=6c=M=D=0Mb-ebM=edaIc
=-77d7"1MprocessHuid*

<D%#, which is an acron&* !or a <lo)all& Dni8ue %denti!ier, is a 128?)it nu*)er, which is
a)solutel& uni8ue across ti*e and sace. (he words <D%# and DD%# ha'e ori+inated !ro*
the world o! 0cti'e. and /$6. (his )rin+s us to the end o! our exlanation o! the S/01
a&load.

Das könnte Ihnen auch gefallen