<?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 Articles</title><link>http://exposureroom.com/members/skumar.aspx/</link><atom:link href="http://rss.exposureroom.com/MemberJournalRssProvider.aspx/skumar/articles/" rel="self" type="application/rss+xml" /><description><![CDATA[]]></description><pubDate>Fri, 05 Sep 2008 15:12:07 GMT</pubDate><generator>ExposureRoom RSS Feed Generator v1.0</generator><language>en</language><item><title>Why you Should Not Letterbox your Videos</title><pubDate>Wed, 13 Aug 2008 14:31:06 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/44/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/44/</guid><description><![CDATA[There are a few reasons why you'd want/need to letterbox your videos. However in this article, I present reasons for NOT leterboxing your videos. The two cases in which I feel letterboxing is not desired are as follows:<br>
<ol>
    <li>You want your HD videos (16:9 aspect) to look like Cinemascope film (2.35:1 aspect). Image 1 below shows an example of this.<br>
    </li>
    <li>You've probably encoded your video for DVD/Blu-ray and tweaked those settings for online video and ended up with a video that has an aspect of 4:3 with the picture inside it with the normal aspect but with letterboxing (black bars on the top and bottom). Image 2 below shows an example of this.<br>
    </li>
</ol>
<img alt="Image1: Video is in 16:9 aspect, but picture is in wide screen aspect (2.35:1)" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=6">
<div><span style="font-weight: bold;">Image1: Video is in 16:9 aspect, but picture is in Cinemascope aspect (2.35:1)</span><br>
</div>
<div>&nbsp;</div>
<div><img alt=" Image 2: Picture is in HD aspect (16:9) but video is in SD aspect (4:3)" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=7"> <span style="font-weight: bold;">Image 2: Picture is in HD aspect (16:9) but video is in SD aspect (4:3)</span><br>
</div>
<div>&nbsp;</div>
<div>
<h3>Letter boxing </h3>
</div>
<div>The concept of letterbox was introduced in order to fit film to video or actually your standard (4:3) TV screen. On ExposureRoom, we retain the original dimensions and aspect ratio of your videos, so there is no real need for you to letterbox your video, since there is nothing to try and fit it into. So use this feature to your advantage and make the best of what we offer you.</div>
<div>&nbsp;</div>
<h3>Crop your Cinemascope (2.35:1) Video.</h3>
<div>If the first case above applies to your video (see image 1 above) then I strongly suggest cropping your videos to the desired dimensions using Adobe Premiere Pro CS3, Quicktime Pro,&nbsp;Sorenson Squeeze or other tools. If you've gone through the trouble of shooting within the confines of a 2.35:1 frame, and edited your video with black bars on the top and bottom, why not go through one more step to get the most out of this effort by <span style="font-weight: bold;">cropping your videos</span>? I'll explain why in a moment.<br>
</div>
<div>&nbsp;</div>
<div>
<h3>HD Videos in HD Aspect </h3>
</div>
<div>If the second case above applies to your video (see image 2 above) then the issue really is the wrong encoding settings. Your video is really a 16:9 aspect (SD wide or HD) and you should render it as such. Please look at the article titled, <a href="http://exposureroom.com/help/view.aspx/207/">Getting your videos to show in the correct Aspect</a> in our <a href="http://exposureroom.com/help/">online help</a> section for how to get the correct aspect for your videos.</div>
<div>&nbsp;</div>
<h3>Problems with Letterboxing your Videos</h3>
There are two reasons you should not letter box videos or actually Not crop your videos (as the case may be). In the first case you're intentionally letterboxing but you're not cropping&nbsp; your video to the actual dimensions, and the issues with this are:<br>
<ol>
    <li>The video looks a whole lot better without letterboxing.</li>
    <li>The picture quality is not as good as what it would be if you cropped your video instead of simply letterboxing. </li>
