ExposureRoom Home
Sign Up Log in Theme Help/FAQ
Shiv's Website
Shiv Kumar
United States
Friends: 131
Focused on : 5
 
       
                                                             

Building your First ISAPI Application using Delphi

Not Rated YetNot Rated YetNot Rated YetNot Rated YetNot Rated Yet0votes
January 18, 2008 11:06 AM  Views:2283   Favorited:0 Comments:0
Filed Under:  Programming
Tags:  Delphi, Html, Http, ISAPI
 

In this article we will take you through the steps in building an ISAPI application using Delphi 3/4/5 Client/Server (Enterprise) edition.

What do you need to start?

  1. Delphi 3/4/5 Client/Server or Enterprise Edition
  2. A Web Server (software).
    You may use Microsoft’s Personal Web Server (PWS) which is available for free from their web site. You may already have PWS if you use Win98 Second Edition, which comes with Personal Web Server 4.0. You may also use Microsoft’s IIS on Windows NT/ Windows 2000. In any case, be sure to use a web server that supports ISAPI. If the server you use does not support ISAPI, you may work with the project as a CGI (EXE) program instead. It will not have the same resource and speed advantages that an ISAPI DLL will have, but it is certainly adequate to develop your application as a CGI program during the development phase, or if you know that the site where you employ the CGI will not be heavily trafficked. You can also use Omni httpd (you can download it from here) or Falcon WebServer which is a web server written in Delphi (you can download it from here). Both these web server should allow you to debug your ISAPI projects like any other DLL project from within the IDE. I suggest you don't run these web servers as NT services for debugging purposes.
  3. Some basic HTML knowledge.
    HTML is a scripting language that uses tags to delineate different parts of a document. All tags take the form of <tagname> to open the tag, and most have a closing tag </tagname> to close the tag. Tags may are embedded in other tags. Some tags may have attributes, such as the <FONT> tag that has a COLOR attribute. We will use some of these tags in the exercise in this article. Your web projects will benefit greatly with an advanced knowledge of HTML/DHTML.
  4. Knowledge of Delphi.

What you do in Delphi to access databases (and other programming stuff) will be the same as what you do in your ISAPI/CGI application. To write web applications, you just need to learn the ISAPI part. Your existing Delphi programming knowledge will be leveraged. For a good Delphi programmer, wanting to start with web development, the ISAPI part is the simplest! It's actually the HTML, JavaScript, Graphics etc. that is much harder to do. In my experience in developing web sites, I spend 60-70% of my time trying to come up with good graphics and functional JavaScript to make the web pages interesting. After being used to developing front end applications, one feels handicaped trying to get a browser to do what you could so easily achieve with a front end GUI. Mind you, the simplicity of ISAPI is only for the Delphi/BC developer, thanks to the Delphi R&D team. A VC programmer has a ton of work to do before he can get his ISAPI up and running!

Now that I've made you feel comfortable, let's get on with it shall we ?

Web Applications Concepts

FirstISAPI1.png

Let’s explain some basic concepts and terms before we begin.

You have a browser as your "front end". The browser makes "requests" to the web server. These requests could be a request for an HTML page, or information from a database, or a combination of the two.

The request made by the browser goes to the web server. The web server will pass this request onto your ISAPI (or CGI) application which is targeted by the URL of the request.

(To understand the differences between creating an ISAPI DLL and a CGI EXE, please see the note at the bottom of this article.)

Within your ISAPI application you can "see" this request as an event that is generated. The request may have parameters passed to it. What you must program then is a response to this request, and return that response along with any requested information to the client (browser) via the web server. Your response will be in the form of an HTML string.

After you have installed a web server on your PC, you may "run" your web application by entering the URL in your browser. To access your URL’s "domain name", use the name of your PC. Let’s say the name of your PC (Computer Name) is "MyPC". To get the default home page to display, you need to type in http://mypc/, or http://MyPC.default.htm. The web server will always look for a file called "default.htm" (or default.asp) in your web server’s "root" folder if not instructed otherwise. Web servers have what is known as a "root" folder. In the case of Personal WebServer 4.0 and IIS, the "root" folder is C:\Inetpub\wwwroot.

The root folder is the equivalent of the "C:\" folder of the hard drive. This root folder can be any subfolder on the hard drive, but the server needs to be informed of where that root folder is.

The web server cannot "see" any folder higher than its root folder. This provides for security. The root folder is the starting point for the web server, and it can "see" all the folders and subfolders in its own tree. Most folders are read access only. One of the subfolders of the web server is /scripts (or /cgi-bin) and it is this folder only that has read/write/execute access by default. Your ISAPI or CGI application will reside in this folder.

You can access another page called "MyHTML.htm" from your web server’s root folder by typing http://MyPC/MyHTML.htm as the URL. To access a script with a name of MyISAPI.DLL, the URL would be http://MyPC/scripts/MyISAPI.DLL. Since you have not specified any "action" (after the DLL name), the default "action" of your web application, (something you define) will be executed.

