<?xml version="1.0" encoding="iso-8859-1"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Matlus ISAPI, TCP/IP and Webservice Related Tutorials</title><link>http://exposureroom.com/members/skumar.aspx/</link><atom:link href="http://rss.exposureroom.com/MemberJournalRssProvider.aspx/skumar/tutorials/" rel="self" type="application/rss+xml" /><description><![CDATA[<ul>
<li>ISAPI</li>
<li>TCP/IP</li>
<li>HTTP</li>
<li>SOAP/XML/WebServices</li>
<li>N-tier Applications and Zero configuration thin Clients</li>
</ul>
You should be able to find information, tutorials and articles on the technologies listed above and their implementation in Delphi on this site. Whereever is makes sense, you should find on-line demos and/or downloadable project source code.

Please Rate the tutorials/articles wherever possible. This will help me improve the quality of material you see here.
]]></description><pubDate>Fri, 05 Sep 2008 15:13:19 GMT</pubDate><generator>ExposureRoom RSS Feed Generator v1.0</generator><language>en</language><item><title>Building your First WebService in Delphi</title><pubDate>Wed, 23 Jan 2008 10:10:55 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/tutorials/post/1/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/tutorials/post/1/</guid><description><![CDATA[If you've been reading the Webservice articles on this site in the order that they are listed, then this is your first Webservice. As WebServices go, this is not the simplest of WebServices, but my thinking was that I could take you through the paces of building a Webservice that addresses some of things you'll need to know when building "real world" WebServices while at the same time not overwhelm you with all these new things. If you haven't read the previous articles, I strongly suggest you do. This tutorial assumes you have read those articles or know about the things that were discussed there. 
<p>In this tutorial, we'll start with building a WebService client for an existing WebService. Then we'll build the WebService itself. This way, you don't have to get both projects up and running before you can have any fun at all. </p>
<h2>Building the WebService Client</h2>
<p>So lets start by building a WebService client for an existing Webservice. Just to get our feet wet as it were. If you go to <a title="xmethods" href="http://www.xmethods.com/ve2/index.po" rel="nofollow">Xmethods.com</a> you'll see there are a number of WebServices people have posted links for. We'll use one of these services for starters. </p>
<p>You might notice that I'm being partial here. I've chosen the <a title="Send an Email WebService" href="http://www.xmethods.com/ve2/ViewListing.po?" rel="nofollow" key="uuid:E7B84967-6183-4746-2B3D-E04259314FF5">Send an Email</a>&nbsp;WebService. We'll write a simple client for this WebService. Before we can begin to use any WebService, we need to have the WSDL file. With Delphi, you simply need the URL to a WSDL file. You could use a physical WSDL file as well, but the Expert available to us, allows us to supply the URL to a WSDL file so we'll use this capability. The expert will generate the Interface files for us. </p>
<h2>WSDL File</h2>
<p>Let's take a brief look at the WSDL file. The URL for the WSDL file is <a title="IemailService" href="http://webservices.matlus.com/scripts/emailwebservice.dll/wsdl/IemailService" rel="nofollow">http://webservices.matlus.com/scripts/emailwebservice.dll/wsdl/IemailService</a>. If you're using I.E, you can click on this link to see the WSDL file inside your browser. Without going into too many details (the WSDL spec. can be quite complex for the faint hearted), lets take a look at some of the elements you should be aware of. </p>
<p>
<ol>
<li>The <b>&lt;message&gt;</b> element. The <code>name</code> attribute contains the name of the method with the word <code>Request</code> added to it. This is part of the spec. This is not the element that really tells you the name of the method however. That comes later 
<li>the <b>&lt;part&gt;</b> element's <code>name</code> attribute tells you the name of the parameters while the <code>type</code> attribute tells you the type of the parameters. 
<li>Next, take a look at the next <b>&lt;message&gt; </b>element. The <code>name</code> attribute has the name of the method with the word <code>Response</code> at the end of it. Once again, this is as per spec. 
<li>Under this element the <b>&lt;part&gt; </b>element's <code>name</code> attribute tells you what is being returned and the <code>type</code> attribute tells you the type of this return value. 
<li>The next important element is the <b>&lt;operation&gt; </b>element. This is the element that really gives you the remote method name. In this case <code>SendMail</code>. 
<li>The <b>&lt;soap:operation&gt; </b>element has an attribute called <code>soapAction</code>. You'll see this mentioned once again later in this tutorial. The <code>value</code> of this attribute is generated for you automatically by the Delphi 6 SOAP framework. In particular by the <code>TWSDLHTMLPublish</code> component at the server end. This is the component that actually generated this WSDL file in the first place.(if you examine the URL for this WSDL file, you'll notice that it points to an action in the ISAPI.) 
<li>The <b>&lt;service&gt;</b> element and it's <code>name</code> attribute are the next elements to look at. We'll see these again when building the client later. In particular, when populating the <code>THTTPRIO</code> component's <code>Service</code> and <code>Port</code> properties. </li></li></li></li></li></li></li></ol>
<p>That's probably some of the more important things to look for in a WSDL file when building a Webservice client. Of course, things can get a bit funky when you run into problems with namespaces etc. when dealing with services that were either built according to an older or newer SOAP specification, or different development tool. These are some of the issues you're going to have to live with when living on the bleeding edge of technology. </p>
<p>I'd also like to take this opportunity to highlight another aspect that relates to XML. Now you don't need to get too involved with this at this point in time. It'll all come together soon enough. So if you don't understand it now, it's ok. For the moment there is no real need to <b>have</b> to understand it. I'm talking about <b>Namespaces</b>. Any good book on XML will give you a more detailed explanation. However, I'll explain things as they relate to SOAP and in particular the WSDL file in question. Right at the start of this WSDL file, you'll see some namespaces being declared. In I.E. they will be highlighted in red (You must have wondered about this when you first show the WSDL file right?). Namespaces are declared as attributes of an element. In this case the <b>&lt;definitions&gt;</b> element like</p><pre><code>xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" </code></pre>
<p>
<p>This declaration now gives us a namespace called <b><code>soap</code></b>. Further down in the WSDL file there are a few elements that start with the word <code>soap</code>. For example, <b>&lt;soap:operation&gt;</b>. This is really the <b>&lt;operation&gt;</b> element in the <b><code>soap</code></b> namespace. You can tell this by the virtue of the fact that there is a <b>:</b> (colon) between the word <code>soap</code> and <code>operation</code>. Hope that makes some sense at this point. </p>
<h2>WebService Client Project</h2>
<ol>
<li>Start a new project 
<li>Then <code>File | New | Other</code> 
<li>In the New Items dialog, choose the <code>WebServices</code> tab 
<li>Choose the <code>WebServices Importer</code> 
<li>Click OK </li></li></li></li></li></ol>
<p><a href="http://www.matlus.com/images/FirstWebService1.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService1.jpg" border="0"></a> <br><b>Figure 1: Selecting the WebServices Importer</b> </p>
<p>This should show you the Wizard. </p>
<p><a href="http://www.matlus.com/images/FirstWebService4.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService4.jpg" border="0"></a> <br><b>Figure 2: Showing the WebService Importer Wizard</b> </p>
<p>In the <code>WSDL Location</code> field, type in the URL for the WSDL File for the Send an Email WebService. This should be <code>http://webservices.matlus.com/scripts/emailwebservice.dll/wsdl/IEmailService</code>. Once you've done that (make sure the URL you type in is exactly as shown), click on the <code>Generate</code> button. Delphi will now create a new unit for you and the Interface declaration for the Send an Email WebService. This unit will look like this: </p>
<p>
<div class="codeblockouter">
<div class="codeblockInner"><code></code><pre><font face="Courier New"><font color="#0000ff"><b>Unit</b></font> <font color="#000080">Unit2</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font> <font color="#000080">Types</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>type</b></font>

  <font color="#000080">IEmailService</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>interface</b></font><font color="#ff0000">(</font><font color="#000080">IInvokable</font><font color="#ff0000">)</font>
    <font color="#ff0000">[</font><font color="#008000">'{C355CCC3-4CD4-4577-A0D2-88FBB9B2801E}'</font><font color="#ff0000">]</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">ToAddress</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font> <font color="#0000ff"><b>const</b></font> <font color="#000080">FromAddress</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font> <font color="#0000ff"><b>const</b></font> <font color="#000080">ASubject</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font> <font color="#0000ff"><b>const</b></font> <font color="#000080">MsgBody</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>  <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>


<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>uses</b></font> <font color="#000080">InvokeRegistry</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInterface</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">IEmailService</font><font color="#ff0000">)</font><font color="#ff0000">,</font> <font color="#008000">'urn:EmailIPortTypeInft-IEmailService'</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></div></div><pre></pre>
<p>From the code listing above, you should see that the interface is called <code>IEmailService</code> and that is has one method (a function in this case) called <code>SendMail</code>. This method, expects to see the parameters required to send an email. What is interesting to note is that this <code>Interface</code> is derived from an interface called <code>IInvokable</code>. This is new to Delphi 6. <code>IInvokable</code> is almost exactly the same as <code>IInterface</code> (or <code>IUnknown</code>) which is the base type for all Delphi Interfaces. The key difference is that it is compiled with Run time Type information using the <code>{$M }</code> compiler directive. I mentioned in the previous articles, the Delphi SOAP implementation uses RTTI and Interfaces. This is one part of that equation. </p>
<p>The next thing to note is the <code>initialization</code> section of the unit that was generated. The invocation registry is again new to Delphi 6. The Delphi 6 SOAP framework uses this "registry" to be able to automatically instantiate instances of Invokable classes (classes that implement interfaces derived from IInvokable) and Remoteable classes (we'll get to these in a later tutorial). Needless to say, that if you don't register things that need to be registered, your WebServices will not work. The Online help has a decent explanation of the <code>RegisterInterface</code> method and the parameters expected (most of them are optional). Also notice the <code>stdcall</code> directive. Currently, the Delphi default calling convention (register) is not yet supported. You could use any other calling convention that Delphi supports, such as <code>cdecl, pascal, or safecall</code>. It is not recommended that you use <code>safecall</code> since <code>safecall</code> calls are wrapped with an exception handler by the compiler and this may swallow more exceptions than you'd want to. The default is to use <code>stdcall</code> so I suggest you stick with this.</p>
<p>Lets switch to the main form of the application and drop down a <code>THTTPRIO</code> component on the form. You'll find this component in the WebServices palette. This component has 4 key properties. </p>
<ol>
<li><code>WSDLLocation</code> 
<li><code>Service</code> 
<li><code>Port</code> 
<li><code>URL</code> </li></li></li></li></ol>
<p>You either use the <code>WSDLLocation, Service and Port</code> properties or just the <code>URL</code> property. </p>
<p>
<p>Given a WSDLLocation (URL) the <code>THTTPRIO</code> component is capable of parsing out the WSDL file and populating the <code>Service</code> and <code>Port</code> property dropdown lists. So lets fill in the WSDLLocation with the same URL we used earlier. Now drop down the <code>Service</code> property's combo box and select <code>IEmailServiceservice</code>. Do the same for the <code>Port</code> property and select <code>IEmailServicePort</code>. </p>
<p><a href="http://www.matlus.com/images/FirstWebService2.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService2.jpg" border="0"></a> <br><b>Figure 3: Showing the Object Inspector with the THTTPRIO component's properties populated.</b> </p>
<p>Looking at the parameters required by the <code>SendMail</code> method of the <code>IEmailService</code>, I've built a simple GUI with the required fields as show in <b>Figure 3</b> below. </p>
<p><a href="http://www.matlus.com/images/FirstWebService3.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService3.jpg" border="0"></a> <br><b>Figure 4: Showing the simple GUI for the Send an Email WebService</b> </p>
<h2>The Code</h2>
<p>I've named the unit that Delphi created as <code>EmailIPortTypeInft</code>. You don't need to name it the same, but you do need to add this unit to the <code>uses</code> clause of the <code>implementation</code> section of your form's unit. Once you do this, in the <code>OnClick</code> event of the <code>Send</code> button you need to write some code. </p>
<div class="codeblockouter">
<div class="codeblockInner"><code></code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">uClientMain</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">Windows</font><font color="#ff0000">,</font> <font color="#000080">Messages</font><font color="#ff0000">,</font> <font color="#000080">SysUtils</font><font color="#ff0000">,</font> <font color="#000080">Variants</font><font color="#ff0000">,</font> <font color="#000080">Classes</font><font color="#ff0000">,</font> <font color="#000080">Graphics</font><font color="#ff0000">,</font> <font color="#000080">Controls</font><font color="#ff0000">,</font> <font color="#000080">Forms</font><font color="#ff0000">,</font>
  <font color="#000080">Dialogs</font><font color="#ff0000">,</font> <font color="#000080">StdCtrls</font><font color="#ff0000">,</font> <font color="#000080">Rio</font><font color="#ff0000">,</font> <font color="#000080">SoapHTTPClient</font><font color="#ff0000">,</font> <font color="#000080">ComCtrls</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">TForm1</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TForm</font><font color="#ff0000">)</font>
    <font color="#000080">HTTPRIO1</font><font color="#ff0000">:</font> <font color="#000080">THTTPRIO</font><font color="#ff0000">;</font>
    <font color="#000080">Label1</font><font color="#ff0000">:</font> <font color="#000080">TLabel</font><font color="#ff0000">;</font>
    <font color="#000080">Button1</font><font color="#ff0000">:</font> <font color="#000080">TButton</font><font color="#ff0000">;</font>
    <font color="#000080">txtToAddress</font><font color="#ff0000">:</font> <font color="#000080">TEdit</font><font color="#ff0000">;</font>
    <font color="#000080">Label2</font><font color="#ff0000">:</font> <font color="#000080">TLabel</font><font color="#ff0000">;</font>
    <font color="#000080">txtFromAddress</font><font color="#ff0000">:</font> <font color="#000080">TEdit</font><font color="#ff0000">;</font>
    <font color="#000080">Label3</font><font color="#ff0000">:</font> <font color="#000080">TLabel</font><font color="#ff0000">;</font>
    <font color="#000080">txtSubject</font><font color="#ff0000">:</font> <font color="#000080">TEdit</font><font color="#ff0000">;</font>
    <font color="#000080">MemMessageBody</font><font color="#ff0000">:</font> <font color="#000080">TMemo</font><font color="#ff0000">;</font>
    <font color="#000080">Label4</font><font color="#ff0000">:</font> <font color="#000080">TLabel</font><font color="#ff0000">;</font>
    <font color="#000080">StatusBar1</font><font color="#ff0000">:</font> <font color="#000080">TStatusBar</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">Button1Click</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#808080">{ Private declarations }</font>
  <font color="#0000ff"><b>public</b></font>
    <font color="#808080">{ Public declarations }</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>var</b></font>
  <font color="#000080">Form1</font><font color="#ff0000">:</font> <font color="#000080">TForm1</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#808080">{$R *.dfm}</font>

<font color="#0000ff"><b>uses</b></font>
 <font color="#000080">EmailIPortTypeInft</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>procedure</b></font> <font color="#000080">TForm1</font><font color="#ff0000">.</font><font color="#000080">Button1Click</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">Screen</font><font color="#ff0000">.</font><font color="#000080">Cursor</font> <font color="#ff0000">:=</font> <font color="#000080">crHourGlass</font><font color="#ff0000">;</font>
  <font color="#000080">StatusBar1</font><font color="#ff0000">.</font><font color="#000080">SimpleText</font> <font color="#ff0000">:=</font> <font color="#008000">'Sending Email....'</font><font color="#ff0000">;</font>
  <font color="#000080">StatusBar1</font><font color="#ff0000">.</font><font color="#000080">Refresh</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>try</b></font>
    <font color="#0000ff"><b>if</b></font> <font color="#ff0000">(</font><font color="#000080">HTTPRIO1</font> <font color="#0000ff"><b>as</b></font> <font color="#000080">IEmailService</font><font color="#ff0000">)</font><font color="#ff0000">.</font><font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#000080">txtToAddress</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font> <font color="#000080">txtFromAddress</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font>
      <font color="#000080">txtSubject</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font> <font color="#000080">MemMessageBody</font><font color="#ff0000">.</font><font color="#000080">Lines</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">)</font> <font color="#ff0000">&lt;&gt;</font> <font color="#800080">0</font> <font color="#0000ff"><b>then</b></font>
      <font color="#000080">StatusBar1</font><font color="#ff0000">.</font><font color="#000080">SimpleText</font> <font color="#ff0000">:=</font> <font color="#008000">'Error Sending Email.'</font>
    <font color="#0000ff"><b>else</b></font>
      <font color="#000080">StatusBar1</font><font color="#ff0000">.</font><font color="#000080">SimpleText</font> <font color="#ff0000">:=</font> <font color="#008000">'Email Sent.'</font><font color="#ff0000">;</font>
    <font color="#000080">StatusBar1</font><font color="#ff0000">.</font><font color="#000080">Refresh</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>finally</b></font>
    <font color="#000080">Screen</font><font color="#ff0000">.</font><font color="#000080">Cursor</font> <font color="#ff0000">:=</font> <font color="#000080">crDefault</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>


<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></div></div><pre></pre>
<p>
<p>Basically, you really need just one line of code. Most of the code you see in the OnClick event is really related to GUI frills. The one line of code that really does the work is: </p>
<div class="codeblockouter">
<div class="codeblockInner"><code></code><pre><font face="Courier New">    <font color="#0000ff"><b>if</b></font> <font color="#ff0000">(</font><font color="#000080">HTTPRIO1</font> <font color="#0000ff"><b>as</b></font> <font color="#000080">IEmailService</font><font color="#ff0000">)</font><font color="#ff0000">.</font><font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#000080">txtToAddress</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font> <font color="#000080">txtFromAddress</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font>
      <font color="#000080">txtSubject</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">,</font> <font color="#000080">MemMessageBody</font><font color="#ff0000">.</font><font color="#000080">Lines</font><font color="#ff0000">.</font><font color="#000080">Text</font><font color="#ff0000">)</font> <font color="#ff0000">&lt;&gt;</font> <font color="#800080">0</font> <font color="#0000ff"><b>then</b></font></font>
</pre></div></div><pre></pre>
<p>If you run this application and fill in the values to send yourself an email and hit the send button, you'll receive and email if all goes well.</p>
<h2>Behind the Scenes</h2>So what's happening? First of all, you're using a WebService that is already there for you to use. Because the service exists, you can use it without the need to build it yourself. This is one the reasons that SOAP is so exciting. SOAP has added another dimension to the word "re-usability". 
<p>Behind the scenes, the <code>THTTPRIO</code> component has built a SOAP envelope for you and sent it over to the WebService server. The server knows what to do with this SOAP envelop. This SOAP envelope (for those interested) looks like this: </p>
<div class="codeblockouter">
<div class="codeblockInner"><code></code><pre>POST http://matlus.matlus.com/scripts/emailwebservice.dll/soap/IEmailservice HTTP/1.0<br>Accept: application/octet-stream, text/xml<br>SOAPAction: "urn:EmailIPortTypeInft-IEmailService"<br>Content-Type: text/xml<br>User-Agent: Borland SOAP 1.1<br>Host: matlus.matlus.com<br>Content-Length: 759<br>Proxy-Connection: Keep-Alive<br>Pragma: no-cache<br><br>&lt;?xml version="1.0" encoding='UTF-8'?&gt;<br>  &lt;SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br>    xmlns:xsd="http://www.w3.org/1999/XMLSchema"<br>    xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"<br>    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"&gt; <br>    &lt;SOAP-ENV:Body&gt; <br>      &lt;NS1:SendMail xmlns:NS1="urn:EmailIPortTypeInft-IEmailService" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"&gt; <br>        &lt;NS1:ToAddress xsi:type="xsd:string"&gt;shivk@erols.com&lt;/NS1:ToAddress&gt; <br>        &lt;NS1:FromAddress xsi:type="xsd:string"&gt;Shiv Kumar&lt;shiv@matlus.com&gt;&lt;/NS1:FromAddress&gt; <br>        &lt;NS1:ASubject xsi:type="xsd:string"&gt; Testing&lt;/NS1:ASubject&gt; <br>        &lt;NS1:MsgBody xsi:type="xsd:string"&gt;This is a TEST MESSAGE&lt;/NS1:MsgBody&gt; <br>      &lt;/NS1:SendMail&gt; <br>    &lt;/SOAP-ENV:Body&gt; <br>  &lt;/SOAP-ENV:Envelope&gt;<br></pre></div></div>Let me highlight some of the things you might want/need to know. <br>
<ol>
<li>In the HTTP header take a look at the URL that was constructed - <code>http://matlus.matlus.com/scripts/emailwebservice.dll/soap/Iemailservice</code>. What is key here is the part after the <code>emailwebservice.dll</code>. On the server side, when the Service receives this Request a component called <code>THTTPSOAPDispatcher</code> fields this request (because it has PathInfo <code>/soap</code>). It then hands it over to another component called <code>THTTPPascalInvoker</code>. This component looks up the Invocation Registry and tries to match the name of the interface (<code>IEmailService</code>). If it finds a match, it instantiates an instance of the class that implements this interface. We'll get to this when we build the server side. But you should know, that this is done for you automatically by the Delphi 6 SOAP framework. 
<li>The <code>SOAPAction</code> HTTP header. This is a new HTTP header required for SOAP calls. This is one of the headers that a firewall/proxy can look for to either allow/disallow SOAP calls past it for security reasons. Of course, the SOAP spec. does not make this mandatory. I would guess that in time this header will be mandatory. 
<li>Next, within the XML Document (SOAP envelope) you should see the name of the method. 
<li>You should also see the parameters and values to these parameters that are being sent to the server. </li></li></li></li></ol>
<p>The server processed this packet and responded with another SOAP packet that looks like this </p><code></code>
<div class="codeblockouter">
<div class="codeblockInner"><pre>HTTP/1.1 200 OK<br>Server: Microsoft-IIS/5.0<br>Date: Sat, 14 Jul 2001 07:35:44 GMT<br>Content-Type: text/xml<br>Content-Length: 531<br>Content:<br><br>&lt;?xml version="1.0" encoding='UTF-8'?&gt;<br>  &lt;SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br>    xmlns:xsd="http://www.w3.org/1999/XMLSchema"<br>    xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"<br>    xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/&gt;<br>    &lt;SOAP-ENV:Body&gt;<br>      &lt;NS1:SendMailResponse xmlns:NS1="urn:EmailIPortTypeInft-IEmailService" SOAP-ENV:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/&gt;<br>        &lt;NS1:return xsi:type="xsd:int"&gt;0&lt;/NS1:return&gt;<br>      &lt;/NS1:SendMailResponse&gt;<br>    &lt;/SOAP-ENV:Body&gt;<br>  &lt;/SOAP-ENV:Envelope&gt;<br></pre></div></div>After looking at all of this, I'm sure you'll appreciate the fact that the Delphi 6 SOAP framework hides the HTTP and XML details from you and does all of the hard work while you wrote a simple line of code! 
<p>If you really want to know what all the XML stuff is you'll need to go deeper into the SOAP spec and XML. If you want to be a good SOAP programmer you can't avoid this. For now however, we don't <b>need </b>to know. </p>
<p>What if this WebService was written in Java or C ? How would they know what to do with such as request? In particular, how do they treat <code>IEmailService</code>? As I mentioned in the previous articles, Delphi 6's SOAP implementation uses Interfaces. Other SOAP tool kits don't have to. So they will understand this request the way <b>They</b> need to. SOAP is an implementation and platform agnostic protocol. With WebServices it doesn't matter what tool the service is written in or what platform its running on. Well, this is the ideal scenario. Currently, there are interoperability issues, but we'll get there one day I'm sure. For the most part, things should work just fine. </p>
<p>With the knowledge you've gained so far, you should be able to experiment with other WebServices listed on the XMethods web site. I suggest you do this and then come back here to learn how to build the server for this WebService. </p>
<h2>THTTPRIO Explained</h2>When building a WebService client, the <code>THTTPRIO</code> component is the key component. Therefore, I'd like to explain some of the properties of this component, while we're still playing with the client side. Take a look at <b>Figure 5</b> 
<p>
<p><a href="http://www.matlus.com/images/FirstWebService5.jpg" target="_blank" rel="nofollow"><img height="125" hspace="0" src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService5.jpg" width="78" border="0"></a> <br><b>Figure 5: Showing the Properties of THTTPRIO</b> </p>
<p>We've used the <code>WSDLLocation</code> property, the <code>Service</code> property and the <code>Port</code>. Keep in mind, that for you to be able to use the <code>WSDLLocation</code> in design time (or run time) you need access to the Internet if your <code>WSDLLocation</code> is a URL. Also, you use the <code>Service</code> and <code>Port</code> properties only when using the <code>WSDLLocation</code> property. Instead of using the <code>WSDLLocation</code> property, you could use the <code>URL</code> property. When using the <code>URL</code> property, you don't need (and shouldn't) use the <code>Service</code> and <code>Port</code> properties. The value of the <code>URL</code> property will not be the same as the <code>WSDLLocation</code>. You need to use the proper value in this case. This is the <b><code>SOAP Endpoint URL</code></b>. When looking at SOAP services that listed at sites such as XMethods or SALCentral, you will see the <code>SOAP Endpoint URL</code> listed along with the WSDL file. The <code>THTTPRIO</code> component gets the WSDL file at run time, parses it out and finds the <code>SOAP Endpoint URL</code> in the WSDL File. So it goes without saying, that using the <code>URL</code> property will be slightly faster than using the <code>WSDLLocation</code> property since some round trips are saved. Keep this in mind, if you are making repeated calls to a certain WebService in your applications. Another interesting point to note is that the URL for the WSDL file and the SOAP Endpoint (only for Delphi 6 build WebServices) have a very small difference. The word <code>wsdl</code> is replaced with the word <code>soap</code>. Note that this is by default and that you have the option to change this. </p>
<p>What if you are behind a proxy/firewall either at home or work? Well, then you're going to have some issues that you'll need to circumvent. You won't be able to use the <b>WebService Importer</b> as I explained earlier. What you'll have to do is use your browser to get to the WSDL File. Save it locally, and then use this file (you can use the Browse button) to fill in the <code>WSDLLocation</code> field in the wizard. Once you've done this and the interface file(s) is created for you, your next issue will be when you attempt to fill in the properties of the <code>THTTPRIO</code> component. First, if you look at the properties shown in <b>Figure 5</b>, you'll see that the <code>THTTPRIO</code> component has a <code>Proxy</code> property as well as <code>UserName</code> and <code>Password</code> properties. You'll need to get the details from your Network administrator if you don't know what to fill in here. As an example, if you have a proxy server called <code>MyProxy</code> that uses port 8080, then the <code>Proxy</code> property needs to be filled in as <code>MyProxy:8080</code>. As explained earlier, I suggest you use the <code>URL</code> property instead of the <code>WSDLLocation</code>. If you do plan to use the <code>WSDLLocation</code> property, you need to use the file path and name instead of the URL to this file and most probably, when you deploy your client application, it's going to then need to find this WSDL file as well. </p>
<p>The <code>Agent</code> property is another interesting property. If you look at the HTTP header that was shown earlier, you'll see that the <code>User-Agent</code> HTTP header was <code>Borland SOAP 1.1</code>. Now you're free to change this to whatever else you'd like. I normally use the <code>User-Agent</code> HTTP header to distinguish my client applications from others. If you have to deal with security (proxies/firewalls), the <code>User-Agent</code> HTTP header can come in handy to allow for further filtering. For example, you can tell you network security guys, to allow HTTP requests that have a <code>Content-Type</code> of text/xml <b>ONLY</b> if the <code>User-Agent</code> is xyz and the <code>SOAPAction</code> header is abc. Etc. </p>
<p>The <code>THTTPRIO</code> component can be lifetime managed as a component or as an Interfaced object. It is managed, as a component when its owner is not nil. If you drop it on a form, its owner is the form and so it is managed as a component. This becomes important to know in the following case: </p>
<p>In the <code>OnClick</code> event of code listed above, you'll notice that we've not declared a variable of the type <code>IEmailService</code>. But what if we needed to do this? What if we needed a global variable of this type in our application? Well, we declare a variable of this type in the <code>private</code> section and use it in the <code>OnClick</code> event and elsewhere in our code. When we do this, we need to be sure to nil out this variable in the <code>destructor</code> of the form (or some other appropriate place). The code below shows and example of this. </p>
<div class="codeblockouter">
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>type</b></font>
  <font color="#000080">TForm1</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TForm</font><font color="#ff0000">)</font>
    <font color="#000080">Button1</font><font color="#ff0000">:</font> <font color="#000080">TButton</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">Button1Click</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">FormDestroy</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#000080">EmailService</font><font color="#ff0000">:</font> <font color="#000080">IEmailService</font><font color="#ff0000">;</font>
    <font color="#808080">{ Private declarations }</font>
  <font color="#0000ff"><b>public</b></font>
    <font color="#808080">{ Public declarations }</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>var</b></font>
  <font color="#000080">Form1</font><font color="#ff0000">:</font> <font color="#000080">TForm1</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#808080">{$R *.dfm}</font>

<font color="#0000ff"><b>procedure</b></font> <font color="#000080">TForm1</font><font color="#ff0000">.</font><font color="#000080">Button1Click</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">EmailService</font> <font color="#ff0000">:=</font> <font color="#000080">HTTPRIO1</font> <font color="#0000ff"><b>as</b></font> <font color="#000080">IEmailService</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>procedure</b></font> <font color="#000080">TForm1</font><font color="#ff0000">.</font><font color="#000080">FormDestroy</font><font color="#ff0000">(</font><font color="#000080">Sender</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">EmailService</font> <font color="#ff0000">:=</font> <font color="#0000ff"><b>nil</b></font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<h2>Building the Send an EMail WebService Server</h2>
<p>Before we begin with building the Send an Email Webservice, let me take you through the paces of what we will be doing. </p>
<p>We're going to start a new SOAP Server Application using the Wizard. This essentially produces a Web server extension (CGI, ISAPI etc.) that contains a Web Module and some components on it. This is really very similar to a Web Broker application. We'll choose the ISAPI option. </p>
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> If you're not familiar with ISAPI applications, I suggest you look at the tutorials on my web site related to ISAPI applications. The WebServices you'll build with the help of tutorials on this web site will mostly be ISAPI applications. Your knowledge of ISAPI Applications/debuggin etc. will be leveraged here. If you don't have experience building ISAPI applications, debugging etc. I strongly suggest you read the tutorials on my web site for this before you attempt to build WebServices. This way you'll have a firmer grasp of what is going on and this will save you (and me <g>) endless hours of frustration. 
<p>
<p>I assume you know ISAPI application development and as a result, you will find that I do not explain ISAPI related concepts in any of the WebService tutorials. </p></g></div>
<p>The standard SOAP Server application has three components on it. </p>
<ol>
<li><code>THTTPSOAPDispatcher</code> 
<li><code>THTTPSOAPPascalInvoker</code> 
<li><code>TWSDLHTMLPublish</code> </li></li></li></ol>
<p>The <code>THTTPSOAPDispatcher</code> dispatches all requests that have <code>/soap</code> in the PathInfo. It then hands the request over to <code>THTTPSOAPPascalInvoker</code>. This component really handles the bulk of the process. What is this process? Well, If you take a look at the HTTP request header from earlier, you see, that the full request looks like this: </p><pre><code>
http://matlus.matlus.com/scripts/emailwebservice.dll/soap/IEmailservice
</code>
</pre>
<p>The PathInfo part of this request is: </p><pre>/soap/IEmailservice

</pre>
<p>You learned earlier, that the <code>THTTPSOAPDispatcher</code> handles all requests, with <code>/soap</code> in it and hands it over to the <code>THTTPSOAPPascalInvoker</code>. So the <code>THTTPSOAPPascalInvoker</code> has to do something with <code>/IEMailservice</code>. So what does it do? It looks up the Invocation Registry for any registered Interfaces that match the name IEMailservice. It also parses out the content of the web request (this is the SOAP Packet from earlier) and finds the name of the method and the parameters. Once it has done that, it instantiates an instance of the class that implements this interface and calls the required method handing it the parameters it received. Remember that it's able to do all this using RTTI for interfaces (new to Delphi 6) and some old RTTI magic. Since it receives all this information in the form of a string, it is converting these strings into method calls that instantiate an instance of a class and call the required methods (very much like a scripting engine). When you build a WebService, it is your job to: </p>
<ol>
<li>Define an Interface. 
<li>Implement this interface in a class. 
<li>Register the interface and class with the invocation registry. </li></li></li></ol>
<p>That's it. The Delphi 6 SOAP framework handles the rest of it for you. What's the rest of it you might ask? </p>
<ol>
<li>Parsing the SOAP envelope. 
<li>Instantiating the required class. 
<li>Calling the required method and passing the received (parsed) parameters to it 
<li>Getting back a result from the method. 
<li>Putting the result back in a SOAP response envelope and sending it back out. 
<li>If there is an exception it constructs a SOAP Fault packet instead </li></li></li></li></li></li></ol>
<p>To put it in really simple terms! </p>
<p>I hope this short explanation has cleared things up a bit. If it has, then we're ready to move on and start with building our first Delphi 6 WebService. </p>
<h2>The SOAP Server Application</h2>
<ol>
<li>From the Delphi main menu, choose File | New | Other 
<li>Choose the WebServices tab and choose the SOAP server Application Expert 
<li>In the next dialog, leave the ISAPI/NSAPI (this is the default) Dynamic Link Library option selected and Click OK. </li></li></li></ol>
<p>
<table>
<tbody>
<tr>
<td><a href="http://www.matlus.com/images/FirstWebService6.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService6.jpg" border="0"></a></td>
<td><a href="http://www.matlus.com/images/FirstWebService7.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService7.jpg" border="0"></a></td>
<td><a href="http://www.matlus.com/images/FirstWebService8.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService8.jpg" border="0"></a></td></tr>
<tr>
<td colspan="3"><b>Figure 6: Showing the Steps involved in Creating a New SOAP Server Application</b></td></tr></tbody></table>After doing these steps, you should see something like the last image in <b>Figure 6</b>. I suggest you save this project as EmailWebService and the WebModule unit as MainU.pas. </p>
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> Note: I assume at this point that you know about building ISAPI Applications and debugging them etc. I keep stressing this because I don't want to be flooded with emails asking me questions about WebServices that really pertain to ISAPI applications. I believe the information available on my web site related to ISAPI is more than enough to help you get started with ISAPI applications and get to the point where you can now build WebServices. </div>
<p>
<h2>Defining the Interface</h2>
<p>If you've registered Delphi 6, you should then have access to some of the power toys that will be made available to you. At the time of this writing, I believe they are not yet available. Anyhow, I'll use (one of these toys) the Invokable Wizard that will help in building the WebService. Don't worry, if you don't have this wizard. What it does is it creates two new units for you, one that defines the Interface and the other that defines a class that implements this interface. I'll show you the full units, so you can create them by hand if required. Why have the interface defined in one unit and the implementation in another? Technically, there is obviously no need for this. But if you're building a client for the WebService as well (and 99% of the time you will, only if it's to test the WebService), you can include the unit that declares your interface in the client application's project as well. This will eliminate the need to import the WSDL file (one of the steps we went through while building the client). However, if you want to test your WebService completely, you're better off building the client as we did earlier. That is, treat the client as an independent part of your system, so you know that others attempting to use the WebService will be able to. </p>
<p>The Invokable Wizard can be found in the <code>New Items</code> dialog (File | New | Other | WebServices) as shown in <b>Figure 7</b> below. </p>
<p><a href="http://www.matlus.com/images/FirstWebService9.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService9.jpg" border="0"></a> <br><b>Figure 7: Showing the Invokable Wizard</b> </p>
<p>As Shown in <b>Figure 8</b> below, the Invokable Wizard presents you with another dialog. 
<p><a href="http://www.matlus.com/images/FirstWebService10.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService10.jpg" border="0"></a> <br><b>Figure 8: Showing the dialog the Invokable Wizard presents you with.</b> </p>
<p>I've filled in the values as shown there. You'll notice that the <code>InvokableClass</code> field has a combo box. I've chosen <code>TInvokableClass</code>. The other option is <code>TInterfacedObject</code>. There is a subtle difference between these two. <code>TInvokableClass</code> is derived from <code>TInterfacedObject</code> so it implements QueryInterface, AddRef and ReleaseRef. But it also has a virtual constructor. The fact that it has a virtual constructor allows the compiler to create an instance of the class using RTTI. If you need to derive from <code>TInterfacedObject</code> for some reason, you'll have to implement one extra step in your code (Ill show you that later) and register the class differently (I'll show you that too). All this, so the compiler can instantiate an instance of your class on the fly (That is <code>THTTPSOAPPascalInvoker</code> can instantiate an instance as was described earlier). </p>
<p>The two units thus created are shown below. The first one is the unit that declares the Interface - <code>IEmailService</code> and the next one declares the class that will implement this interface - <code>TEmailService</code>. </p>
<div class="codeblockouter">The unit that declares the <code>IEMailService</code> Interface 
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">EMailServiceIntf</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">Types</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">IEMailService</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>interface</b></font><font color="#ff0000">(</font><font color="#000080">IInvokable</font><font color="#ff0000">)</font>
    <font color="#ff0000">[</font><font color="#008000">'{A987FE00-E596-4733-83BB-E75ACA5FF363}'</font><font color="#ff0000">]</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">InvokeRegistry</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInterface</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">IEMailService</font><font color="#ff0000">)</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<p>
<div class="codeblockouter">The unit that declares the <code>TEMailService</code> class 
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">EMailServiceImpl</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">EMailServiceIntf</font><font color="#ff0000">,</font> <font color="#000080">InvokeRegistry</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">TEMailService</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TInvokableClass</font><font color="#ff0000">,</font> <font color="#000080">IEMailService</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInvokableClass</font><font color="#ff0000">(</font><font color="#000080">TEMailService</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<p>Make a note of the units in the uses clause of both these units and the <code><b>initialization</b></code> section as well. If you're building these units, by hand, I suggest you do so at this point looking at the above listings. </p>
<p>To understand the "Registration" need, I suggest you look at the on-line help for more information. Notice also, that the unit that declares the Interface is very similar to the one that was generated for us using the <code>WebService Importer</code> wizard back when we started with building the client application. Minus the SendMail method and GUID obviously. </p>
<p>Lets go ahead and define the SendMail method as shown in the listing below. </p>
<div class="codeblockouter">
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">EMailServiceIntf</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>
<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">Types</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">IEmailService</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>interface</b></font><font color="#ff0000">(</font><font color="#000080">IInvokable</font><font color="#ff0000">)</font>
  <font color="#ff0000">[</font><font color="#008000">'{C56A3546-DA66-492F-9024-D78D960AB248}'</font><font color="#ff0000">]</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#000080">ToAddress</font><font color="#ff0000">,</font> <font color="#000080">FromAddress</font><font color="#ff0000">,</font> <font color="#000080">ASubject</font><font color="#ff0000">,</font> <font color="#000080">MsgBody</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">InvokeRegistry</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInterface</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">IEmailService</font><font color="#ff0000">)</font><font color="#ff0000">)</font><font color="#ff0000">;</font>


<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<p>Save these units using the names shown (these are the names generated for you by the Wizard if you used it). New to Delphi 6 is the ability to use Code Insight to fill in the methods of an interface in the class that implements the interface. You can even multi-select the methods shown to get Code Insight to write them all out for you as they were declared in the Interface. Note that the units need to be saved for this to work. </p>
<p>So switch to the unit that declares the class the implements the <code>IEMailService</code>, move you cursor under the "T" of <code>TEMailService</code> and hit CTRL Space. You should see the SendMail method listed in the code completion drop down. Select it and hit the Enter key and you'll see that Delphi does the rest for you. Now do the class completion (CTRL SHIFT C) </p>
<p>We're using Indy to do the sending of emails. You'll notice that Indy is now a part of Delphi 6. Those of you who have not used Indy yet, will obviously need to get to know how to use them. Our implementation of sending an email is nothing special, except for the fact that all objects are being created on the fly. You will also need to add the required units to the uses clause of your units. The listing below shows the full unit for the <code>TEmailService</code> class. Remember, this is the class that implements the interface <code>IEmailService</code>. </p>
<div class="codeblockouter">
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">EMailServiceImpl</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">InvokeRegistry</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">,</font> <font color="#000080">EmailIServiceInft</font><font color="#ff0000">,</font> <font color="#000080">IdBaseComponent</font><font color="#ff0000">,</font> <font color="#000080">IdComponent</font><font color="#ff0000">,</font>
  <font color="#000080">IdTCPConnection</font><font color="#ff0000">,</font> <font color="#000080">IdTCPClient</font><font color="#ff0000">,</font> <font color="#000080">IdMessageClient</font><font color="#ff0000">,</font> <font color="#000080">IdSMTP</font><font color="#ff0000">,</font> <font color="#000080">IdMessage</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">TEmailService</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TInvokableClass</font><font color="#ff0000">,</font> <font color="#000080">IEmailService</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>public</b></font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#000080">ToAddress</font><font color="#ff0000">:</font> <font color="#0000ff"><b>String</b></font><font color="#ff0000">;</font> <font color="#000080">FromAddress</font><font color="#ff0000">:</font> <font color="#0000ff"><b>String</b></font><font color="#ff0000">;</font>
      <font color="#000080">ASubject</font><font color="#ff0000">:</font> <font color="#0000ff"><b>String</b></font><font color="#ff0000">;</font> <font color="#000080">MsgBody</font><font color="#ff0000">:</font> <font color="#0000ff"><b>String</b></font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#808080">{ TEmailService }</font>

<font color="#0000ff"><b>function</b></font> <font color="#000080">TEmailService</font><font color="#ff0000">.</font><font color="#000080">SendMail</font><font color="#ff0000">(</font><font color="#000080">ToAddress</font><font color="#ff0000">,</font> <font color="#000080">FromAddress</font><font color="#ff0000">,</font> <font color="#000080">ASubject</font><font color="#ff0000">,</font>
  <font color="#000080">MsgBody</font><font color="#ff0000">:</font> <font color="#0000ff"><b>String</b></font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>const</b></font>
  <font color="#000080">SMTPServer</font> <font color="#ff0000">=</font> <font color="#008000">'smtp-server'</font><font color="#ff0000">;</font> <font color="#808080">{ Change this to your SMTP server }</font>
<font color="#0000ff"><b>var</b></font>
  <font color="#000080">IdSMTP</font><font color="#ff0000">:</font> <font color="#000080">TIdSMTP</font><font color="#ff0000">;</font>
  <font color="#000080">IdSendMsg</font><font color="#ff0000">:</font> <font color="#000080">TIdMessage</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">IdSMTP</font> <font color="#ff0000">:=</font> <font color="#000080">TIdSMTP</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#0000ff"><b>nil</b></font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">IdSendMsg</font> <font color="#ff0000">:=</font> <font color="#000080">TIdMessage</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#000080">IdSMTP</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>try</b></font>
   <font color="#000080">Result</font> <font color="#ff0000">:=</font> <font color="#ff0000">-</font><font color="#800080">1</font><font color="#ff0000">;</font>
   <font color="#0000ff"><b>with</b></font> <font color="#000080">IdSendMsg</font> <font color="#0000ff"><b>do</b></font>
   <font color="#0000ff"><b>begin</b></font>
     <font color="#000080">Body</font><font color="#ff0000">.</font><font color="#000080">Text</font> <font color="#ff0000">:=</font> <font color="#000080">MsgBody</font><font color="#ff0000">;</font>
     <font color="#000080">From</font><font color="#ff0000">.</font><font color="#000080">Text</font> <font color="#ff0000">:=</font> <font color="#000080">FromAddress</font><font color="#ff0000">;</font>
     <font color="#000080">Recipients</font><font color="#ff0000">.</font><font color="#000080">EMailAddresses</font> <font color="#ff0000">:=</font> <font color="#000080">ToAddress</font><font color="#ff0000">;</font>
     <font color="#000080">Subject</font> <font color="#ff0000">:=</font> <font color="#000080">ASubject</font><font color="#ff0000">;</font>
   <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font> <font color="#808080">{ with IdSendMsg do }</font>

   <font color="#0000ff"><b>with</b></font> <font color="#000080">IdSMTP</font> <font color="#0000ff"><b>do</b></font>
   <font color="#0000ff"><b>begin</b></font>
     <font color="#000080">Host</font> <font color="#ff0000">:=</font> <font color="#000080">SMTPServer</font><font color="#ff0000">;</font>
     <font color="#000080">Connect</font><font color="#ff0000">;</font>
     <font color="#0000ff"><b>try</b></font>
       <font color="#000080">Send</font><font color="#ff0000">(</font><font color="#000080">IdSendMsg</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
       <font color="#000080">Result</font> <font color="#ff0000">:=</font> <font color="#800080">0</font><font color="#ff0000">;</font>
     <font color="#0000ff"><b>finally</b></font>
       <font color="#000080">Disconnect</font><font color="#ff0000">;</font>
     <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
   <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font> <font color="#808080">{ with IdSMTP do }</font>
  <font color="#0000ff"><b>finally</b></font>
    <font color="#000080">IdSendMsg</font><font color="#ff0000">.</font><font color="#000080">Free</font><font color="#ff0000">;</font>
    <font color="#000080">IdSMTP</font><font color="#ff0000">.</font><font color="#000080">Free</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font> <font color="#808080">{ try }</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInvokableClass</font><font color="#ff0000">(</font><font color="#000080">TEmailService</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<p>Add these two units to your project and we're almost done now. Pretty simple so far huh? The last thing that's left is getting the service application to respond to SOAP calls and publish the WSDL file. Remember, without a WSDL file, your WebService is practically useless to anyone else. </p>
<h2>TWSDLPublish</h2>
<p>What we need to do is select the <code>TWSDLPublish</code> component on the WebModule and set its <code>AdminEnabled</code> property to true. Now run your application and using a browser, navigate to this URL <code>http://matlus.matlus.com/scripts/EmailWebService.dll/wsdl</code>. Change the domain and path according to your setup. Just be sure you put the <code>/wsdl</code> as a path of the final URL. You should see a screen similar to that shown in Figure 9. </p>
<p>
<p><a href="http://www.matlus.com/images/FirstWebService11.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService11.jpg" border="0"></a> <br><b>Figure 9: Showing the WSDL Administration Page</b> </p>
<p>If you had not set the <code>AdminEnabled</code> property to True, you wouldn't see the <code>Administrator</code> button. Click on the <code>WSDL for IEmailService</code> link. You should now see a WSDL file in your browser. Scroll to the end of the document. You should see that the <code><b>&lt;service&gt;</b></code> element is an <code>empty tag</code> (as per XML definition). If you look at the WSDL file at the URL specified at the start of this tutorial, you should notice that the <code><b>&lt;service&gt;</b></code> element had a child element called <code><b>&lt;port&gt;</b></code> and the <code><b>&lt;port&gt;</b></code> element had a <code><b>&lt;soap:address&gt;</b></code> element as a child like so: </p>
<div class="codeblockouter">
<div class="codeblockInner"><code><pre>&lt;port name="IEmailServicePort" binding="IEmailServicebinding"&gt;
  &lt;soap:address location="http://matlus.matlus.com/scripts/EmailWebservice.dll/soap/IEmailService" /&gt;
</pre></code></div></div>
<p>We need to define the <code>Port</code> for our service. We do that by clicking on the <code>Administrator</code> button and then on the <code>WSDL for IEMailService</code> link. You should see a screen that looks like that shown in <b>Figure 10</b>. </p>
<p><a href="http://www.matlus.com/images/FirstWebService12.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService12.jpg" border="0"></a> <br><b>Figure 10: Showing the Admin Screen that allows for registering a Port for the WebService</b> </p>
<p>In the <code>PortName</code> field enter <code>IEmailServicePort</code> and in the <code>Address</code> field enter <code>http://matlus.matlus.com/scripts/EmailWebservice.dll/soap/IEMailservice</code>. Change the domain name as per your set up. Click the <code>Add</code> button. You should see a screen that looks like that shown in <b>Figure 11</b>. </p>
<p><a href="http://www.matlus.com/images/FirstWebService13.jpg" target="_blank" rel="nofollow"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=FirstWebService13.jpg" border="0"></a> <br><b>Figure 11: Showing the Admin Screen that allows for registering a Port for the WebService</b> </p>
<p>Hit the back button of your browser twice. This should show the URL <code>http://matlus.matlus.com/scripts/EmailWebService.dll/wsdl</code> in your browser. Now if you click on the <code>WSDL for IEMailService</code> link and check the WSDL file thus generated, the <code><b>&lt;service&gt;</b></code> and <code><b>&lt;port&gt;</b></code> elements are as they should be. You should note also, that this operation has generated an <code>.ini</code> file in the <code>/scripts</code> folder (the same folder in which your DLL is installed. This <code>.ini</code> file will have the same name as your ISAPI dll with the words <code>_WSDLADMIN.INI</code> appended to it. The contents of this file should be something like this: </p><pre><code>
[IWSDLPublish]
IWSDLPublishPort=http://matlus.matlus.com/scripts/EmailWebservice.dll/soap/IWSDLPublish

[IEmailService]
IEmailServicePort=http://matlus.matlus.com /scripts/EmailWebservice.dll/soap/IEmailService
</code>
</pre>
<p>When you deploy your WebService to your production server, you either need to go through these steps again, or simply copy this <code>.ini</code> file over to the production server and change the domain name parts in both sections to match that of your production server. Do not forget this step. Without this step, your WebService will be quite un-usable. </p>
<h2>TInvokableClass or TInterfacedObject</h2>
<p>Earlier, I mentioned that if you decide to use <code>TInterfacedObject</code> as the class to derive your implementation class, you'll need to do things differently. Here are the differences and why you need to do them. <code>TInterfacedObject</code> does not have a virtual constructor declared. As a result, there is no way for your application to instantiate an instance of your class at run time when it gets a SOAP request to do so. As usual, there is always an option with Delphi. (These guys think of everything). What you need to do is implement a "Factory" method for your class. This method needs to return an instance of your class as an <code><b>out</b></code> parameter. Further, for the run time to figure it out, you need to register this method when registering the class with the invocation registry so that the application can call this method to get back an instance of your class. This is how you should implement this method and register it. </p>
<div class="codeblockouter">
<div class="codeblockInner"><code><pre><font face="Courier New"><font color="#0000ff"><b>procedure</b></font> <font color="#000080">EMailServiceFactory</font><font color="#ff0000">(</font><font color="#0000ff"><b>out</b></font> <font color="#000080">obj</font><font color="#ff0000">:</font> <font color="#000080">TObject</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">obj</font> <font color="#ff0000">:=</font> <font color="#000080">TEmailService</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInvokableClass</font><font color="#ff0000">(</font><font color="#000080">TEMailService</font><font color="#ff0000">,</font> <font color="#000080">EMailServiceFactory</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div><pre></pre>
<p>Note the change in the call to the <code>RegisterInvokableClass</code> method in the <code>initialization</code> section as well. </p>
<p>Well, that pretty much does it. This tutorial contains more explanation than the actual work involved in building a WebService with Delphi 6. It's really very simple and I hope, after you've read this tutorial, you feel the same. Testing your WebService server is a simple task, now, since you already have a client. All you need to do is change the <code>WSDLLocation</code> property of the <code>THTTPRIO</code> component in your client application (or <code>URL</code> property as the case may be) to match that of your WebService (instead on mine). The projects are available for download as a project group containing the WebService Client project and WebService server project. </p>]]></description><category>Programming</category><category>Delphi</category><category>SOAP</category><category>WebServices</category></item><item><title>Building WebService Clients By Hand</title><pubDate>Tue, 22 Jan 2008 10:45:41 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/tutorials/post/2/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/tutorials/post/2/</guid><description><![CDATA[This tutorial is for Delphi 5 (Pro and Enterprise) as well as Delphi 6 (Pro and Enterprise) users. This Tutorial does not use, or show you how to build WebService clients using the Delphi 6 SOAP framework. Instead, this tutorial is intended for those wanting to have a firmer understanding of SOAP/WebServices as well as show Delphi 5 and Delphi 6 Pro users, how they can build WebService Clients using the tools they've got. 
<p>Having a framework to do all the grunt work for you is great. It saves you a lot of time, hides things from you that you don't need or want to know and brings the fun back into programming. But if you're like me, then you <b>want to do</b> the grunt work initially, so you can get your hands dirty and begin to understand the underpinnings of a certain technology. </p>
<p>Actually doing the work gives you a far better understanding and also surfaces the "facts" and "half-truths" about a certain technology. Further, having actually done it <b>by hand</b>, gives you a better insight into the technology in question. So rub your hands together and get ready for the fun that lies ahead. </p>
<p>The WebService client that we are about to build is a generic SOAP Client. Currently, it can handle WebServices that have one method and expect none or one parameter. Examples of such WebServices are: 
<ol>
<li><a rel="nofollow" href="http://www.xmethods.com/detail.html?" id="98" target="_blank">WhoIS</a> 
<li><a rel="nofollow" href="http://www.xmethods.com/detail.html?" id="93" target="_blank">Shakespearean Insult Generator</a> 
<li><a rel="nofollow" title="Kazoo Training Classes " href="http://www.xmethods.com/detail.html?" id="82" target="_blank">Kazoo Training Classes</a> 
<li><a rel="nofollow" title="WordFind" href="http://www.xmethods.com/detail.html?" id="100" target="_blank">WordFind</a> 
<li><a rel="nofollow" title="FedEx Tracker" href="http://www.xmethods.net/detail.html?" id="15" target="_blank">FedEx Tracker</a> 
<li><a rel="nofollow" title="Delayed Stock Quote" href="http://www.xmethods.net/detail.html?" id="2" target="_blank">Delayed Stock Quote</a> 
<li><a rel="nofollow" title="Domain Name Checker" href="http://www.xmethods.net/detail.html?" id="6" target="_blank">Domain Name Checker</a> </li></li></li></li></li></li></li></ol>These are just some that I have tested. The "result" can be seen in the SOAP Response Page. Generally, the <code><b>&lt;result&gt;</b></code> element contains the result. 
<h3>What will you need to build this project</h3>
<ol>
<li>Delphi 5 Pro/Enterprise or Delphi 6 Pro/Enterprise 
<li>Microsoft <a rel="nofollow" title="Microsoft SOAP toolkit 2.0 Gold Release" href="http://msdn.microsoft.com/downloads/default.asp?" url="/code/sample.asp?" url="/msdn-files/027/001/580/msdncompositedoc.xml" target="_blank">SOAP toolkit 2.0 Gold Release</a> 
<li><a rel="nofollow" title="Indy Version 8.0" href="http://www.nevrona.com/indy" target="blank">Indy version 8.0</a> </li></li></li></ol>
<h3>What will you have learnt by the end</h3>Yes, that's a good question. I mean, what's the point in all the work you're about to do right? 
<ol>
<li>You'll learn how to use the <b>Microsoft DOM Parser, to build and parse XML Documents</b> 
<li>You'll learn how to use the Indy <b>TIdHTTP component</b> 
<li>You'll learn about <b>WSDL Files</b> and how to "read" them 
<li>You'll learn about the <b>SOAP protocol</b> 
<li>You'll learn how to use the I.E. <b>ActiveX Browser control</b> </li></li></li></li></li></ol>
<div class="note">This tutorial, does not expect you to use the Microsoft SOAP toolkit, but rather only use the DOM Parser. If you are familiar with another XML parser, then feel free to use this parser instead. You'll have to make the necessary changes to your code however. </div>
<h3>Importing the MSXML type library</h3>After you've downloaded the Microsoft SOAP Toolkit, you need to import the type library using the Delphi IDE. 
<table cellspacing="2" cellpadding="2">
<tbody>
<tr>
<td align="middle"><a rel="nofollow" href="http://www.matlus.com/images/ImportingMSXML1.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=ImportingMSXML1.jpg" border="0"></a></td>
<td align="middle"><a rel="nofollow" href="http://www.matlus.com/images/ImportingMSXML2.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=ImportingMSXML2.jpg" border="0"></a></td>
<td align="middle"><a rel="nofollow" href="http://www.matlus.com/images/ImportingMSXML3.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=ImportingMSXML3.jpg" border="0"></a></td></tr>
<tr>
<td>Step 1</td>
<td>Step 2 - Select the Library and Click Create Unit</td>
<td>Step 3 - You should see the file in the Editor - Save it</td></tr></tbody></table>
<p>
<h3>Let the games begin</h3>
<div class="note">This tutorial is not yet complete, but the project source files are available for download at the end of this article. </div>
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep1.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep1.jpg" border="0"></a> <br><b>Image1 - The First Step - Get the URL to a WSDL File</b> 
<p>
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep2.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep2.jpg" border="0"></a> <br><b>Image2 - Enter the URL for the WSDL File</b> 
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep3.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep3.jpg" border="0"></a> <br><b>Image3 - Clicking on the Get WSDL Button retrieves the WSDL File, Parses it and populates the fields</b> 
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep4.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep4.jpg" border="0"></a> <br><b>Image4 - If the WebService Method Requires a Parameter, then Enter a Valid Value</b> 
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep5.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep5.jpg" border="0"></a> <br><b>Image5 - Clicking on the Make SOAP Request Button Executes the SOAP method</b> 
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep6.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep6.jpg" border="0"></a> <br><b>Image6 - The SOAP Request that was sent to the WebService</b> 
<p><a rel="nofollow" href="http://www.matlus.com/images/SOAPClientStep7.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=SOAPClientStep7.jpg" border="0"></a> <br><b>Image7 - The SOAP Response that came back from the WebService</b> ]]></description><category>Programming</category><category>Delphi</category><category>SOAP</category><category>WebServices</category></item><item><title>WebServices and Complex Types</title><pubDate>Mon, 21 Jan 2008 10:52:07 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/tutorials/post/3/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/tutorials/post/3/</guid><description><![CDATA[You saw in the previous tutorial - Building your first WebService how simple it it with Delphi 6 to build WebServices. This tutorial assumes you've read that tutorial or know of the things that were discussed there. 
<p>Sending back strings, integers etc. as a result of a WebService method is really simple. You didn't have to do anything special to accomplish this. In this tutorial, we'll see how we can: </p>
<ol>
<li><b>Send</b> back custom objects 
<li>Define and raise custom Exceptions </li></li></ol>
<p>As soon as you read the things we're going to learn how to do in this tutorial, you must have thought to yourself: </p>
<ul>
<li>If we send back an <b>Object</b> how will clients written in tools other then Delphi deal with these objects? 
<li>Riase an Exception? What, on a Remote Client? What if the client is not a Delphi client? How will it know what to do with a Delphi Exception? 
<li>What if the Client is running on a platform other than Windows? </li></li></li></ul>
<p>If you asked any or all of these questions, then you've been paying attention <g>. That's good news. Read on, and you'll have the answers to questions you ask. <p>
<h2>WebService Methods Returning Objects</h2>The WebService we will build in this tutorial has two methods. The WSDL file for this WebService can be found at <a rel="nofollow" href="http://webservices.matlus.com/scripts/XMLDataSetWebService.dll/wsdl/IDatasetXML" target="_blank">http://webservices.matlus.com/scripts/XMLDataSetWebService.dll/wsdl/IDatasetXML</a>. One of these methods (<code>GetSchemaInfo</code>) returns an array of objects. The object is a custom Delphi object. The class declaration of this object is shown below. 
<p>
<div class="codeblockouter">The <code>TFieldInfo</code> object 
<div class="codeblockinner"><code><pre><font face="Courier New"><font color="#0000ff"><b>type</b></font>
  <font color="#000080">TFieldInfo</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TRemotable</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#000080">FIsKeyField</font><font color="#ff0000">:</font> <font color="#000080">Boolean</font><font color="#ff0000">;</font>
    <font color="#000080">FFieldSize</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>
    <font color="#000080">FFieldName</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
    <font color="#000080">FFieldType</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>published</b></font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldName</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldName</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldName</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldType</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldType</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldType</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldSize</font><font color="#ff0000">:</font> <font color="#000080">Integer</font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldSize</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldSize</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">IsKeyField</font><font color="#ff0000">:</font> <font color="#000080">Boolean</font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FIsKeyField</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FIsKeyField</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

  <font color="#000080">TFieldInfoArray</font> <font color="#ff0000">=</font>   <font color="#0000ff"><b>array</b></font> <font color="#0000ff"><b>of</b></font> <font color="#000080">TFieldInfo</font><font color="#ff0000">;</font></font>
</pre></code></div></div>As shown above, <code>TFieldInfoArray</code> is declared as an array of type <code>TFieldInfo</code>. Depending on the number of fields in the table, the method will return those many elements in the array. Take a look at the SOAP Request and Response shown below. 
<p>
<div class="codeblockouter">Showing the HTTP Header and Content (SOAP Request) for the <code>GetSchemaInfo</code> method. 
<div class="codeblockinner"><code><pre>POST http://webservices.matlus.com/scripts/xmldatasetwebservice.dll/soap/IDatasetXML HTTP/1.0
Accept: application/octet-stream, text/xml
SOAPAction: "urn:DatasetXMLIntf-IDatasetXML#GetSchemaInfo"
Content-Type: text/xml
User-Agent: Borland SOAP 1.1
Host: webservices.matlus.com
Content-Length: 535
Proxy-Connection: Keep-Alive
Pragma: no-cache

&lt;?xml version="1.0" encoding='UTF-8'?&gt;
&lt;SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/1999/XMLSchema"
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"&gt;
  &lt;SOAP-ENV:Body&gt;
    &lt;NS1:GetSchemaInfo xmlns:NS1="urn:DatasetXMLIntf-IDatasetXML" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"&gt;
      &lt;NS1:TableName xsi:type="xsd:string"&gt;Customer&lt;/NS1:TableName&gt;
    &lt;/NS1:GetSchemaInfo&gt;
  &lt;/SOAP-ENV:Body&gt;
&lt;/SOAP-ENV:Envelope&gt;
</pre></code></div></div>
<div class="codeblockouter">Showing the HTTP Header and Content (SOAP Response) for the <code>GetSchemaInfo</code> method. 
<div class="codeblockinner"><code><pre>HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Fri, 20 Jul 2001 04:34:23 GMT
Content-Type: text/xml
Content-Length: 4676
Content:

&lt;?xml version="1.0" encoding='UTF-8'?&gt;
&lt;SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/1999/XMLSchema"
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"&gt;
  &lt;SOAP-ENV:Body&gt;
    &lt;NS1:GetSchemaInfoResponse
      xmlns:NS1="urn:DatasetXMLIntf-IDatasetXML"
      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:NS2="http://www.w3.org/2001/XMLSchema"&gt;
      &lt;NS1:return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS2:TFieldInfo[13]"&gt;
        &lt;NS1:item href="#1"/&gt;
        &lt;NS1:item href="#2"/&gt;
        &lt;NS1:item href="#3"/&gt;
        &lt;NS1:item href="#4"/&gt;
        &lt;NS1:item href="#5"/&gt;
        &lt;NS1:item href="#6"/&gt;
        &lt;NS1:item href="#7"/&gt;
        &lt;NS1:item href="#8"/&gt;
        &lt;NS1:item href="#9"/&gt;
        &lt;NS1:item href="#10"/&gt;
        &lt;NS1:item href="#11"/&gt;
        &lt;NS1:item href="#12"/&gt;
        &lt;NS1:item href="#13"/&gt;
      &lt;/NS1:return&gt;
      &lt;NS2:item id="1" xsi:type="NS2:TFieldInfo"&gt;
        &lt;NS2:FieldName xsi:type="xsd:string"&gt;CustNo&lt;/NS2:FieldName&gt;
        &lt;NS2:FieldType xsi:type="xsd:string"&gt;ftFloat&lt;/NS2:FieldType&gt;
        &lt;NS2:FieldSize xsi:type="xsd:int"&gt;0&lt;/NS2:FieldSize&gt;
        &lt;NS2:IsKeyField xsi:type="xsd:boolean"&gt;False&lt;/NS2:IsKeyField&gt;
      &lt;/NS2:item&gt;
      &lt;NS2:item id="2" xsi:type="NS2:TFieldInfo"&gt;
        &lt;NS2:FieldName xsi:type="xsd:string"&gt;Company&lt;/NS2:FieldName&gt;
        &lt;NS2:FieldType xsi:type="xsd:string"&gt;ftWideString&lt;/NS2:FieldType&gt;
        &lt;NS2:FieldSize xsi:type="xsd:int"&gt;30&lt;/NS2:FieldSize&gt;
        &lt;NS2:IsKeyField xsi:type="xsd:boolean"&gt;False&lt;/NS2:IsKeyField&gt;
      &lt;/NS2:item&gt;
      &lt;NS2:item id="3" xsi:type="NS2:TFieldInfo"&gt;
        &lt;NS2:FieldName xsi:type="xsd:string"&gt;Addr1&lt;/NS2:FieldName&gt;
        &lt;NS2:FieldType xsi:type="xsd:string"&gt;ftWideString&lt;/NS2:FieldType&gt;
        &lt;NS2:FieldSize xsi:type="xsd:int"&gt;30&lt;/NS2:FieldSize&gt;
        &lt;NS2:IsKeyField xsi:type="xsd:boolean"&gt;False&lt;/NS2:IsKeyField&gt;
      &lt;/NS2:item&gt;
    &lt;/NS1:GetSchemaInfoResponse&gt;
  &lt;/SOAP-ENV:Body&gt;
&lt;/SOAP-ENV:Envelope&gt;
</pre></code></div></div>
<p><a rel="nofollow" href="http://www.matlus.com/images/DataSetXMLWebService1.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=DataSetXMLWebService1.jpg" border="0"></a> <br><b>Figure 1: Showing part of the WSDL file that defines the complexType</b> 
<p>The SOAP request is a standard request (for this WebService) calling the <code>GetSchemaInfo</code> method and sending it the <code>TableName</code>, <code>Customer</code>. The response by the WebService is what we need to take a closer look at. As I mentioned earlier, this method returns an array of objects. In XML terms, as you can see from the WSDL file or <b>Figure 1</b>, this is a <code><b>complexType</b></code> that is defined as an array. So you see, that the object is really defined like a Delphi record or C/C   struct. When a Delphi client receives this kind of data it gets converted into an object instance (more about this later). The <code>Customer</code> table in this case has 13 fields. You can see this from the HTTP response shown earlier. I've shown only the first 3 fields to save space, but the line: </p>
<div class="codeblockouter">Showing part of the HTTP Header and Content (SOAP Response) that tells us to expect 13 elements in the <code>TfieldInfoArray</code>. 
<div class="codeblockinner"><pre><code>
&lt;NS1:return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS2:TFieldInfo[13]"&gt;
</code></pre></div></div>tells us to expect 13 elements in the array <code>TFieldInfoArray</code>. If the client is a Java Client, then it will handle this response the way it needs to. It may or may not treat this response as an array of objects. That depends on the implementation of the framework used. Delphi 6's SOAP framework works with interfaces and objects. When you do SOAP with Delphi 6, you are really doing Remote Object Invocation. (That's where <code>TRIO</code> got it's name from. This is similar to RMI in Java with the advantage that the protocol is a standard. 
<p><a rel="nofollow" href="http://www.matlus.com/images/DataSetXMLWebService2.jpg" target="_blank"><img src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=1&amp;imagefile=DataSetXMLWebService2.jpg" border="0"></a> <br><b>Figure 2: SOAP is just a Wire Protocol</b> </p>
<p>Remember that SOAP is a wire protocol. What that means is that the actual communication between two end points is taking place using the SOAP protocol. What happens before the message leaves one end and what happens once the messages gets to the other end is left totally up the implementation specific details of the two end points. What is key is that everyone should be on the same page as far as their interpretation of the SOAP specification is concerned. Once the messages gets across the wire it's up to that end point how you deal with it. Even though SOAP has the word <b>Object</b> in it, is not necessary that there are any objects involved. When a Delphi built WebService server receives a SOAP Request, it instantiates an instance of an object. It doesn't matter what kind of client made a request or what platform the client is running on. Similarly, if a WebService responds with a SOAP Response as shown earlier, a Delphi WebService Client, will instantiate an instance of an array of objects with 13 elements in it. It doesn't matter what language the WebService was written in or what platform it is running on. That's just the way Delphi implements SOAP. </p>
<p>We saw in the - <a rel="nofollow" title="Building your First WebService in Delphi" href="http://www.matlus.com/scripts/website.dll/Tutorials?DelphiWebServices&amp;BuildingYourFirstWebservice&amp;3" target="_blank">Building your First WebService</a> tutorial (from here on in reffered to as "the previous tutorial), how Delphi built WebServices and clients figure out what these objects are and how to instantiate them and which objects to instanciate. In this case, the difference is that the WebService is returning an object. How the client figures out what this object is and how to instanciate which object, we'll see later in this tutorial (hint - the object needs to be registered with the Invocation Registry and needs to be derived from a specific class). </p>
<h2>Building the Server</h2>I won't go into the step by step instructions on how to start with building a WebService application with Delphi 6 Enterprise. If you've not built WebServices with Delphi before, I suggest you read the previous Tutorial. 
<p>The first thing we're going to need is to define our Interface. You can use the Wizard (available to registered users) or code the unit by hand. The method <code>GetDatasetAsXML</code> expects to see and SQL SELECT statement as a parameter and it returns the result of the query in the form of an XML document. The second method, <code>GetSchemaInfo</code> expects to see the name of a table (in this case a table that exists in the dbdemos.mdb Access database) and returns the schema of the table in the form of an array of <code>TFieldInfo</code> objects (one element per field). </p>
<p>
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> Returning an XML document as a result of a WebService method is not recommended. This is because the WSDL file indicates that this method will return a string. Someone building a client for this service simply looking at the WSDL file (which is really how WebServices are supposed to work.) will have no indication that this "string" is in fact going to be an XML document. </div>
<p>
<div class="opinion"><img alt="Suggestion.gif" src="http://www.matlus.com/images/Suggestion.gif" border="0"> When designing WebServices it is important to keep the spirit of WebServices. 
<ul>
<li>WSDL - always think, "Will just the WSDL file be enough for anyone else to use my WebService?" 
<li>Interoperability - People using other development tools and/or platforms should be able to access your WebService. </li></li></ul>If you feel you don't need to comply with these two points. You probably don't need to use WebServices. That is, if you're building the client and server for personal consumption, as a result you can ignore the above "requirements", there are probably better solutions for your needs. Remember, XML is a very verbose protocol and as a result tends to be very slow. The number of bytes being transferred between client and server is very large and there is a fair amount of processing on both the client and server in constructing the XML document and parsing it. There are solutions (I'll present one of them soon if I haven't already by the time you read this) that are much lighter than XML and can use HTTP and so still gain the benefits that SOAP provides but require a lot less bandwidth and processing power and as a result are more scalable. If you need to expose and API to a system you're building, to the out side world then WebServices is a good choice. If you're using WebServices for a Client/Server or n-tier system then WebServices is <b>not</b> the answer. You might want to take a look at this article on ZDNet <a rel="nofollow" href="http://techupdate.zdnet.com/techupdate/stories/main/0,14179,2836041,00.html" target="_blank">Fat protocols slow Web services</a>. </div>
<p>
<div class="codeblockouter">The <code>IDataSetXML</code> Interface Unit. 
<div class="codeblockinner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">DatasetXMLIntf</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">Types</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">,</font> <font color="#000080">uFieldInfo</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">IDatasetXML</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>interface</b></font><font color="#ff0000">(</font><font color="#000080">IInvokable</font><font color="#ff0000">)</font>
    <font color="#ff0000">[</font><font color="#008000">'{C7785514-F56F-40AD-B943-950A162296BE}'</font><font color="#ff0000">]</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">GetDatasetAsXML</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">SelectSQL</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">GetSchemaInfo</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">TableName</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">TFieldInfoArray</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">InvokeRegistry</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">InvRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterInterface</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">IDatasetXML</font><font color="#ff0000">)</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div>You should notice that there is an additional unit (<code>uFieldInfo</code>) in the <code>Uses</code> clause of this unit. This is the unit in which the <code>TFieldInfo</code> class is declared. 
<p>
<div class="codeblockouter">The <code>uFieldInfo</code> Unit. 
<div class="codeblockinner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">uFieldInfo</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">InvokeRegistry</font><font color="#ff0000">,</font> <font color="#000080">XSBuiltIns</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">TFieldInfo</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TRemotable</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#000080">FIsKeyField</font><font color="#ff0000">:</font> <font color="#000080">Boolean</font><font color="#ff0000">;</font>
    <font color="#000080">FFieldSize</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>
    <font color="#000080">FFieldName</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
    <font color="#000080">FFieldType</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>published</b></font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldName</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldName</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldName</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldType</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldType</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldType</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">FieldSize</font><font color="#ff0000">:</font> <font color="#000080">Integer</font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FFieldSize</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FFieldSize</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">IsKeyField</font><font color="#ff0000">:</font> <font color="#000080">Boolean</font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FIsKeyField</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FIsKeyField</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

  <font color="#000080">TFieldInfoArray</font> <font color="#ff0000">=</font>   <font color="#0000ff"><b>array</b></font> <font color="#0000ff"><b>of</b></font> <font color="#000080">TFieldInfo</font><font color="#ff0000">;</font>


<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>initialization</b></font>
  <font color="#000080">RemClassRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterXSClass</font><font color="#ff0000">(</font><font color="#000080">TFieldInfo</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">,</font> <font color="#008000">'TFieldInfo'</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">RemTypeRegistry</font><font color="#ff0000">.</font><font color="#000080">RegisterXSInfo</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">TFieldInfoArray</font><font color="#ff0000">)</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">,</font> <font color="#008000">'TFieldInfoArray'</font><font color="#ff0000">)</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>finalization</b></font>
  <font color="#000080">RemClassRegistry</font><font color="#ff0000">.</font><font color="#000080">UnRegisterXSClass</font><font color="#ff0000">(</font><font color="#000080">TFieldInfo</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">RemTypeRegistry</font><font color="#ff0000">.</font><font color="#000080">UnRegisterXSInfo</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">TFieldInfoArray</font><font color="#ff0000">)</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">.</font></font>
</pre></code></div></div>The things to notice here are the <code>initialization</code> and <code>finalization</code> sections, and the fact that the class <code>TFieldInfo</code> is derived from <code><b>TRemotable</b></code>. <code>TRemotable</code> is the base class for classes that can be passed as parameters or return values in a Web Service application. Again, this class is compiled with RTTI and has a virtual constructor that is used by the <code>TPascalInvoker</code> as explained in the previous tutorial. 
<p>
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> For ComplexTypes to work, you need to apply a fix to the <code>WebServExp.pas</code> source code file. This is an unofficial fix that I have made and is not supported. So far I have not seen any repercussions to implementing this fix. When Borland releases a patch or fix for this, please be sure to implement their fix rather than this. The WSDL generated without this fix is not correct as it does not include the definition for the complexTypes. </div>
<div class="codeblockouter">The following code listing shows the unofficial fix for the <code>WebServExp.pas</code> source code File. 
<div class="codeblockinner"><code><pre><font face="Courier New"><font color="#0000ff"><b>function</b></font> <font color="#000080">TWebServExp</font><font color="#ff0000">.</font><font color="#000080">FindSchema</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">ObjectTypeInfo</font><font color="#ff0000">:</font> <font color="#000080">PTypeinfo</font><font color="#ff0000">;</font> <font color="#0000ff"><b>const</b></font>
<font color="#000080">TnsURI</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">Boolean</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>var</b></font>
  <font color="#000080">Index</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">Result</font> <font color="#ff0000">:=</font> <font color="#000080">False</font><font color="#ff0000">;</font>
  <font color="#808080">//Do not register Empty TnsURI or tkSet or any predefined type from XMLSchema</font>
<font color="#808080">{ TODO -oShiv Kumar -cBUG :</font>
<font color="#808080">Complex Types are not generated if this code is NOT commented.</font>
<font color="#808080">Don't know the implications of doing this, but so far have not had issues. }</font>

<font color="#808080">{  if ((TnsURI = '') or (ObjectTypeInfo.Kind = tkSet) or (TnsURI =</font>
<font color="#808080">SXMLSchemaURI_1999) or  (TnsURI = SXMLSchemaURI_2000_10) or</font>
<font color="#808080">    (TnsURI = SXMLSchemaURI_2001))  then</font>
<font color="#808080">  begin</font>
<font color="#808080">    Result := True;</font>
<font color="#808080">    Exit;</font>
<font color="#808080">  end;</font>
<font color="#808080">}</font>
  <font color="#0000ff"><b>for</b></font> <font color="#000080">Index</font> <font color="#ff0000">:=</font> <font color="#800080">0</font> <font color="#0000ff"><b>to</b></font> <font color="#000080">Length</font><font color="#ff0000">(</font><font color="#000080">SchemaArray</font><font color="#ff0000">)</font> <font color="#ff0000">-</font><font color="#800080">1</font> <font color="#0000ff"><b>do</b></font>
  <font color="#0000ff"><b>begin</b></font>
    <font color="#0000ff"><b>if</b></font> <font color="#000080">SchemaArray</font><font color="#ff0000">[</font><font color="#000080">Index</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">TypeInfo</font> <font color="#ff0000">=</font> <font color="#000080">ObjectTypeInfo</font> <font color="#0000ff"><b>then</b></font>
    <font color="#0000ff"><b>begin</b></font>
      <font color="#000080">Result</font> <font color="#ff0000">:=</font> <font color="#000080">True</font><font color="#ff0000">;</font>
      <font color="#000080">Exit</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

  <font color="#808080">//Add new type</font>
  <font color="#000080">Index</font> <font color="#ff0000">:=</font> <font color="#000080">Length</font><font color="#ff0000">(</font><font color="#000080">SchemaArray</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">SetLength</font><font color="#ff0000">(</font><font color="#000080">SchemaArray</font><font color="#ff0000">,</font> <font color="#000080">Index</font><font color="#ff0000"> </font><font color="#800080">1</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">SchemaArray</font><font color="#ff0000">[</font><font color="#000080">Index</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">TypeName</font> <font color="#ff0000">:=</font> <font color="#000080">ObjectTypeInfo</font><font color="#ff0000">.</font><font color="#000080">Name</font><font color="#ff0000">;</font>
  <font color="#000080">SchemaArray</font><font color="#ff0000">[</font><font color="#000080">Index</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">NameSpace</font> <font color="#ff0000">:=</font> <font color="#000080">TnsURI</font><font color="#ff0000">;</font>
  <font color="#000080">SchemaArray</font><font color="#ff0000">[</font><font color="#000080">Index</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">TypeInfo</font> <font color="#ff0000">:=</font> <font color="#000080">ObjectTypeInfo</font><font color="#ff0000">;</font>
  <font color="#000080">SchemaArray</font><font color="#ff0000">[</font><font color="#000080">Index</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">XSGenerated</font> <font color="#ff0000">:=</font> <font color="#000080">False</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font></font>
</pre></code></div></div>
<p>
<h2>More on TRemotable</h2>Some of you might have wondered after seeing the Interface declaration, especially the method: 
<p>
<p>
<div class="codeblockouter">
<div class="codeblockinner"><code><pre><font color="#0000ff"><b>function</b></font> <font color="#000080">GetSchemaInfo</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">TableName</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">TFieldInfoArray</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
</pre></code></div></div>Who is responsible for freeing the instance of <code>TFieldInfoArray</code> that is being returned? If this method were a regular method, then the calling method is responsible. In this case however, the calling method is a remote application, and what's more, it doesn't have to be a Delphi client that calls on this WebService. The answer is that when <code>TRemotable</code> descendants are created in a method that was called remotely using an <code>Invokable interface</code>, the instance is <b>automatically freed</b> after the value of the <code>TRemotable</code> descendant is marshaled for transport back to the client. So you don't need to worry about this aspect of it. 
<p>What if a <code>TRemotable</code> type is a parameter to a method instead of being returned as a result? On the Client end (Delphi Clients), the client is responsible for creating and instance of it before making the method call and freeing the instance after it is finished using it. On the server end, the instance is once again automatically created and freed. Of course, for all of this to work, both the client and server need to register the class with the Invocation Registry. This is very important. Take a look at the on-line help for the methods <code>RegisterXSClass</code> and <code>RegisterXSInfo</code>. </p>
<div class="codeblockouter">The unit <code>DatasetXMLImpl</code> that implements the <code>IDataSetXML</code> Interface. 
<div class="codeblockinner"><code><pre><font face="Courier New"><font color="#0000ff"><b>unit</b></font> <font color="#000080">DatasetXMLImpl</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>interface</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">Classes</font><font color="#ff0000">,</font> <font color="#000080">DatasetXMLIntf</font><font color="#ff0000">,</font> <font color="#000080">InvokeRegistry</font><font color="#ff0000">,</font> <font color="#000080">uFieldInfo</font><font color="#ff0000">,</font> <font color="#000080">DB</font><font color="#ff0000">,</font> <font color="#000080">ADODB</font><font color="#ff0000">,</font> <font color="#000080">msxmldom</font><font color="#ff0000">,</font>
  <font color="#000080">xmldom</font><font color="#ff0000">,</font> <font color="#000080">XMLIntf</font><font color="#ff0000">,</font> <font color="#000080">XMLDoc</font><font color="#ff0000">;</font>

<font color="#0000ff"><b>type</b></font>
  <font color="#000080">ENotSelectSQL</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">ERemotableException</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#000080">FSQLStatememnt</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
    <font color="#000080">FNotes</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
    <font color="#000080">FReason</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>public</b></font>
    <font color="#0000ff"><b>constructor</b></font> <font color="#000080">Create</font><font color="#ff0000">(</font><font color="#000080">IllegalSQLStatement</font><font color="#ff0000">,</font> <font color="#000080">AReason</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>published</b></font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">SQLStatement</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FSQLStatememnt</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FSQLStatememnt</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">Notes</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FNotes</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FNotes</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>property</b></font> <font color="#000080">Reason</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font> <font color="#0000ff"><b>read</b></font> <font color="#000080">FReason</font> <font color="#0000ff"><b>write</b></font> <font color="#000080">FReason</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

  <font color="#000080">TDatasetXML</font> <font color="#ff0000">=</font> <font color="#0000ff"><b>class</b></font><font color="#ff0000">(</font><font color="#000080">TInvokableClass</font><font color="#ff0000">,</font> <font color="#000080">IDatasetXML</font><font color="#ff0000">)</font>
  <font color="#0000ff"><b>private</b></font>
    <font color="#000080">XMLDocument1</font><font color="#ff0000">:</font> <font color="#000080">TXMLDocument</font><font color="#ff0000">;</font>
    <font color="#000080">ADOConnection1</font><font color="#ff0000">:</font> <font color="#000080">TADOConnection</font><font color="#ff0000">;</font>
    <font color="#000080">ADODataset1</font><font color="#ff0000">:</font> <font color="#000080">TADODataset</font><font color="#ff0000">;</font>
    <font color="#000080">DocumentElement</font><font color="#ff0000">:</font> <font color="#000080">IXMLNode</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">CreateDataAccessObjects</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">FreeDataAccessObjects</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">GenerateDataSection</font><font color="#ff0000">(</font><font color="#000080">Dataset</font><font color="#ff0000">:</font> <font color="#000080">TDataSet</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>procedure</b></font> <font color="#000080">GenerateSchemaSection</font><font color="#ff0000">(</font><font color="#000080">Dataset</font><font color="#ff0000">:</font> <font color="#000080">TDataSet</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">GenerateDataAsXML</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>public</b></font>
    <font color="#808080">{ IDatasetXML }</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">GetDatasetAsXML</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">SelectSQL</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
    <font color="#0000ff"><b>function</b></font> <font color="#000080">GetSchemaInfo</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">TableName</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">TFieldInfoArray</font><font color="#ff0000">;</font> <font color="#0000ff"><b>stdcall</b></font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>implementation</b></font>

<font color="#0000ff"><b>uses</b></font>
  <font color="#000080">TypInfo</font><font color="#ff0000">,</font> <font color="#000080">SysUtils</font><font color="#ff0000">;</font>

<font color="#808080">{ TDatasetXML }</font>

<font color="#0000ff"><b>procedure</b></font> <font color="#000080">TDatasetXML</font><font color="#ff0000">.</font><font color="#000080">CreateDataAccessObjects</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">ADOConnection1</font> <font color="#ff0000">:=</font> <font color="#000080">TADOConnection</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#0000ff"><b>nil</b></font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">ADODataset1</font> <font color="#ff0000">:=</font> <font color="#000080">TADODataset</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#0000ff"><b>nil</b></font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">XMLDocument1</font> <font color="#ff0000">:=</font> <font color="#000080">TXMLDocument</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#0000ff"><b>nil</b></font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#000080">ADOConnection1</font><font color="#ff0000">.</font><font color="#000080">Provider</font> <font color="#ff0000">:=</font> <font color="#008000">'Microsoft.Jet.OLEDB.4.0'</font><font color="#ff0000">;</font>
  <font color="#000080">ADOConnection1</font><font color="#ff0000">.</font><font color="#000080">ConnectionString</font> <font color="#ff0000">:=</font> <font color="#008000">'Provider=Microsoft.Jet.OLEDB.4.0;'</font> <font color="#ff0000"> </font>
    <font color="#008000">'Data Source=C:\Program Files\Common Files\Borland Shared\Data\dbdemos.mdb;'</font> <font color="#ff0000"> </font>
    <font color="#008000">'Persist Security Info=False'</font><font color="#ff0000">;</font>
  <font color="#000080">ADOConnection1</font><font color="#ff0000">.</font><font color="#000080">LoginPrompt</font> <font color="#ff0000">:=</font> <font color="#000080">False</font><font color="#ff0000">;</font>
  <font color="#000080">ADOConnection1</font><font color="#ff0000">.</font><font color="#000080">Connected</font> <font color="#ff0000">:=</font> <font color="#000080">True</font><font color="#ff0000">;</font>
  <font color="#000080">ADODataset1</font><font color="#ff0000">.</font><font color="#000080">Connection</font> <font color="#ff0000">:=</font> <font color="#000080">ADOConnection1</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>procedure</b></font> <font color="#000080">TDatasetXML</font><font color="#ff0000">.</font><font color="#000080">FreeDataAccessObjects</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">ADODataset1</font><font color="#ff0000">.</font><font color="#000080">Free</font><font color="#ff0000">;</font>
  <font color="#000080">ADOConnection1</font><font color="#ff0000">.</font><font color="#000080">Free</font><font color="#ff0000">;</font>
  <font color="#000080">XMLDocument1</font><font color="#ff0000">.</font><font color="#000080">Free</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>function</b></font> <font color="#000080">TDatasetXML</font><font color="#ff0000">.</font><font color="#000080">GetDatasetAsXML</font><font color="#ff0000">(</font><font color="#0000ff"><b>const</b></font> <font color="#000080">SelectSQL</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#0000ff"><b>if</b></font> <font color="#000080">AnsiCompareText</font><font color="#ff0000">(</font><font color="#000080">Copy</font><font color="#ff0000">(</font><font color="#000080">SelectSQL</font><font color="#ff0000">,</font> <font color="#800080">1</font><font color="#ff0000">,</font> <font color="#800080">6</font><font color="#ff0000">)</font><font color="#ff0000">,</font> <font color="#008000">'SELECT'</font><font color="#ff0000">)</font> <font color="#ff0000">&lt;&gt;</font> <font color="#800080">0</font> <font color="#0000ff"><b>then</b></font>
  <font color="#0000ff"><b>begin</b></font>
    <font color="#0000ff"><b>raise</b></font> <font color="#000080">ENotSelectSQL</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">(</font><font color="#000080">SelectSQL</font><font color="#ff0000">,</font> <font color="#008000">'Only SELECT SQL Statements are Allowed'</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
  <font color="#000080">CreateDataAccessObjects</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>try</b></font>
    <font color="#000080">ADODataset1</font><font color="#ff0000">.</font><font color="#000080">CommandText</font> <font color="#ff0000">:=</font> <font color="#000080">SelectSQL</font><font color="#ff0000">;</font>
    <font color="#000080">ADODataset1</font><font color="#ff0000">.</font><font color="#000080">Open</font><font color="#ff0000">;</font>
    <font color="#000080">Result</font> <font color="#ff0000">:=</font> <font color="#000080">GenerateDataAsXML</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>finally</b></font>
    <font color="#000080">FreeDataAccessObjects</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>function</b></font> <font color="#000080">TDatasetXML</font><font color="#ff0000">.</font><font color="#000080">GetSchemaInfo</font><font color="#ff0000">(</font>
  <font color="#0000ff"><b>const</b></font> <font color="#000080">TableName</font><font color="#ff0000">:</font> <font color="#000080">WideString</font><font color="#ff0000">)</font><font color="#ff0000">:</font> <font color="#000080">TFieldInfoArray</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>var</b></font>
  <font color="#000080">i</font><font color="#ff0000">:</font> <font color="#000080">Integer</font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">CreateDataAccessObjects</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>try</b></font>
    <font color="#0000ff"><b>with</b></font> <font color="#000080">ADODataset1</font> <font color="#0000ff"><b>do</b></font>
    <font color="#0000ff"><b>begin</b></font>
      <font color="#000080">CommandText</font> <font color="#ff0000">:=</font> <font color="#008000">'SELECT * FROM '</font> <font color="#ff0000"> </font> <font color="#000080">TableName</font><font color="#ff0000">;</font>
      <font color="#000080">Open</font><font color="#ff0000">;</font>
      <font color="#000080">FieldDefs</font><font color="#ff0000">.</font><font color="#000080">Update</font><font color="#ff0000">;</font>
      <font color="#000080">SetLength</font><font color="#ff0000">(</font><font color="#000080">Result</font><font color="#ff0000">,</font> <font color="#000080">FieldCount</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
      <font color="#0000ff"><b>for</b></font> <font color="#000080">i</font> <font color="#ff0000">:=</font> <font color="#800080">0</font> <font color="#0000ff"><b>to</b></font> <font color="#000080">FieldCount</font> <font color="#ff0000">-</font><font color="#800080">1</font> <font color="#0000ff"><b>do</b></font>
      <font color="#0000ff"><b>begin</b></font>
        <font color="#000080">Result</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font> <font color="#ff0000">:=</font> <font color="#000080">TFieldInfo</font><font color="#ff0000">.</font><font color="#000080">Create</font><font color="#ff0000">;</font>
        <font color="#000080">Result</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">FieldName</font> <font color="#ff0000">:=</font> <font color="#000080">Fields</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">FieldName</font><font color="#ff0000">;</font>
        <font color="#000080">Result</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">FieldType</font> <font color="#ff0000">:=</font> <font color="#000080">GetEnumName</font><font color="#ff0000">(</font><font color="#000080">TypeInfo</font><font color="#ff0000">(</font><font color="#000080">TFieldType</font><font color="#ff0000">)</font><font color="#ff0000">,</font><font color="#000080">Integer</font><font color="#ff0000">(</font><font color="#000080">Fields</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">DataType</font><font color="#ff0000">)</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
        <font color="#000080">Result</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">FieldSize</font> <font color="#ff0000">:=</font> <font color="#000080">Fields</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">Size</font><font color="#ff0000">;</font>
        <font color="#000080">Result</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">IsKeyField</font> <font color="#ff0000">:=</font> <font color="#000080">Fields</font><font color="#ff0000">[</font><font color="#000080">i</font><font color="#ff0000">]</font><font color="#ff0000">.</font><font color="#000080">IsIndexField</font><font color="#ff0000">;</font>
      <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font> <font color="#808080">{ for i := 0 to Dataset.FieldCount -1 do }</font>
    <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font> <font color="#808080">{ with Dataset do }</font>
  <font color="#0000ff"><b>finally</b></font>
    <font color="#000080">FreeDataAccessObjects</font><font color="#ff0000">;</font>
  <font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>
<font color="#0000ff"><b>end</b></font><font color="#ff0000">;</font>

<font color="#0000ff"><b>function</b></font> <font color="#000080">TDatasetXML</font><font color="#ff0000">.</font><font color="#000080">GenerateDataAsXML</font><font color="#ff0000">:</font> <font color="#0000ff"><b>string</b></font><font color="#ff0000">;</font>
<font color="#0000ff"><b>begin</b></font>
  <font color="#000080">XMLDocument1</font><font color="#ff0000">.</font><font color="#000080">Active</font> <font color="#ff0000">:=</font> <font color="#000080">True</font><font color="#ff0000">;</font>
  <font color="#000080">DocumentElement</font> <font color="#ff0000">:=</font> <font color="#000080">XMLDocument1</font><font color="#ff0000">.</font><font color="#000080">CreateElement</font><font color="#ff0000">(</font><font color="#008000">'dataset'</font><font color="#ff0000">,</font> <font color="#008000">''</font><font color="#ff0000">)</font><font color="#ff0000">;</font>
  <font color="#808080">{ Set this element as the Document Element }</font>
  <font color="#000080">XMLDocument1</fo