</ol>
The second case has one issue and that is the picture quality is not as good as what it would be if you encoded your video correctly in order to produce a video with the correct dimensions.
<h3>Why the Picture Quality suffers</h3>
<div>You probably know that the <strong>video bit rate</strong> plays a major role in the quality of your video. If you don't understand this, please read the article title, <a href="http://exposureroom.com/help/view.aspx/89/">Encoding Videos for online Viewing</a>. So what does it mean, when you're encoding your video at say 3,500kbps? Before I try and explain what it means, let's establish some points of reference for this discussion. We'll use a video that has been encoded with dimensions of 1280x720 (16:9 aspect) but with letterboxing (see image 1 above), lets also assume that this video has a frame rate of 30p.</div>
<div>&nbsp;</div>
<div>Now when you encode your video at 3,500kbps (kilo bits per second) you're indirectly saying you're using 3,500 kilo bits of information to represent 30 frames or images, where each image has a dimension of 1280x720. Some of you have probably figured out where I'm headed with this, but I'll explain anyway.</div>
<div>&nbsp;</div>
<div>If the dimensions if the video were smaller you'd have more bits to represent each frame. In other words, if you crop your wide screen video to the actual size of the picture rather than leave the letterboxing in place, you'd get a video that has dimensions of 1280x544. Each frame is actually smaller and given the same video bit rate you have more bits available to represent each frame and so the picture quality improves a bit.</div>
<div>&nbsp;</div>
<div><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=8"> <span style="font-weight: bold;">Image 3: Cinemascope aspect (2.35:1) picture and video. For&nbsp;Cinemascope video, crop the video to the correct dimensions.</span><br style="font-weight: bold;">
</div>
<div>&nbsp;</div>
<div>The same applies for case 2 above. If your video is encoded with the correct dimensions, the actual frame size is smaller (for the same given width) since the height is smaller and so once again you have more bits to represent each frame. <br>
</div>
<div>&nbsp;</div>
<div><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=9"><span style="font-weight: bold;">Image 4: HD Video in HD aspect (16:9). Not letterboxing.</span><br>
</div>
<br>
I hope this explanation helps you understand why you <span style="font-weight: bold;">should not</span> use letterboxing for your online videos and in particular on ExposureRoom since we retain the dimensions of your video.]]></description><category>Video</category><category>Aspect Ratio</category><category>HD Video</category><category>Letterboxing</category><category>Widescreen 16:9</category></item><item><title>Getting Your HD Videos to show in the Correct Aspect</title><pubDate>Wed, 25 Jun 2008 08:46:08 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/33/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/33/</guid><description><![CDATA[<h4>The Problem</h4>
<div>One would think that of all things, getting your video to show in the correct aspect ratio&nbsp;would be something that just happens. In reality, we find however that this is not the case. The most common problem people seem to have is what I call a "squished" video. A squished video is one where it seems the video is too tall or that it got squished from the sides (pressed in). Another common problem is that that the video frame is really in 4:3 aspect ratio while the picture (the video) within is in 16:9 but a lot of space is wasted due to letterboxing. In other words, it's not as wide as it should be or the actual video is not the dimensions you expect.&nbsp;<br>
<br>
The image below shows a frame of an HD Video that is in the correct aspect ratio of 16:9.</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=1" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=1&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>This next image shows a frame of the same HD Video but "Squished". Notice that the video is really in a 4:3 aspect ratio and not 16:9 aspect ratio as it should be. Things look taller and thiner (squished).</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=2" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=2&amp;reduced=true" border="0"></a>I </div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>This image shows another common problem. The video picture appears in the correct aspect ratio of 16:9, however the video itself is in a 4:3 aspect ratio. The encoder has compensated for the difference by letterboxing the video, effectively making the video a lot smaller than it should be in order to fit.</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=3" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=3&amp;reduced=true" border="0"></a>&nbsp;</div>
<div>&nbsp;</div>
<h4>Why does something so simple end up being so difficult</h4>
<div>I think these issues stem from a few things that are seemingly disconnected.</div>
<ol>
    <li>The way your camera records and outputs video</li>
    <li>The editing software you use and the abundant choices it offers for encoding, none of which really seem to apply to what you're trying to do. </li>
</ol>
<h4>HD, HDV, Full Raster</h4>
<div>The video output by HD Video cameras comes in at least 3 flavors. This is directly related to the type of HD video your camera captures or outputs. Standard HD (or full HD) is 1920x1080 (16:9 aspect ratio) or also called full raster. Here are some of the HD formats and their raster dimensions.</div>
<div>&nbsp;</div>
<div>
<table style="border: 1px dotted #7f7c75;">
    <tbody>
        <tr>
            <td style="border: 1px dotted #7f7c75;">HDV, XDCAM</td>
            <td style="border: 1px dotted #7f7c75;">1440x1080</td>
        </tr>
        <tr>
            <td style="border: 1px dotted #7f7c75;">AVCHD, XDCAM EX</td>
            <td style="border: 1px dotted #7f7c75;">1920x1080</td>
        </tr>
        <tr>
            <td style="border: 1px dotted #7f7c75;">DVCPro HD</td>
            <td style="border: 1px dotted #7f7c75;">1280x1080</td>
        </tr>
    </tbody>
</table>
</div>
<div>&nbsp;</div>
<h4>Pixel Aspect Ratio</h4>
<div>Before going on, I'd like you to understand another concept. Pixel aspect ratio or PAR. Yes, I do mean pixel aspect ratio and not video aspect ratio. TV screens&nbsp;have rectangular pixels. That is each pixel is wider than it is taller. Wider by a factor of 1.3333333333333333333. So the pixel aspect ratio of TV monitors is 1.3333333333333333333:1. Computer monitors have square pixels (and so a pixel aspect ratio of 1:1). Are you beginning to see where we're going with this? No? Ok, no problem. If you multiplied 1440 x 1.333333333333333333 you'll get 1920. What this means is that a squished video would actually look normal when viewed on a TV monitor, because the TV stretches your video out.</div>
<div><br>
This might actually confuse you more instead of clearing things up, but bear with me a moment. It's important to know that there is a difference between encoding for DVD or Blu-ray and for online viewing. The trick is to keep in mind, that when encoding video for online purposes, be sure to choose the Square Pixel option. That's not the only thing but just one of the things to keep in mind.</div>
<div>&nbsp;</div>
<h4>Video Editing Software</h4>
Video editing software have their own terminology for the various attributes one can choose when attempting to encode video. To further aggravate matters, your editing software most likely compensates for the difference in pixel aspect ratios, while editing and so you don't see the issue at the time of editing but only notice that your video is squished after encoding.
<h4>The Solution&nbsp;</h4>
<div>Finally, here are the settings you should use to ensure your video is rendered with the correct aspect ratio.</div>
<ul>
    <li>Choose <strong>Square pixels</strong>&nbsp; - <em>Do not choose Widescreen 16:9, HD Anamorphic 1080 or any other option</em></li>
    <li>Make sure you choose or set the <strong>correct dimensions </strong>(1920x1080 or 1280x720). For most online video hosting services that support HD video you'd probably choose to encode at 1280x720. </li>
</ul>
<p>The image below shows and annotated version of Adobe Premiere Pro CS3's Media Encoder screen with the wrong settings.</p>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=4" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=4&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>The image below shows and annotated version of Adobe Premiere Pro CS3's Media Encoder screen with the <strong>Correct settings</strong>.</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=5" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=5&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>I hope this article has helped you better understand the cause of your issues and the solution.</div>
<div>&nbsp;</div>
<div class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 12pt; font-family: 'Arial','sans-serif';">I've encoded the same source video using the above two settings so you can see the difference for yourselves.<o:p></o:p></span> The first one is the correct aspect ratio, while the second is the squished aspect ratio version.</div>
<div class="MsoNormal" style="margin: 0in 0in 0pt;">&nbsp;</div>
<div><a href="http://exposureroom.com/members/skumar.aspx/assets/b61032c949084f0e89bc1d47cf3e57f2/" target="_blank"><img title="Click Here to View The Video Titled: Correct Aspect HD Video" alt="Click Here to View The Video Titled: Correct Aspect HD Video" src="http://exposureroom.com/getassetthumbnailimage.aspx?id=b61032c949084f0e89bc1d47cf3e57f2&amp;size=sm" border="0"></a>&nbsp;</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/members/skumar.aspx/assets/a77701f64859431a9c07abf03ced8546/" target="_blank"><img title="Click Here to View The Video Titled: Incorrect Aspect Ratio - HD Video" alt="Click Here to View The Video Titled: Incorrect Aspect Ratio - HD Video" src="http://exposureroom.com/getassetthumbnailimage.aspx?id=a77701f64859431a9c07abf03ced8546&amp;size=sm" border="0"></a></div>]]></description><category>Video</category><category>Aspect Ratio</category><category>HD Video</category><category>Letterboxing</category><category>Widescreen 16:9</category></item><item><title>What are WebServices</title><pubDate>Fri, 11 Jan 2008 14:34:12 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/1/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/1/</guid><description><![CDATA[WebServices are - No wait! I'm not going to give you yet another definition. If you're like me, you'll probably understand it better with as example. That's what I'll try and do. 
<p>So here is a simple example. Lets say, FedEx has a WebService that allows customers to get information regarding a certain package, given the shipment no. So if you access this WebService, call it's method and supply the shipment No. you'll be given the estimated date and time of receiving your package. This sort of thing is easy to perceive in terms of a web site and user interface is it not? Well, WebServices are really very similar except with one key difference. They allow for non-interactive access. That is, machine to machine communication, without the need for human intervention. </p>
<p>Lets say, you were building a large system and one of it's functionalities was to be able to retrieve information about a certain FedEx package given the Shipment No. What you will do then, is use the "service" provided by FedEx to do this non-interactively (without human intervention) through your system. </p>
<p>Lets imagine that there are other similar "services" you could utilize in your system and you'd like to use these services rather than have to build them yourself. Essentially, you are building a system by "re-using" components that someone else has built and made available to you. It does not matter to you, what platform the service is running under or what tool was used to develop it. All you really care about is that you can find out how to use the service. This means your system is effectively decoupled from these "services" since you're not tied to using these services on a certain platform or using a certain development tool. </p>
<p>Lets sum it up now: 
<ol>
<li>Re-useable "components". 
<li>Platform agnostic. 
<li>Implementation agnostic. 
<li>Following certain published specifications/standards. 
<li>Decoupled or loosely coupled. </li></li></li></li></li></ol>That's what WebServices are all about. The ability to build distributed systems that are loosely coupled, dynamically integrated, using re-usable "components". 
<h3>SOAP for the Delphi developer</h3>SOAP (<b>S</b>imple <b>O</b>bject <b>A</b>ccess <b>P</b>rotocol) is an XML application. That's how everyone describes it. I prefer to say, SOAP is an application of XML (i.e. a way in which XML can be used). XML-RPC (XML Remote Procedure Call) is SOAP's predecessor. A company called UserLand Software developed XML-RPC back in 1998. XML-RPC later evolved into SOAP as a more mature protocol and is supported by big names in the IT industry such as, IBM, Microsoft, Sun, Apache etc. 
<h3>Why SOAP</h3>As if we don't already have our plates full with tons of other technologies/buzz words huh? Well, this one really does make sense. To better understand why, we need to take a look at what technologies SOAP intends to replace and the problems with these technologies today. 
<p>Most distributed systems today use technologies such as DCOM and CORBA. Systems built with these technologies are: </p>
<ol>
<li>Tightly coupled. 
<li>Often platform specific and therefore not interoperable. 
<li>Need to be configured on the client machines. 
<li>Have security issues, primarily when it comes to firewalls and the ability to get past them without having to punch holes through them to get them to function normally. </li></li></li></li></ol>SOAP sets out to try and overcome most of the issues cited above. Probably, <b><i>the</i></b> most important aspect of SOAP is not technology, but the fact that everyone (well, everyone that matters or can make a difference) has agreed to work together and formulate standards and adhere to them. The rest of what SOAP is, is really these specifications that everyone has agreed to abide by. So SOAP is not some fancy new technology. It is a simple technology (if you want to call it that), we're only just using our heads this time around, learning from mistakes in the past. Swallowing our egos and pride and making the effort of working with competitors to provide the rest of us with a <b>S</b>imple <b>O</b>bject <b>A</b>ccess <b>P</b>rotocol (that fit quite well didn't it?) 
<p>So SOAP sets out to achieve: </p>
<ol>
<li>Interoperability. 
<li>Decoupled distributed systems. 
<li>Easy access through Firewalls etc. </li></li></li></ol>The need for configuration still remains, as this depends on the software used to build the client applications. Configuration issues related to security will most probably not exist on the client. 
<p>Essentially, if you want to use a "service" you should not need to know the platform on which this service is running and nor should you be concerned about the implementation details. This is very similar to HTTP and Web Browsers. You can use a Web Browser today and surf the world wide web without the need to know what kind of server is serving you the web pages (platform, server vendor etc.) nor how it is serving you these pages (implementation - static pages, dynamic pages, ISAPI, ASP etc.). All you should need to know, is: 
<ol>
<li>What are the methods of the service and parameters to these methods, and the types of these parameters (string, integer etc.) 
<li>If a method is returning some information, then what are the details of that (parameters, types etc.) </li></li></ol>SOAP is a W3C recommendation and is being supported by most of the big names in the industry (IBM, Microsoft, Developmentor, Apache, Sun etc.). To me, it looks like everything is going to be a WebService in some form or the other. Microsoft' s .NET strategy also revolves around SOAP. 
<h3>Wire Protocol</h3>SOAP is a wire protocol. What that means is SOAP is used across the wire or SOAP comes into play between the two end points. When information needs to be sent across the wire, SOAP is used. It doesn't matter what was used to send it across the wire and it doesn't matter what technology is used once it gets to the other end (You are free to use COM/DCOM and/or CORBA etc. at the client end and server end). To this end, SOAP is (transport) protocol agnostic. You're free to use any transport protocol such as, HTTP, FTP, SMTP etc. however, most implementations of SOAP use HTTP as the transport protocol. There are additional specifications for SOAP bindings to HTTP as well. I personally think, HTTP is probably going to be used by 95% of SOAP implementations (but that's my personal opinion). 
<p>For those of you who are interested and know something about HTTP, a typical SOAP packet (including HTTP header) might look like this: </p>
<div class="codeblockouter">Showing a typical HTTP Header and SOAP Envelope. 
<div class="codeblockinner"><pre>POST http://webservices.matlus.com/MyService HTTP/1.0
Accept: application/octet-stream, text/xml
SOAPAction: "urn:MyServiceIntf-IMyService"
Content-Type: text/xml
User-Agent: Borland SOAP 1.1
Host: webservices.matlus.com
Content-Length: 521
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:MethodName xmlns:NS1="urn:MyServiceIntf-IMyService" SOAP-ENV:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/&gt;
      &lt;NS1:MethodParameter xsi:type="xsd:string"&gt;ParameterValue&lt;/NS1: MethodParameter&gt;
    &lt;/NS1:MethodName&gt;
  &lt;/SOAP-ENV:Body&gt;