Let’s say we had a logon screen that we wanted displayed. The action we decided for this is "/logon". (Note use of the forward slash.) To get the Logon page (dynamically generated by our ISAPI application) the URL would be http://MyPC/scripts/MyISAPI.DLL/logon. This request is sent on to PWS. PWS receives this request, loads our DLL in memory, and sends the "logon" action. In our application, this action’s event will be fired.

The key point to understand is that it is our job to send back an HTML page in the form of a string. So in this way a form of communication is established between the client and the server. If you understand this concept, you can go on to building an ISAPI application using Delphi.

Building your first ISAPI application

  • Start Delphi
  • Choose File | New
  • From the dialog, choose - Web Server Application and then OK.
  • In the next dialog, leave the selected option as ISAPI (you have CGI and Win-CGI options as well).

You should now see a new project with a Web Module and its unit.

At this point, I suggest you go into the project options dialog and set the "output directory" on the Directories and Conditionals page, to the scripts folder of your web server. That is – C:\Inetpub\scripts. The reason I suggest doing this is so when you compile your application, the DLL will be generated in the folder in which you need it.

  • Save the project with the of name MyISAPI.

The web module is where you place you Data access components.

  • To add actions to your web application, either click on the ellipses for the "actions" property in the object inspector or double click on the web module, to display the Actions editor.
  • Add an action to the web module. Once you have the Actions editor active, click on the "Add new" toolbar button of the actions editor.

FirstISAPI2.png

  • With the new action selected in the (Actions) editor, switch to the object inspector. You should see the properties of the selected action. The "PathInfo" property is what we need to set. In this case, we want to set the path to "/logon". Even if you type just "logon", the object inspector will change it to "/logon".
  • Now switch to the events page of this action item, and create an event handler for the one (and only) event you see there, called "OnAction".

At the point of writing code for the OnAction event, you should notice the parameters that are passed onto you, namely, the "request" and the "response" parameters. Both of these are objects and have their own set of properties and methods.

Our "logon" action needs to return the logon screen to the browser. So what we need to do is return the HTML tags and text that will produce a logon screen in a browser. One needs to know HTML to some degree to know what tags need to be sent back to the browser to display and HTML screen.

We use the request object to find out what was requested of us, and the response object to send data back to the web browser. In this case (because this event will be fired for us) we don’t need to know what was requested, since all we need to know is that a logon screen was requested. But what we do need to do is send back the logon screen. The way we do that is:

procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.Content :=
    '<html>'  
    '<head>'  
    '        <title>User Log On</title>'  
    '</head>'  
    '<body>'  
    { Remember to change the URL from skumar to your PC's name !! }
    '<form action="http://skumar/scripts/MyISAPI.dll/logUser" method="post">'  
    '<BR/>UserID<input name="txtUserID">'  
    '<BR/>Password<input name="txtPassword">'  
    '<BR/><BR/>'  
    '<input type="submit" value="Submit">'  
    '<input type="reset" value="Reset">'  
    '</form>'  
    '</body>'  
    '</html>';
end;

The Response.Content property contains the HTML that needs to be sent back. What is sent back is an HTML Form. "Data Entry" screens in HTML are known as "Forms" and use the <FORM> tag to delineate the form. What happens when the "submit" button is clicked is determined by the forms' "action". In this case:

<FORM action=http://MyPC/scripts/MyISAPI.DLL/logUser method=post>

So when the submit button is clicked in this case, the request will be made to our ISAPI application (MyISAPI.DLL) with the "/logUser" action sent to it. So we need to have a "/logUser" action item in our application as well. So lets go back and:

  1. Add a new action to the web module.
  2. Set the PathInfo property of this action item to - /logUser.
  3. Generate an OnAction event handler for this action item.

FirstISAPI3.png

What we want to do now is verify that the user id and password are valid. To be able to do that, we need to know what the "user id" and "password" are that were sent. How do we get the user id and password so that it is available to the LogUser action?

Notice that the "method" of the <FORM> above is "post". When you use the "post" method of an HTML form, the parameters of the form are made available to you in the "ContentFields" property of the Request Object sent to you as a parameter in the OnAction event. The ContentFields property is of type TStrings.

The HTML form’s "values" (values of the various fields of the form) are made available to you in the ContentFields property as Name value pairs in the format:

txtUserID=skumar
txtPassword=shiv

The "name" or left part of the equation is the name of the field, got from the <INPUT> tags, here txtUserID and txtPassword. The actual values sent back will be returned as the element to the right of the "=".

The TStrings object has methods to make extracting these values simple. To extract these values you need to use the following code:

sUserID := Request.ContentFields.Values['txtUserID'];
sPassword := Request.ContentFields.Values['txtPassword'];

where sUserID and sPassword are declared as local string type variables.

So the whole event handler of the /loguser action item will look like:

procedure TWebModule1.WebModule1WebActionItem2Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  sUserID: string;
  sPassword: string;
begin
  { Extract the values for the forms' fields }
  sUserID := Request.ContentFields.Values['txtUserID'];
  sPassword := Request.ContentFields.Values['txtPassword'];

  { Validate the UserID and Password fields }
  if (sUserID = '') or (sPassword = '') then
  begin
    Response.Content :=
      '<html>'  
      '<head>'  
      '        <title>Log On Error</title>'  
      '</head>'  
      '<body>'  
      'Either the UserID or Password was blank.'  
      'Please make sure your user information is entered correctly'  
      '</body>'  
      '</html>';
  end
  else
  begin
    { At this point you could verify the userid and password with
      data in a database or any other way. Assuming the userid
      and password are valid. You can then send back an HTML page
      indicating that to the user.
    }
    Response.Content :=
      '<html>'  
      '<head>'  
      '        <title>User is Valid</title>'  
      '</head>'  
      '<body>'  
      'Welcome. Your profile has been recognized.'  
      '</body>'  
      '</html>';
  end;
end;

Remember, you need to use the Request object in this case and not the Response object. The Request Object is used to GET information about the request. The Response Object is used to send information back to the requestor.

Once we have this information, we can determine the validity of the user using standard Delphi methods.

Testing MyISAPI

  1. We are now ready to compile and test MyISAPI DLL. If you changed the Output directory to the scripts folder of your web server then you should see the file MyISAPI.DLL in this folder once you've compiled your application.
  2. Open up your browser and type in the following URL. Remember to substitute "MyPC" with the name of your PC. The URL is http://MyPC/scripts/MyISAPI.DLL/Logon
  3. This should show you a page similar to this.

FirstISAPI4.png

Fill in the Fields and hit the submit button. Unless you've left any of the fields blank, you should see an HTML page like this:

FirstISAPI5.png


Developing Web applications: ISAPI or CGI?

Those using PWS should choose CGI instead of ISAPI when creating the web application. The reason is that PWS does not have the option to stop the HTTP service. Due to this. DLLs once loaded can’t be released by the web server easily, and you will not be able to compile your ISAPI DLL more than once without re-booting. The down side of this is that you can't debug CGI applications like you can an ISAPI application.

If you are using IIS and you wish to recompile your project, stop the HTTP service, recompile and then start the service again before attempting to refresh the browser. You could also set IIS such that it does not cache ISAPI Applications. But remember to turn on caching on your production web server.

From a development perspective there is no difference between ISAPI and CGI. You may find it convenient to develop your applications as CGI through the development and de-bugging stages, and then when done, convert the CGI to an ISAPI. To do this a few minor changes are required in the Project source file:

  1. Change the word "program" to "library" in the main project file.
  2. Add an "export" clause for ISAPI.
  3. Change the "CGIApp" unit to "ISAPIApp" in the uses clause.

You can use compiler directives to account for these differences, so it becomes simple to change from CGI to ISAPI and back. There will be absolutely no change required to your code, except for the consideration that an ISAPI app loads only once so the OnCreate event of the web data module is called only once. Database access needs to be multi-threaded which is easily accomplished by using a TSession component with its AutoSessionName property set to True. Any initialization code needs to be considered.

Using Compiler Directives to Accommodate use of either ISAPI or CGI

Add the following compiler directives to your project file:

{$IFDEF ISAPI}
library Project1;
{$ELSE}
program Project1;
  {$APPTYPE CONSOLE}
{$ENDIF}
uses
  WebBroker,
  {$IFDEF ISAPI}
  ISAPIApp,
  {$ELSE}
  CGIApp,
  {$ENDIF}
  Unit1 in 'Unit1.pas'  {WebModule1: TWebModule};
{$R *.RES}
{$IFDEF ISAPI}
exports
  GetExtensionVersion,
  HttpExtensionProc,
  TerminateExtension;
{$ENDIF}
begin
  Application.Initialize;
  Application.CreateForm(TWebModule1, WebModule1);
  Application.Run;
end.

Note: The WebBroker unit found in the uses clause was theHTTPApp unit in Delphi 3 and 4.

Using Code Templates to Make HTML’ing Faster and Easier

One can make good use of the code template features of Delphi’s code editor, which will speed up your HTML typing. Some examples are.

'<INPUT TYPE="TEXT" NAME="txt|">'
'<FORM METHOD="POST" ACTION="'   Response.ScriptName   '/|">'   crlf  
'</FORM>'

Even a simple thing like typing "Response.Content := " can be painful since the code completion wizard will show you "Response.ContentEncoding". So set up a short cut such as "res" that generates

Response.Content :=  | 

Comments have been Disabled for this post





 Search ExposureRoom

Privacy Policy  |  Terms Of Service  |  Contact Us  |  Support  |  Help/FAQs  |  News