&lt;/SOAP-ENV:Envelope&gt;
</pre></div></div>Those of you who understand XML may be able to make more sense of this than others. At this point it's not required that you understand this at all. Except that you understand that a SOAP packet or envelope is really XML. 
<h3>Why HTTP as a Transport Protocol</h3>HTTP probably has the largest investment in infrastructure today. The WWW uses HTTP (Web servers) primarily. HTTP is a stateless protocol and so is highly scaleable since it can service 100s even 1000s of requests seemingly simultaneously. Most organizations today have firewalls for protection. HTTP traffic is generally allowed past these firewalls and so SOAP traffic can get in and out without the need to configure firewalls. There are some HTTP headers that SOAP messages must contain and so firewalls can be configured to block SOAP messages if so desired ( The <code><b>SOAPAction</b></code> HTTP header is one of them. If you look at the HTTP Header above, you'll see it there). Currently, SOAP uses port 80, which is the standard for the HTTP protocol. This may change in time, but for now it is port 80. 
<h3>WebService Description Language (WSDL)</h3>This is one of those things that the powers that be have agreed on. A language that is capable of describing a web service. Essentially, the information you are able glean from a WSDL file (it's an XML file) are: 
<ol>
<li>Where is the WebService located (the URL) 
<li>What are the methods available 
<li>What are the parameters and type of these parameters 
<li>What is being returned (if anything) and what are the types </li></li></li></li></ol>Given the above information, it should be simple enough to be able to use this service, without consideration of the platform on which the actual service is running on and it's implementation details. 
<p>Ideally, given a WSDL file for a specific WebService, you should be able to build a client application that uses the services of this WebService. If the SOAP and WSDL specs are adhered to, you have all the information you need to start using the service. Similarly, when you build a WebService, you should make sure you adhere to the SOAP and WSDL specs and publish a WSDL file so others can access your WebService without a problem. </p>
<h3>WebServices Today and Tomorrow</h3>WebServices have been accepted by the IT industry. There is no question about that. This is good, since it means we're all in agreement. That's the first step. As things stand today, the WebServices available to use are primarily toys. People are feeling their way around, building simple to use WebServices, while others build WebService clients to test issues such as interoperability, usage etc. As a Delphi developer, I strongly urge you to part take in this endeavor. There are a number of websites that host WebServices. My new website at <a href="http://www.delphisoap.com/" target="blank" rel="nofollow">http://www.delphisoap.com/</a> is one of them. There are others such as: 
<ol>
<li><a href="http://www.xmethods.com/" target="_blank" rel="nofollow">http://www.xmethods.com/</a>
<li><a href="http://www.salcentral.com/" target="_blank" rel="nofollow">http://www.salcentral.com/</a> </li></li></ol>to name a few. Using these services listed at these sites, one can build clients for these web services using Delphi quite easily. 
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> Please note, that things will not always be smooth sailing. This is due to a number of reasons, some of them are: 
<ol>
<li>Some of these services were built conforming to earlier specs 
<li>Due to constantly changing specs. Delphi implementation may not always be current. I'm sure Borland on their part will do their best to release patches, fixes, upgrades etc. as soon as possible. </li></li></ol></div>There is a lot of work still remaining in the WebServices arena, to make using SOAP in Enterprise level applications feasible. Soon you should see people publishing enterprise level applications of WebServices. There is no doubt in my mind, that WebServices will change the way we look at distributed system in the near future. 
<p>There are about 35-40 implementations of SOAP today. Each employing different methodologies or catering to different platforms and development tools. Most of them are free and most of them do their best to conform to the SOAP spec. At this point in time, differences in conformance are to be expected. </p>
<p><b>Let the games begin!</b> </p>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category><category>WebServices</category></item><item><title>Delphi does WebServices</title><pubDate>Thu, 10 Jan 2008 14:34:12 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/2/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/2/</guid><description><![CDATA[<STRONG>Delphi 6 Enterprise</STRONG> makes building WebServices a breeze. This does not mean that one can't build WebServices with Delphi 6 Pro or even earlier versions of Delphi. It is possible. However, since no framework exists, you'll either have to build one yourself or use a third party toolset if it is available. In this article however, I mean Delphi 6 Enterprise whenever I say "Delphi" or "Delphi 6". Before I go on, I'd also like to say, that in order to build WebServices with Delphi 6, you don't really need to know the finer details of XML, SOAP or WebService. Having a good understanding (of SOAP, WebServices and Delphi's implementation) will most definitely go a long way in better designing, building and debugging WebServices. Please read the article <a rel="nofollow" href="http://www.matlus.com/scripts/website.dll/Tutorials?DelphiWebServices&amp;WhatAreWebServices&amp;1" target="_blank">What are WebServices</A> if you haven't already. This article assumes you read the above mentioned article. 
<H3>Delphi's SOAP Architecture and Implementation</H3>As I said earlier, SOAP itself is implementation agnostic. That said, it is important to realize that different tools implement SOAP differently. This is important to remember, since the way you develop SOAP applications depends on the implementation of the development tools you are using. In this article, I attempt to explain Delphi's implementation and architecture of SOAP and WebServices. 
<P>Before I take you into the SOAP world as Delphi sees it, I'd like to touch upon one of the advantages of exiting distributed technologies such as DCOM, CORBA and Java RMI (Remote Method Invocation). </P>
<P>The one thing that these technologies have in common is the concept of a <B><I>"Stub"</I></B>. In terms of COM and CORBA, this is a type library (IDL). One of the advantages of having a stub, besides the fact that one gets to see the interface of the object (it's methods and their parameters, properties etc.), is that the compiler can help detect errors in code at compile time. In most implementations of SOAP this is one aspect that is missing and developers that have no real need for some of the advantages that SOAP has to offer, see no point in using SOAP simply due to this fact. </P>
<P>Delphi however, has the best of both worlds. Delphi's run time type library has been enhanced and some new classes have been provided to allow for the way SOAP is implemented in Delphi. A brand new interface <CODE><B>IInvokable</B></CODE> two new classes <CODE><B>TRemotable</B></CODE> and <CODE><B>TRIO</B></CODE> and the <CODE><B>Invocation Registry</B></CODE>, make up the core of how Delphi implements SOAP. You can read about these in the on-line help. 
<P>You should also realize, that it is not required, that one accesses an "Object" in a WebService, even though SOAP has the word Object in it. Once a WebService receives a request for a certain method, how it implements this request is totally up to the WebService. It may or may not use an object in its implementation. In Delphi however, we use objects that implement Interfaces. This is not new to the Delphi developer, so when building WebServices with Delphi, you'll find yourself in familiar territory. </P>
<H3>Method Invocation - Object Pascal style</H3>In Delphi WebServices, one actually instantiates an object and invokes its methods, sending it any parameters that may have been sent in the SOAP request. It all happens seamlessly. This aspect of invoking methods and sending it any parameters that the request might contain is handled by <CODE><B>TSOAPPascalInvoker</B></CODE>. In fact, when writing a WebService, you need only to be concerned with describing your interface and implementing it in a class. The framework does the actual instantiation and method invocation automatically. 
<P></P>
<P><a rel="nofollow" href="http://www.matlus.com/images/DelphiWebServiceImpl.jpg" target="_blank"><IMG src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=DelphiWebServiceImpl.jpg" border=0></A> </P><BR><B>Figure 1: Showing the SOAP Request Cycle</B> 
<P>Refer to <B>Figure 1</B> 
<OL>
<LI>A SOAP Request is received by a Delphi built WebService. 
<LI>The SOAP Dispatcher recognizes this to be a SOAP Request and so, hands the Request over to the PascalInvoker. 
<LI>The PascalInvoker, parses the request. After parsing the request, It figures out the class that needs to be instantiated and the method that needs to be called. It instantiates an instance of the required class and calls the appropriate method, sending it any parameters if applicable. </LI></OL>
<P></P>
<P>Similarly, when you build a client for the WebService, and your WebService returns an object, an instance of this class/Interface is automatically created for you. That's great is it not? Yes, that's great when <B>you</B> build a WebService and the client that uses this WebService. What about when someone attempts to use your WebService and he or she is using Java on a Mac for example? Here is the beauty of it. The Delphi implementation conforms to the SOAP spec. So when others call on your WebServices, they don't see anything untoward about the response sent back by a Delphi built WebService. It's the way that a Delphi built client interprets the SOAP message (This is handled for you by <CODE><B>TRIO</B></CODE> or <B>R</B>emote <B>I</B>nterface <B>O</B>bject) that is unique. In other words, when a Delphi built client application receives a SOAP message as a response to a request, it instantiates instances it requires. That's just the way it has been implemented. Similarly, if you build a Delphi client for a non-Delphi built WebService, you still work with objects if that is how the response gets interpreted. So it doesn't really matter what platform the WebService is running under or the tool used to build it. If you build a WebService client in Delphi you work with classes and interfaces. </P>
<H3>The Interface Stub</H3>Given a WSDL file (or URL to a WSDL file) Delphi is capable of interpreting/parsing this WSDL and creating the interface and class stubs for you, no matter what platform or tool the WebService is written in! This makes it really simple to use, since you get compile time checking and further, you see the "Interface" of this WebService in a language that you are familiar with. Did you hear me mention XML anywhere in all of this? That's because, the Delphi architecture handles it all for you. What you "see" is classes and interfaces. The XML stuff happens in the background for you. 
<H3>What about the WSDL</H3>Now lets not forget the importance of publishing the interface to WebServices we develop. This is a key aspect of SOAP. For someone to use our WebService, we need to publish a WSDL file that describes our WebService in terms of a WSDL (as per SOAP Specs.). Now, we really have to work with XML, since a WSDL file is really an XML document. Well, even here, Delphi comes to the rescue. A WebService application you built with Delphi is capable of generating a WSDL file automatically based on the Interface you describe and any special types (also known as complexTypes) you may have declared. So essentially, even this aspect of SOAP is taken care of for you by Delphi. 
<P>I can image that a lot of the things I've said in this article don't make much sense. It seems to be out of context in a way. I suggest you read the next few tutorials and you'll find things will start to fall in place. Unfortunately, there is so much to be said about so many things, that I can't say much about one thing without including the other. So please bear with me. </P>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category><category>WebServices</category></item><item><title>The Multi-Module ISAPI Framework</title><pubDate>Wed, 09 Jan 2008 14:39:04 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/3/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/3/</guid><description><![CDATA[The Matlus Multi-Module ISAPI Frame work allows you to use multiple WebModules in your ISAPI Projects. Due to this, team development of ISAPI applications has been made simple/possible, since each team member can work with her own set of modules to be later seamlessly merged with the main application. But that's not all. The Matlus Multi-Module ISAPI framework has a number of features (that are lacking in WebBroker) built into it. This framework has been built with robust, Industrial strength applications in mind, thus providing required features out of the box. Complimenting the Multi-Module framework is a component suite enables building such systems 
<H2>Basic Concepts</H2>Basically, there is a <B>Multi-Module</B> Project Expert that plugs into the IDE. The options you have in the Expert are: <BR><IMG alt="Showing the Multi-Module ISAPI Expert Dialog" src="http://www.matlus.com/MMFw/images/ExpertDialog.png" border=0> 
<OL>
<LI>The Number of Slave Web Modules for Multi-Module ISAPI project 
<LI>Addtional Components (that are part of my package) 
<LI>Output Folder (such as C:\inetpub\scripts) 
<LI>The Host Application (used for debugging) </LI></OL>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> It should be noted that currently, only the default settings are implemented. That is you can build a multi-module ISAPI extension, you can choose the number of slave modules and you can determine the output folder of the compiled dll and the host application. </DIV>
<P>The expert then builds one Master WebModule (You can have only one Master WebModule per project), and one or more Slave WebModules (in reality, you don't want any slave modules, until you've named your Master Web Wodule. The reason for this will be explained later). There is also a <B>New Slave Module Expert</B> so you can add additional slave modules at a later time. </P>
<P><IMG alt="The Multi-Module framework architecture" src="http://www.matlus.com/MMFw/images/MultiModuleArchitecture.png" border=0> </P>
<DIV class=codeblockouter>The Master WebModule unit the Project Expert Creates 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#808080>{**********************************************}
{  Multi-Module Support for ISAPI Applications }
{       Developed by Shiv R. Kumar (2001)      }
{              Master Web Module               }
{**********************************************}
</FONT><FONT color=#0000ff><B>unit </B></FONT><FONT color=#000080>Unit1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>interface

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>Classes</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>MsMultiModule</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>HTTPApp</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsMasterWebModule1 </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsMasterWebModule</FONT><FONT color=#ff0000>)
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>MsMasterWebModuleCreate</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=#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>MsMasterWebModule1</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</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>TMsMasterWebModule1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsMasterWebModuleCreate</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=#0000ff><B>begin
</B></FONT><FONT color=#808080>{***************************************************************}
{ If you add Slave WebModules to your project, be sure to       }
{ to include a call to the ModuleFactory of the Salve WebModule }
{ Example usage of ModuleFactory                                }
{ ModuleFactory(TMsSlaveWebModule2, True, True);                }
{***************************************************************}
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>.
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<H2>The Dispatching Mechanism</H2>The Master WebModule is an extension of the normal WebBroker WebModule. Therefore it has actions, that function similar to the normal WebModule. Slave WebModules are almost identical to a regular WebModule and so also have their own actions. Both kinds of Web Modules can also have <B>default</B> actions. 
<P>The Master WebModule's dispatcher fields <B>all</B> requests made on the ISAPI Dll. The Master WebModule's dispatcher handles dispatching requests either to itself, or the other Slave WebModules. </P>When a request comes in, the Master dispatcher first tries to determine if the request is for one of it's own actions. If so, it dispatches it to the relevant action. If not, it then tries to determine if the request is for an action in one of the Slave WebModules that have been registered with it. It does this by matching the <B>Class Name</B> (not including the "T") of each of the Slave WebModules and the Request URL (<CODE>PathInfo</CODE>). 
<P>
<P>Lets assume the name of the ISAPI dll is <CODE>Multimodule.dll</CODE>. A URL like this: <PRE>http://www.matlus.com/scripts/multimodule.dll/MyPathInfo
</PRE>will be dispatched to the Master WebModule's action whose <CODE>PathInfo</CODE> is <CODE>/MyPathInfo</CODE>. If an action with this <CODE>PathInfo</CODE> does not exist it will dispatch it to it's default action. On the other hand, a URL like this: <PRE>http://www.matlus.com/scripts/multimodule.dll/SlaveModule1/MyPathInfo
</PRE>will be dispatched to the Slave WebModule whose <CODE>ClassName</CODE> is <CODE>TSlaveModule1</CODE>. The Master WebModule's dispatcher does not try and determine if a corresponding action exists in the Slave WebModule. It simply hands the request over to the Slave WebModule. The Slave WebModule then dispatch the request to the appropriate action. If no action exists, with a matching <CODE>PathInfo</CODE> the Slave WebModule's dispatcher will dispatch it to its default action if one exists. If a default action does not exist, the Request is bounced back to the Master WebModule and will then be handled by the default action of the Master WebModule. The actual handling of a request once it has been dispatched to an action is identical to the way you'd handle it in a normal WebBroker application. That is to say, you code the OnAction event of the actions you define to get the job done. 
<P></P>
<H2>Session Management</H2>The Session Management is comprised of a TMsSessionInfo object. This object holds session information for each session. A TMsSessionBroker object. This object is a thread safe hash table that maintains the list of TMsSessionInfo objects and manages the expiration of sessions etc. For the programmer, the Master WebModule surfaces a TMsSessionManager object. The SessionManager object's methods are similar to the SessionBroker, in that it allows access to an instance of TMsSessionInfo, thereby giving the programmer access to any information stored in the session. Besides a list of Name-Value pairs, the SessionInfo object also has a "Data" property (Pointer). 
<P>The Session Management has been built with Remote Session Management in mind and will allow session information to reside across application and machine boundaries. (there is a Port and Server property available at design time as part of the Master WebModule). <B>This feature has not been implemented as yet</B>, but the hooks are in place. </P>
<P></P>
<DIV class=codeblockouter>Here is a class declaration of the SessionManager object. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#808080>{ TMsSessionManager }
  </FONT><FONT color=#000080>TMsSessionManager </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TPersistent</FONT><FONT color=#ff0000>)
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#000080>FSessionManagerIndentifier</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FSessionManagerTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FSessionBroker</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsSessionBroker</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FCurrentSessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FServer</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FPort</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetSessionIdentifier</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetSessionManagerTimeOut</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionManagerTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetData</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetData</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SessMgrOnBeforeDeleteSession</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=#000080>SessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
  </FONT><FONT color=#0000ff><B>public
    constructor </B></FONT><FONT color=#000080>Create</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>destructor </B></FONT><FONT color=#000080>Destroy</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>override</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>CreateSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>overload</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>CreateSession</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TimeOutInMinutes</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>overload</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>ClearSessionInfo</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>AddSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>DeleteSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>DeleteSession</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionData</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>CurrentSessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FCurrentSessionID </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>FCurrentSessionID</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetData </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>SetData</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>published
    property </B></FONT><FONT color=#000080>SessionTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetSessionManagerTimeOut </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>SetSessionManagerTimeOut</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>SessionIdentifier</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FSessionManagerIndentifier </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>SetSessionIdentifier</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Server</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FServer </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FServer</FONT><FONT color=#ff0000>;</FONT><FONT color=#808080>{ TODO -oShiv -cFuture : To be Implemented }
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Port</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FPort </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FPort</FONT><FONT color=#ff0000>;</FONT><FONT color=#808080>{ TODO -oShiv -cFuture : To be Implemented }
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The Session Management can use Fat URLs, Cookies or Hidden fields. The order of precedence is in that order. By default, the <CODE>SessionIdentifier</CODE> is <CODE><B>sid</B></CODE>, which means when you pass the session id back and forth between the browser and ISAPI, it should be in the form: </P><PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid={12805C36-7ABE-4E4D-B6B5-31C3CA0B9BA8}
  </CODE>
</PRE>In code however, you would do it like this: <PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid=
  </CODE>
</PRE>
<P>If you're using cookies, then it should be in the form</P><PRE>  <CODE>
    sid={12805C36-7ABE-4E4D-B6B5-31C3CA0B9BA8}
  </CODE>
</PRE>
<P>If you're using a hidden field then the name of the field should be <B>sid</B>.</P>
<P>The Master WebModule has a property called <CODE>SessionIdentifier</CODE>. The value is this property is <CODE>sid</CODE> by default. If you change this property to something else, be sure to use this new value everywhere including the special tag <CODE></CODE>.</P>Creating a new session is as simple as: <PRE>  <CODE>
    SessionManager.CreateNewSession;
  </CODE>
</PRE>
<P>The <CODE>CreateNewSession</CODE> method has a default parameter called <CODE>SessionTimeOut</CODE>. This property is defaulted to whatever the Master WebModule's <CODE>SessionTimeOut</CODE> property is. The Session Manager allows for each session to have it's own timeout. If you need to use this feature, you simply set the value at the time of creating a new session. The timeout value is in minutes.</P>
<P>When you create a new session, the <CODE>SessionManager.CurrentSessionID</CODE> is set to a GUID. You should hardly ever need to use this property, since where you need to put the GUID (in html) you can simply use the special tag <CODE></CODE>. </P>
<P>When a Request comes in, the Session Manager automatically puts you in the context of the session. So any operations you do with respect to the Session Manager is with the session that was identified in the URL (or cookie or hidden field). </P>
<P>In practice, you never have to put the GUID in the URL yourself. If the html you send as a Response is in the form </P><PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid=&lt;#sid&gt;
  </CODE>
</PRE>
<P>The Master WebModule will automatically replace the <CODE>&lt;#sid&gt;</CODE> tag with the GUID of the current session. So no matter where you put the <CODE>&lt;#sid&gt;</CODE> tag in your html, it will be replaced by the Master WebModule's in built PageProducer. This PageProducer understands some other tags as well. Such as: </P>
<UL>
<LI>&lt;#scriptname&gt; is replaced by: Request.ScriptName 
<LI>&lt;#sid name="NameOfSessionItem"&gt; is replaced by the <CODE>Value</CODE> of the item 
<LI>&lt;#sid name="sessioninfo"&gt; is replaced by an html page listing all the name=value pairs of the current session </LI></UL>
<P>
<H2>Tagging objects with Sessions</H2>The ability to tag an object with the session is really useful. I've used this to tag a DataModule that contains other component/objects and has it's own methods etc. This ability allows different users to have their own connections to databases, and data access objects, where you might need to have different users connect to different databases (or with different user names). I've used this also in cases where a TMsDataSetTableProducer (the component produces "pages" of a result set, with Paging and navigation etc.) can be used for search results, where each user can potentially get totally different result sets. Besides the fact that you don't need to query the database each time for each user, since each user gets her own instance of a dataset, the cursor remains where you left it, and as a result, you don't need to navigate to the first record only to move to the 200th record say. This speeds the response of the application quite significantly. All in all, Session Management without the ability to tag objects is quite useless in the "real world". 
<P></P>Of course, what good is the ability to tag objects with a session if you don't have the ability to free these objects when the session is deleted? The Master WebModule surfaces an OnBeforeDeleteSession for this purpose. The event prototype looks like this: 
<DIV class=codeblockouter>The OnBeforeDelete event of the Master WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsMasterWebModuleBeforeDeleteSession</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=#000080>SessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin

end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>Since the <CODE>Data</CODE> property is a pointer, you are free to tag any object to the session. It could be an ObjectList or a DataModule that has other objects and Objects lists. </P>
<H2>Additional Events</H2>
<P>In addition to the events of a normal WebModule, the Master WebModule publishes the following events:</P>
<DIV class=codeblockouter>Other Events the Master WebModule surfaces. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnModuleHTMLTag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnModuleHTMLTag </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnModuleHTMLTag </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>FOnModuleHTMLTag</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnException</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TExceptionEvent </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnException </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnException</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnSessionInvalid</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnSessionInvalid </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnSessionInvalid </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnSessionInvalid</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnSessionExpired</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnSessionExpired </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnSessionExpired </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnSessionExpired</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P></P>
<DIV class=codeblockouter>Signatures of some of the additional events. 
<DIV class=codeblockInner><CODE><PRE><FONT face="Courier New">  <FONT color=#000080>TExceptionEvent</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></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=#000080>E</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>Exception</FONT><FONT color=#ff0000>;</FONT> <FONT color=#0000ff><B>var</B></FONT> <FONT color=#000080>Handled</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>Boolean</FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT>
  <FONT color=#000080>TOnSessionInvalid</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></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=#000080>SessionID</FONT><FONT color=#ff0000>:</FONT> <FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT>
  <FONT color=#000080>TOnSessionExpired</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></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=#000080>SessionID</FONT><FONT color=#ff0000>:</FONT> <FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT></FONT>
</PRE></CODE></DIV></DIV>
<P>The Master WebModule has a few "helper" methods as well. They are:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>ExtractMultipleRequestFields</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>FieldName</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetRequestFieldValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>FieldName</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The <CODE>ExtractMultipleRequestFields</CODE> coms in handy when you have a multi-select list box in a form and you need to find out which items were selected (The WebBroker framewrork does not support this out of the box). This method (given the field name) returns the <CODE>StringList</CODE> containing all the <CODE>Values</CODE> that were selected in the list box.</P>
<P>The <CODE>GetRequestFieldValue</CODE> makes processing Requests easier since it decouples code from the need to know the <B>type of method</B> (GET or POST) that was used. Frequently, one needs to process boths kinds of <CODE>Requests</CODE> in a certain action. Internally, this method determines the method type of the Request and uses either the Request.ContentFields property or the Request.QueryFields property and returns the <CODE>Value</CODE> for a given <CODE>Name</CODE>.</P>
<P>The (read only) <B>property</B> <CODE>ModuleName</CODE> returns the Path and File name of the ISAPI Dll. The read access method of this property uses the <B>GetModuleFileName</B> API.</P>
<H2>Handling Special tags - A "Catch All" OnHTMLTag event (built in Page Producer)</H2>Every Response, leaving the application passes through the Master WebModule's internal PageProducer. Besides, processing the tags it understands, as mentioned earlier, the programmers has the opportunity to process tags as well. In case the programmer replaced some tags with tags that this PageProducer understands, these tags will be replaced once again. This makes is really convenient when designing applications, since no matter where (which module) you put these tags, they can be processed at a single point if required. Or no matter where you put in the special tags that the Session Manager understands (as listed above), they are guaranteed to be processed by the Master WebModule. 
<H2>Communicating between Slave WebModules and the Master WebModule</H2>To create a new Slave Module, you use the New Slave WebModule Expert. This expert creates a WebModule whose class looks like this: 
<P>
<DIV class=codeblockouter>The unit generated by the New Slave WebModule Expert. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#808080>{**********************************************}
{  Multi-Module Support for ISAPI Applications }
{       Developed by Shiv R. Kumar (2001)      }
{               Slave Web Module               }
{**********************************************}
</FONT><FONT color=#0000ff><B>unit </B></FONT><FONT color=#000080>Unit2</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>interface

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>Classes</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>MsMultiModule</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>HTTPApp</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Unit1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsSlaveWebModule2 </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsSlaveWebModule</FONT><FONT color=#ff0000>)
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#808080>{ private declarations }
  </FONT><FONT color=#0000ff><B>public
    property </B></FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1 </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>;
    </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>MsSlaveWebModule2</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>implementation

</B></FONT><FONT color=#808080>{$R *.DFM}

</FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>begin
  </B></FONT><FONT color=#000080>Result </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>MasterWebModule</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>
</CODE></PRE></DIV></DIV>
<P>Notice that the expert has included the Master WebModule's unit (<CODE>Unit1</CODE> in this case) in the uses clause of the <B><CODE>Interface</CODE></B> section. Notice also, that the (read only) <B>property</B> <CODE>Master</CODE>, returns a type <CODE>TMsMasterWebModule1</CODE>. This happens to be the class name of the Master WebModule at the time of creating the new Slave WebModule.</P>
<P></P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> It is therefore recommended that one should first name and save the Master WebModule (class and unit) before creating additional Slave WebModule. The Expert will then use the unit name and class name when generating the code for the Slave WebModule class. </DIV>
<P></P>So essentially, <B>All</B> Slave WebModules, have a <B>property</B> called <CODE>Master</CODE>, that returns a reference to the Master WebModule instance. So when you need to reference the Master WebModule's Session Manager, your code would look like this: 
<DIV class=codeblockouter>Referencing the Master WebModule's Session Manager from a Slave WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsSlaveWebModule2WebActionItem1Action</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=#000080>Request</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebRequest</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Response</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebResponse</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>Handled</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Boolean</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
  </B></FONT><FONT color=#808080>{ Adding "ProductID" to the Current Session as received from a Posted Form }
  </FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>SessionManager</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>AddSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'ProductID'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>GetRequestFieldValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'ProductID'</FONT><FONT color=#ff0000>));
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<H2>Registering Slave WebModules</H2>Each time you add a new Slave WebModule to your project, you need to register it with the Master Module's Module Factory. An example of the code you need to use is provided as comments in the OnCreate event of the Master WebModule. For the Slave WebModule class shown above, the code would look like this: 
<DIV class=codeblockouter>Registering Slave WebModules with the Master WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#000080>ModuleFactory</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>True</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>True</FONT><FONT color=#ff0000>);
</FONT></FONT>
</CODE></PRE></DIV></DIV>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>Best Practice - Using the TPageProducer Component</title><pubDate>Tue, 08 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/4/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/4/</guid><description><![CDATA[In my experience with Delphi's WebBroker framework since Delphi 3, I've found the TPageProducer to be the single most useful component (out of the box). I have put this component to many uses in many different applications. Over a period of time, I've come up with a set of rules that define the ways in which I use this component. In this article, I'd like to show you, what I think is the best way to use this component. 
<H2>Fixing A Minor Flaw</H2>Before we look at the "best practice" use of this component, I'd like to highlight a flaw (in my opinion) in the component. When the component encounters a tag that you don't process (in the OnHTMLTag Event), it "swallows" this tag. This behavior prevents you from being able to chain page producer one after the next (which by the way is a good use of this component). If you're not familiar with the use of the TPageProducer, I suggest reading the tutorial titled - Using Cookies Hidden Fields and the TPageProducer. 
<P>To circumvent this issue in the OnHTMLTag event of your PageProducer, you could have code like this:</P>
<DIV class=codeblockouter>Circumventing the "flaw" in the TPageProducer 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TForm1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>PageProducer1HTMLTag</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=#000080>Tag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TTag</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>ReplaceText</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
  if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'sometag'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'Something'
  </FONT><FONT color=#0000ff><B>else
  begin
    if </B></FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Text </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'' </FONT><FONT color=#0000ff><B>then
      </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;#%s&gt;'</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>])
    </FONT><FONT color=#0000ff><B>else
      </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;#%s %s&gt;'</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Text</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>
</CODE></PRE></DIV></DIV>
<P></P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No:1 HTML should not be mixed in with code. </DIV>In real world Applications, I don't like to have HTML mixed with code in my ISAPI applications. This "rule" has a number of benefits: 
<OL>
<LI>Makes the code cleaner and therefore more maintainable/manageable. 
<LI>Speeds up the application quite a bit. (Due primarily to the intricacies related to string handling in 32 bit Delphi) 
<LI>Allows the use of HTML designers (designers being either tools or people) to design the "templates", while you the programmer can code the business rules. (yea right if only we were that lucky!) 
<LI>Allows for changing the page layout of your web sites/applications without the need to re-compile the application. </LI></OL>
<P>The TPageProducer has a property called HTMLFile. You should use this property to load up static html templates at run time. If you're having problems loading up files/images at run time due to "path" issues, I suggest reading the article titled - Relative/Virtual Paths Explained.</P>
<H2>Defining a Language</H2>
<P>I won't go into HTML/JavaScript specific things here, but rather talk about how templates should be designed from the perspective of using a TPageProducer to "process" templates.</P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No:2 Define a minimal "tag language" that you use over and over again across applications. </DIV>This rule goes a very long way in: 
<OL>
<LI>Streamlining your templates 
<LI>Making your templates more readable/maintainable/configurable 
<LI>When working in a team where there are HTML designers (people) they start to understand your "language" and can start to apply it in templates they build for you. </LI></OL>
<P>So what is this language about? It's simple really. It's tags that you "re-use". Tags that have "attributes" that when set control the "behavior" of the processing. Kind of like an object that has properties and setting different properties change the behavior slightly. The more generic you make your tags, the more reusable they become.</P>In the process of building web applications, there are quite a few things we seem to repeat. For example: 
<OL>
<LI>We use Request.ScriptName wherever we need the "path" of our application to be included in things like hyperlinks, form actions and the like. 
<LI>The action attribute of forms. 
<LI>The target attribute of forms. 
<LI>The src attribute of images. </LI></OL>For such needs I suggest you use tags like: <CODE>&lt;#scriptname&gt;</CODE> 
<P>All your page producers should "understand" this tag (Or at least one PageProducer in your application should). In the OnHTML event you could have code like the following:</P><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>If </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'scriptname'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
  </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Scriptname</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE>
<P>Similarly for the "form" tag <CODE>&lt;#form action="" target="" method=""&gt;</CODE></P><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'form'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
  </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;form action="%s" target="%s" method="%s" /&gt;'</FONT><FONT color=#ff0000>, [
    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'action'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'target'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'method'</FONT><FONT color=#ff0000>]]);
</FONT></FONT>
</CODE></PRE>
<P>This kind of tag gives you the flexibility to define attributes in your template while also giving you the flexibility to change them later. Granted, if you're using templates, you could simply change them there (the hard coded value of a form action say). But believe you me a time will come, when you wished you used tags in the template! For example, you might need to change either the target or the action of the form depending on some condition. Instead of having two similar templates (that need to be synchronized each time there is a change) you can have just one.</P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No: 3 - Get used to coding your html in xhtml style. That is all tags and attributes in lowercase, all attribute values within double quotes and all empty tags closed. </DIV>
<H2>Designing Templates</H2>As our first exercise we'll look at some design aspects related to templates for HTML Forms. This form may contain various "controls" to allow for data entry. I propose the following: 
<OL>
<LI>All &lt;input&gt; elements will have one and only one tag. 
<LI>All &lt;select&gt; elements will have one and only one tag. </LI></OL>
<P>Of course one could go a step further and say that we need have only one tag for ALL controls. This is the kind of thing I do personally in fact. But I have a component that does this for me (and a lot more). But for this discussion we'll stick to the 2 proposed above.</P>
<P>We won't be talking about the html aspects of the design here (the look and feel). We'll only look at the tags involved. The tags shown below can satisfy our needs for any type of &amp;lg;input&gt; tag we need in our forms:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#ff0000>&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etText</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>10</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>10</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etHidden</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>0</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etCheckBox</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>caption</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>bar</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>checked</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>false</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>caption</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>bar</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>checked</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>false</FONT><FONT color=#ff0000>" /&gt;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>It goes without saying that this is only one tag. As a result, we can process these tags using one conditional statement in our code. It's the attributes that make all the difference. The code that processes these tags might look like this:</P>
<DIV class=codeblockouter>Sample code to process the proposed Tag Language. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsHTMLElementType </FONT><FONT color=#ff0000>= (</FONT><FONT color=#000080>etText</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etHidden</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etComboBox</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etLookUpCombo</FONT><FONT color=#ff0000>,
    </FONT><FONT color=#000080>etMemo</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etCheckBox</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etButton</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etLabel</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>TypInfo</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TForm1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>PageProducer1HTMLTag</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=#000080>Tag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TTag</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>ReplaceText</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>const
  </B></FONT><FONT color=#000080>sHTMLTextInput </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'&lt;input type="%s" name="%s" value="%s" maxlength="%s" /&gt;'</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#000080>sHTMLCheckRadio </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'&lt;input type="%s" name="%s" value="%s" maxlength="%s"%s /&gt;nbsp;%s'</FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>var
  </B></FONT><FONT color=#000080>sChecked</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
  </FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>begin
  If </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'input'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    case </B></FONT><FONT color=#000080>TMsHTMLElementType</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>GetEnumValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TypeInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsHTMLElementType</FONT><FONT color=#ff0000>), </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'type'</FONT><FONT color=#ff0000>])) </FONT><FONT color=#0000ff><B>of
      </B></FONT><FONT color=#000080>etText    </FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'text'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'password'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etHidden  </FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'hidden'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etCheckbox</FONT><FONT color=#ff0000>,
      </FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>:
        </FONT><FONT color=#0000ff><B>begin
          if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'type'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>'etCheckBox'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
            </B></FONT><FONT color=#000080>sRadioOrCheck </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'checkbox'
          </FONT><FONT color=#0000ff><B>else
            </B></FONT><FONT color=#000080>sRadioOrCheck </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'radio'</FONT><FONT color=#ff0000>;
          </FONT><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'checked'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>'true'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
            </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLCheckRadio</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
              </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>' checked="checked"'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'caption'</FONT><FONT color=#ff0000>]])
          </FONT><FONT color=#0000ff><B>else
            </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLCheckRadio</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
              </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>''</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'caption'</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>
</CODE></PRE></DIV></DIV>
<P></P>
<P>Similarly, you could define a tag that (depending) on an attribute can become either a Combo Box or a List Box. Better yet, if it's a list box, whether it's a multi-select list box or a normal list box. You can then go on to define a "data aware" combo box tag that will allow you to define the stored procedure to use to populate it, the "name" field, then "value" field and so on.</P>
<P>Sooner or later you're going to want to build a specialized descendant component that does all of this for you thus allowing you to reuse your vocabulary. That's what object oriented programming is about. So don't let anyone stop you!</P>
<P>One could go in all sorts of directions with this concept. For instance, you could define a template that has a special tag like so:</P>
<P><CODE>&lt;#embedtemplate filename=""&gt;</CODE></P>
<P>buried deep inside it somewhere. The filename attribute is the name of another template, a template for an html form for instance. That way, the same basic template can be used over and over throughout your system. You could even determine the embedded template to use at run time. Or the template to use is determined by the value of a parameter in the URL or content fields of a posted form. It's up to you really. But where ever you do, make sure the concept is re-usable and is generic enough to be reusable. Give a lot of thought to naming your tags and the attributes they can/should have.</P>
<P></P>
<DIV class=codeblockouter>A sample Template that allows for embeding other templates. 
<DIV class=codeblockInner><PRE><CODE>
&lt;html&gt;
  &lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="&lt;#statevar name="StyleSheet"&gt;
    &lt;title&gt;&lt;#title&gt;&lt;/title&gt;
    &lt;script&gt;
    &lt;#script&gt;
    &lt;/script&gt;
  &lt;/head&gt;
&lt;#body&gt;
  &lt;table border="0" cellpadding="0" cellspacing="0" width="100%" align="" valign=""&gt;
    &lt;tr&gt;
      &lt;td colspan="2"&gt;Page Header goes here&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;#embedtemplate id="1" name="LoginForm"&gt;&lt;/td&gt;&lt;td&gt;&lt;#childtemplate&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td colspan="2"&gt;Page Footer goes here&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;
</CODE></PRE></DIV></DIV>
<H2>A Template that Shows Database information</H2>This kind of thing is really simple to do. Depending on your template, you should generally be able to "fill in the blanks" using one line of code. 
<P>Take a look at the template below:</P>
<DIV class=codeblockouter>A simple Template that can show information from a database. (single record) 
<DIV class=codeblockInner><PRE><CODE>
&lt;table&gt;
  &lt;tr class="tableheaderrow"&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Customer ID&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Company Name&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Address&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr class="tablerowrow"&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="CUST_ID "&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="COMPANY_NAME"&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="ADDRESS "&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
</CODE></PRE></DIV></DIV>
<P>Given a dataset that holds a record, the code to process this template might look like this:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'fieldvalue'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>MyDataSet</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>FieldByName</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'fieldname'</FONT><FONT color=#ff0000>]).</FONT><FONT color=#000080>AsString</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The next thing that comes to mind is; "Ok, now how do we do this for a record set that contains a number of records?". This is probably a more common need than the previous one. So let's explore this case a bit. The solution is to break up your templates in "snippets". </P>
<OL>
<LI>A Main "Table" template 
<LI>A Header Template 
<LI>A Row Template 
<LI>A Footer Template </LI></OL>
<P>The Main "Table" template essentially, has "place holders" for the other templates. This template might look like this:</P>
<DIV class=codeblockouter>The Main "Table" template used for showing Multiple Records from a Dataset 
<DIV class=codeblockInner><PRE><CODE>
&lt;table border="0" cellpadding="0" cellspacing="0" width="100%" align="" valign=""&gt;
  &lt;tr&gt;
    &lt;#tableheadertemplate name="SoAndSoTableHeaderTemplate"&gt;
  &lt;/tr&gt;
  &lt;#tablerowtemplate name="SoAndSoTableRowTemplate"&gt;
&lt;/table&gt;
</CODE></PRE></DIV></DIV>
<P>Notice that the "insertion" point where "Rows" are inserted does not have the <CODE>&lt;tr&gt;</CODE> tags around it. Unlike the tag for the header.</P>
<P>Using the earlier templates as a starting point, the header template would look like this:</P>
<DIV class=codeblockouter>A Table Header Template. 
<DIV class=codeblockInner><PRE><CODE>
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Customer ID&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Company Name&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Address&lt;/td&gt;
</CODE></PRE></DIV></DIV>
<P>The Row Template would look like this:</P>
<DIV class=codeblockouter>A Table "Row" Template. Make sure you include the <CODE>&lt;tr&gt;</CODE> tags. 
<DIV class=codeblockInner><PRE><CODE>
  &lt;tr class="tablerowrow"&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="CUST_ID "&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="COMPANY_NAME"&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="ADDRESS "&gt;&lt;/td&gt;
  &lt;/tr&gt;
</CODE></PRE></DIV></DIV>
<P>Notice that the "row" template has the <CODE>&lt;tr&gt;</CODE> tags, while the "header" template does not.</P>
<P>I hope this article has shown you how best to utilize the power of the TPageProducer component.</P>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>The Internet and Internet Applications</title><pubDate>Mon, 07 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/5/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/5/</guid><description><![CDATA[<UL>
<LI>TCP/IP 
<LI>Domain names and IP Addresses 
<LI>Domain name registration and DNS servers 
<LI>Ports and services 
<LI>Other TCP/IP services 
<LI>Web Servers 
<LI>Web Server software 
<LI>Web sites and HTML Pages 
<LI>DHTML 
<LI>ActiveX / Java Applets 
<LI>Web Server Extensions 
<LI>CGI 
<LI>Win-CGI 
<LI>ISAPI / NSAPI 
<LI>ASP 
<LI>CGI and ISAPI 
<LI>Differences 
<LI>Advantages / disadvantages 
<LI>Browser based applications 
<LI>Internet enabled applications </LI></UL><B>
<P>Domain names and IP Addresses </P></B>
<P>Web sites on the Internet are known by their Domain Names, such as www.Microsoft.com / www.Datasourceinc.com. Domain names actually resolve to an IP address such as 207.176.25.218. So actually, to get to the DataSource web site one could actually type in http://205.177.16.151 and the browser will take you to the site. But remembering numbers such as these is not easy and so Domain Names were introduced. Domain Names (that end in - .com or .org) have to be registered with an organization called INTERNIC. There is an annual charge of $35 for this registration and the Domain Name has to be unique! When one types in a domain name, the browser actually goes to Internic's DNS (Domain Name Service) server, that resolves the Domain name to an IP address from a lookup database and gives the browser the IP address of the web site in question. The browser then goes to the IP Address. The IP address is also a unique Address. No two servers on the same network can have the same IP address. The WWW can bee looked at as one big network. Each server on the Internet can be uniquely identified by its IP address. So it follows that typing in the IP address will be a lot faster than using the domain name. </P><B>
<P>TCP/IP </P></B>
<P>Transfer Control Protocol / Internet Protocol. This is the protocol used by the WWW. For this protocol to work we have what are called clients and servers. These are software applications that can "talk" to each other. The server application has to be up and running and "listening" on a certain port number (just a number from 1 to 65535). The client application that wants to talk to the server application must use the same port number and must know the IP address of the server application. Once a connection is established between the client and server, the two can communicate. </P>
<P>Services such as HTTP, FTP, POP, SMTP are what are called "known services" and therefore use a fixed port. </P>
<P>HTTP: Port 80 </P>
<P>FTP: Port 21 </P>
<P>POP: Port 110 </P>
<P>SMTP: Port 25 </P>
<P>Again, the names of the service can be used instead of the port No., such as http://www.datasourceinc.com actually resolves to http://205.177.16.151:80. This really tells the browser and the server to use the HTTP protocol on port 80. Since port 80 is the default port, one need not specify it (and so one normally does not). One is free to use any port for "unknown services". On any one server machine/PC one can have one and only one server application listening on a port. So for a given IP address (that uniquely identifies a PC), you can only one server application listening on a given port. </P><B>
<P>Web server software </P></B>
<P>Web servers are both a physical machine as well as a software application that is listening on port 80. An FTP server is another application (also called service or more accurately TCP/IP service) listening on port 21. So you could have both, an HTTP server (Web server) and an FTP server on one single machine, since they use different ports.</P>
<P>Also one can build ones own TCP/IP applications that "talk" across the Internet using a certain port. The server application needs to be listening on a certain port and the client application needs to know the IP address and the port to use. Only clients can connect to servers. Servers can not initiate a connection by themselves. Servers typically "service" multiple clients and so the name - Server. To learn more about TCP/IP and protocols take a look at th eTCP/IP tutorials in the Tutorials section on my web site.</P><B>
<P>Web sites and HTML pages </P></B>
<P>One can have multiple web site on a single machine. The web server (application) has a way of understanding which site is required by which HTTP request it receives. Web servers have what is known as the "root" folder. The root folder is the equivalent of the "C:\" folder of the hard drive. This root folder can be any subfolder on the HDD but the server needs to be informed of it's root folder. The web server in turn can not "see" anything before this root folder. This is to provide for some form of security. The root folder is the starting point for the web server. It can "see" all the folders and subfolders in its tree. Most folders are read access only but some are read/write/execute access. Normally, one of the subfolders of the web server is /scripts (or /cgi-bin) and it is only this folder that has read/write/execute access. </P>
<P>The home page is an HTML page in the root folder by the name default.htm. So when a surfer types in the URL (Uniform Resource Locator) for your web site, the web server (application) looks for a file in its root folder by the name default.htm and sends it back, to the surfer's browser via TCP/IP or more accurately the HTTP protocol which is nothing but a layer over the TCP/IP protocol. The most common and the easiest way to have a web site is to have numerous HTML pages as physical files on the server that are hyper-linked to help navigate through the web site. This kind of site is also called a static web site. Each time you want to make a change to the web site, you have to edit/change/add the HTML pages you want. For large sites this can be a nightmare to manage. Most sites are a mix between dynamic pages and static pages. If some of your web site's information needs to come from a database of some kind, these pages need to be generated dynamically (on request) by some form of script (application programs). Examples are CGI, ISAPI, ASP etc. For your information, the contents of this page are stored in a database. When you linked to this page, an ISAPI application extracted the information for this particular page from a database and dynamically converted the information into HTML format and sent it back to you, for you to see in your browser. In fact this web site is 100% dynamic, which means there are no static HTML pages on the server's hard disk. All content resides in a database and is servered to you dynamically.</P><B>
<P>DHTML / ActiveX / Java Applets </P></B>
<P>Since HTML is very "static" and does not "respond" to the surfer of your web page, Dynamic HTML was introduced. DHTML is a combination of HTML and JavaScript or VBScript. Combining HTML with a scripting language allows for a more dynamic or active web page. Due to scripts embedded within the HTML document the browser is able to respond to certain events, similar to normal event driven programming tools. Events such as mouse moves, mouse clicks etc. are exposed by the browser to your HTML page and the HTML page can in turn "react" to these events. In this way, the HTML pages produced seem to be more responsive or alive than regular static (HTML) pages. </P>
<P>One needs to know one of the scripting languages in order to create DHTML pages. Further, DHTML is supported only by version 4.0 of both IE and Netscape. JavaScript is supported by IE and Netscape while VBScript is supported only by IE. The level of support differs between these browsers. This means that certain DHTML pages may not "work" on all browsers unlike pure HTML (HTML version 3.0 is supported by most browsers in the market today). </P>
<P>ActiveX is Microsoft's answer to Java applets. Once again ActiveX is supported only by IE version 3.02 onwards, and not by Netscape. Java applets are supported by both IE (3.02 and above) and Netscape versions 3 and is also Windows platform dependent. Besides the incompatibility issue there is a big security risk with ActiveX on a web page. The ActiveX control or document is fully capable. In that, it can access any resource on the PC. It has full access to the Win32API and all of the drives and folders. Ironically, it's these "benefits" that are the downfall of ActiveX. ActiveX is better implemented in an Intranet environment where the platform is the same, the browser versions are compatible and the ActiveX document comes from a trusted source (such as the internal IT department). </P>
<P>Java applets on the other hand are platform independent. But once again, it due to it's benefits that it has limitations. The fact that these applets are platform independent means that these applets can not make use of certain functions (API or the UI capabilities) of the operating system. The moment an applet tries to use platform specific features it looses its platform independence. For a Java applet to run in the browser the target machine needs to have the JVM (Java Virtual Machine) installed on it to be able to interpret the Java byte code in the applet. The JVM comes in many flavors and versions and is most times the cause for applet misbehavior on certain machines. Once again, Java Applets are best suited in an Intranet environment where the environment can be better controlled. Java Applets that are very basic in functionality and made for earlier versions of the JVM are and can be used in Internet applications provided of course that the browsers' version understands them. </P><B>
<P>Web server extensions </P></B>
<P>Seeing that static HTML is very limited in what it can do, web server developers designed a way to allow programmers to extend their capabilities by providing server extensions. Server extensions in their simplest form a scripts that are executed on the server side with the help of interpreters. Examples of these are Perl and Rexx and later came JavaScript and VB script. Scripts allow for server side processing and return HTML pages. Scripts allowed for data access on the server side as well. So with the help of a script, one could query a database local to the server and in return, send back the result set in the form of HTML that the web server sends back to the requester. CGI (Common Gateway Interface) is the interface that most web servers understand. This interface allows web pages to send parameters to the script via the URL and the script processes these parameters and sends back the information via the standard I/O. </P><B>
<P>Win-CGI</B> is specific to the Windows platform and Microsoft's Internet Information Server (IIS) and other compatible web server software. Here, the parameters are sent to the CGI application (normally a .exe file) via an .ini file. The script in turn writes data (the result) in this same .ini file which the web server reads and send back to the requester. </P><B>
<P>ISAPI</B> (Internet Server Application Programming Interface) is specific to IIS and other IIS compatible web server software. Microsoft, went a step further (after Netscape introduced NSAPI - Netscape Server API) to provide more functionality and faster response by introducing the Internet Server API. Using this API, one has access to the web server's functionality. ISAPI application can be written with any tool that produces a compiled native machine code output. The compiled code is generated in the form of a DLL (Dynamic Link Library). This DLL is loaded into memory by the web server upon the first request (by a web page) and is kept in memory until the HTTP service is stopped or the machine is re-booted. ISAPI applications have no limitations on the number of parameters that can be passed to them (CGI applications have a limit of 255 bytes). Further, the way the data is transferred or handed to the ISAPI is much faster than the way CGI applications are pass information to and fro. </P><B>
<P>Advantages / Disadvantages of CGI and ISAPI application. </P></B>
<P>CGI applications are generally .exe files. This means that each time a request is made via the web server, an instance of the exe is loaded into memory and the data passed to it. This exe file is later unloaded once its job is done. So, if you had 100 surfers hitting your site simultaneously and making the same request, you'll actually have 100 instances of the CGI application, all loaded in memory at the same time. The system resources required for such a feat are phenomenal. Besides that, the time it takes for an instance of a CGI application to load and initialize causes a performance hit. </P>
<P>ISAPI applications on the other hand are DLL files. A DLL is run in the process of the calling application (in this case the web server application) and only one instance is loaded. The ISAPI DLL has to be built in such a way as to incorporate safe multi-threading. For each request, the web server spawns a new thread and does not need to load and initialize the ISAPI application. Since there is no load time involved and multi-threading is employed instead of multi-instancing, the system resources required are at a minimum and the response times are far less than those with CGI applications. </P>
<P>On the other hand CGI applications, by virtue of the fact that they are .exe files and don't need to cater for multi-threading are far simpler to build than ISAPI applications. Also, since an ISAPI runs in the process space of its calling application has the capability of crashing the calling application if errors are not handled internal to the DLL. Basically, this means that if an ISAPI DLL crashes, it takes the web server application down with it. This means all web-sites hosted by that web server will not be accessible until the machine is re-booted. This is one of the primary reasons ISPs (Internet Service providers such as AOL, Erols etc.) do not allow ISAPI applications. </P><B>
<P>Browser Based Applications </P></B>
<P>Web applications or browser based applications use the browser as the front end with some form of web server extension application (CGI/ISAPI/NSAPI/ASP) running at the back end. Ideally these applications are a very powerful technology. They are zero configuration thin clients. Which means, the surfer has to do nothing on his/her PC to be able to use these applications. They are platform independent as well as browser and browser version independent. But in reality, these applications are never zero-configuration. Due to the speed with which technology is moving and the inability of individuals to keep upgrading their machines, operating systems and browsers, the zero configuration thin client can not use the new and emerging technologies. Thus browser- based applications will always have to built to conform to earlier versions of operating systems as well as browsers. </P>
<P>Besides the compatibility issues stated above, browsers, by their very nature are isolated from the PC, such that they can not access the resources of the machine they are running on. Therefore they are very limited in their capability to integrate/interface with existing systems or use the Os's API or GUI capability for better and more functional/feature rich UIs. Even in corporate environments, where operating system versions and browser versions can be controlled, these kinds of applications are not the best suited for such a need as 9 times out of 10, these applications will need to interface/integrate with existing systems in the corporate environment. </P>
<P>Browser based application therefore tend to be used for very simple needs. </P><B>
<P>Internet-Enabled Applications. </P></B>
<P>These are applications built as normal PC based applications but access data over the Internet. Effectively, these applications use the Internet infrastructure as their network. This allows for remote connectivity to data from anywhere in the world. Similar to browser based applications. With the advantage of being able to access the resources of the machine on which they are executed and thereby allowing for integration with other existing corporate systems. </P>
<P>On the GUI side, these applications are fully capable, thus allowing for "standard" features such as drag/drop, tree-views and list-views (like in windows Explorer [not Internet Explorer]). This not only gives the user of the application an interface s/he is familiar with but also saves on training needs. The UI is not limited in any way. </P>
<P>Advantages and Disadvantages of Web based and Internet based Applications </P>
<P>Each technology has its place. Where a simple data entry, data view and reporting capability is required, browser based applications are very well suited. On the other hand, if you require the full functionality and capability of a standard PC application as the front end, but need the "remote" connectivity as well, then Internet enabled applications are ideal. In most corporate scenarios, you will find a combination of browser based and Internet enabled applications. For the simple user or "on off" user (surfer) you'll find a web interface and for the power/corporate user you'll find Internet enabled applications. </P>
<P>When the user/surfer is unknown, that is the browser type, platform etc. in not known or controllable, a browser-based application has its advantages. On the other hand, if cross-platform is not an issue and the environment can be controlled to a high degree, then Internet enabled applications are the right choice, due to their interfacing/integrating capability and UI capability. </P></FONT>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>ISAPI Versus CGI/ASP</title><pubDate>Sun, 06 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar.aspx/articles/post/6/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar.aspx/articles/post/6/</guid><description><![CDATA[<H2>CGI - Common Gateway Interface</H2>CGI comes in the form of scripts or executables. In this article, the comparison between ISAPI and CGI assumes we're talking about CGI executables and not scripts. Considering the fact that executables are faster than scripts due to the interpreted nature of scripts. Lets take a look at the CGI model. 
<P><IMG src="http://www.matlus.com/images/CGIModel.jpg"> <BR><B>Figure 1: Showing the Process of a client request in terms of a browser and web server</B> 
<P>As shown in <B>Figure 1</B>: <BR>
<OL>
<LI>The client sends a request to the web server via an HTTP GET or POST method. 
<LI>The connection persists while the web server spawns a new process to handle the request. 
<LI>The CGI application processes the request, builds the output and sends it back to the web server. 
<LI>The Web server adds the protocol (HTTP) headers and passes all of it back to the requesting client. </LI></OL>While this is going on, the web server can receive and process other requests simultaneously. But for every request, the web server has to spawn a new process to handle the request. The implication of this is that it takes a certain amount of time to spawn a new process and each process requires a certain amount of resources (memory). It's easy to see that in a busy web site, the server can very easily get bogged down spawning new processes and running low on resources in an attempt to service multiple simultaneous requests. 
<P>
<H2>ISAPI</H2>The Internet Server Application Programming Interface is an API that allows a developer to add extensions to the Internet Information Server (IIS), replacing or enhancing programming duties typically performed either by CGI scripts or an HTTP server. An ISAPI extension is an application extension (DLL) that executes on the server, in the process space of the server. The request performs some function on the server and returns a response to the client. ISAPI extensions, then, replace the functionality typically associated with CGI scripts/executables. 
<P>Looking at <B>Figure 1</B> again, let see what would happen if the CGI executable were to be replaced by an ISAPI extension application. 
<P>An ISAPI application, does not spawn a new process after it has been called the first time by a request. Rather, it runs in the server's process space, thus reducing both memory overhead and startup time. Only a single copy of this server extension is loaded and is then shared if additional client requests for the same application come in. Furthermore, once an ISAPI application is loaded into the process space, it stays loaded until IIS is stopped and restarted, or until some unspecified period when IIS decides to unload it. This means new requests for the ISAPI will get much quicker responses and resource utilization is kept low due to a single instance model, rather than a multiple instance model in the case of a CGI. 
<P>All in all, this speed improvement is a strong argument for using ISAPI to do anything that requires back-end server processing over a CGI. If one were to look at CGI scripts or any other scripting mechanism, its easy to see that these types of applications will perform far slower than even CGI executables as they are interpreted rather than compiled. One should also note, that the interpreter needs to be loaded in memory to do its job as well. So resource utilization is much higher in scripting mechanisms such as, Perl, ASP etc. and performance is poor due to the interpreted nature. 
<H2>As per Microsoft</H2>
<BLOCKQUOTE><B>Designing High-Performance ISAPI Applications</B> 
<P>ISAPI is the highest-performance interface for Web applications. If you create an ISAPI extension or filter, it will outperform ASP scripts or even components performing similar tasks. 
<P>However, the inherent speed of the ISAPI interface does not mean that you can ignore performance and scalability considerations. Indeed, ISAPI cannot utilize much of the application support services provided by ASP and COM. If you would like your ISAPI application to maintain session state, for instance, much of that session-state functionality would have to be implemented by you. </P></BLOCKQUOTE><B>My Note</B> : Quite easily achieved using Delphi. 
<P>
<BLOCKQUOTE>Quote continues... 
<H2>Here are some suggestions for improving the scalability and performance of your ISAPI extensions:</H2>
<UL>
<LI>Avoid ISAPI filters, unless adding an ISAPI filter is absolutely necessary to your application architecture. You should especially avoid filters that perform processing on raw incoming or outgoing data. If you determine that a filter is absolutely necessary, be sure to carefully optimize the main code paths through the filter event notification code. 
<LI>Create your own worker thread pool, so that the main I/O threads can be freed to accomplish other tasks. This option is available only for ISAPI extensions, and not for ISAPI filters. For more information about how IIS processes requests, see IIS Request Processing. A sample that demonstrates a worker thread pool, implemented in an ISAPI extension, is available in ISAPI Examples. 
<LI>Consider using asynchronous operations and I/O completion ports, when feasible. IIS supports asynchronous reading and writing by using the I/O completion ports, available in Windows NT 4.0, and Windows 2000 or later. Depending on the type of I/O operations being performed, asynchronous operations can make better use of the CPU time available, and generally work particularly well when implemented using a worker thread pool. 
<LI>ISAPI extensions should use the Win32 TransmitFile function, exposed by the HSE_REQ_TRANSMIT_FILE ServerSupportFunction. 
<LI>Use Connection: Keep-Alive headers. Keeping persistent HTTP connections will provide better performance than using non-persistent connections, in most cases. 
<LI>Minimize need for thread synchronization by maintaining state information with the request context. If thread synchronization is required, make sure that critical sections are kept short. 
<LI>If your ISAPI application uses the heap intensively, consider other heap alternatives. Intensive use of the Windows? heap can cause resource contention. Several memory allocation alternatives are worth exploring, including: 
<UL>
<LI>Heap Partitioning, accomplished by creating multiple custom heaps, in addition to the default process heap. Each custom heap would then be controlled by a separate, non-global lock, and lock contention would be reduced. 
<LI>Cached Allocation, which involves using custom allocation operations that operate at a middle layer between the object users and the heap. Calls to the Win32 heap are made infrequently, and only for large memory blocks. These blocks are then subdivided and managed by the custom allocator. 
<LI>Stack Allocation, using the C run-time function _alloca to allocate memory for your objects on the stack instead of the heap. This method is feasible only for relatively small objects, because the space available on the stack is limited. In addition, your newly allocated object will be available only within the current functions, or functions called by that function. Once the current function returns, the storage allocated on the stack will be lost. </LI></UL>
<LI>Object Encapsulation, accomplished by simply incorporating a buffer as a member data structure of a class. This buffer is then used for tasks that would otherwise require accesses to the Win32 heap. 
<LI>Avoid using global locks within your ISAPI, if possible. Global locks can often adversely affect scalability. </LI></UL></BLOCKQUOTE><B>My Note</B>: A lot of these issues are dealt with in a Delphi ISAPI extension with the help of the Web Broker technology, thus freeing the Delphi programmer from such tasks. 
<P><B>An intersting page on the Microsoft site compares ASP and ISAPI performance, scalability etc. Check it out <a rel="nofollow" href="http://msdn.microsoft.com/library/techart/docu2kbench.htm" target="_new">here</A></B> 
<P>
<H2>ISAPI and the Web Application Architecture</H2>The set of interfaces that make up ISAPI were designed to provide application developers with a powerful way to extend the functionality of IIS. ISAPI extensions and filters have the following advantages over some of the other Web application technologies available: 
<UL>
<LI>Highest performance: A properly planned, developed, and used ISAPI-particularly ISAPI extensions-can outperform any other Web application technology available currently for IIS. 
<LI>Low-level control: From an ISAPI extension or filter, you have access to the whole array of Win32 API functions. For instance, you can create a customized worker-thread pool for your ISAPI extension to speed processing, using the Win32 thread functions to access the native thread functionality of Windows 2000. 
<LI>Often, ISAPI extensions and filters are best positioned to solve critical bottlenecks in your Web application-especially if you expect scalability to be an important issue for your application, due to high traffic v