Copyright: Copyright © 2001 Borland Software Corporation.                      All rights reserved.                                                 This Help file was compiled on   Thursday, May 17, 2001 17:37:11.


Creating Internet applications: Overview
 DevGuide: Developing Internet applications

Creating Internet applications: Overview

Topic groups	See also

Web server applications extend the functionality and capability of existing Web servers. A Web server application receives HTTP request messages from the Web server, performs any actions requested in those messages, and formulates responses that it passes back to the Web server. Any operation that you can perform with a Delphi application can be incorporated into a Web server application.

Delphi provides two different architectures for developing Web server applications: Web Broker and WebSnap. Although these two architectures are different, WebSnap and Web Broker have many common elements. The WebSnap architecture acts as a superset of Web Broker. It provides additional components, and new features such as the WebSnap Surface Designer—which allows the content of a page to be displayed without the developer having to run the application. Applications developed with WebSnap can include Web Broker components, whereas applications developed with Web Broker cannot include WebSnap components.


About Web Broker and WebSnap
 DevGuide: Developing Internet applications

About Web Broker and WebSnap

Topic groups	See also

The first step in building a Web server application is choosing which architecture you want to use. Both approaches provide many of the same features, including

Support for many types of Web server applications, including ISAPI, NSAPI, CGI, Win CGI, and Apache. These are described in Types of Web server applications.

Multithreading support so that incoming client requests are handled on separate threads.

Caching of Web modules for quicker responses.

However, each approach has certain advantages and disadvantages. The major differences between these two approaches are outlined in the following table:

Web Broker	WebSnap
Backward compatible	Although WebSnap applications can use any Web Broker components that produce content, the Web modules and dispatcher that contain these are new.
Available in cross-platform (CLX) applications.	At present, WebSnap is only available on Windows.
Only one Web module allowed in an application.	Multiple Web modules can partition the application into units, allowing multiple developers to work on the same project with fewer conflicts.
Only one Web dispatcher allowed in the application.	Multiple, special-purpose dispatchers handle different types of requests.
Specialized components for creating content include page producers, InternetExpress components, and Web Services components.	Supports all the content producers that can appear in Web broker applications, plus many others designed to let you quickly build complex data-driven Web pages.
No scripting support.	Support for server-side scripting (JScript or VBscript) allows HTML generation logic to be separated from the business logic.
No built-in support for named pages.	Named pages can be automatically retrieved by a page dispatcher and addressed from server-side scripts.
No session support.	Sessions store information about an end user that is needed for a short period of time. This can be used for such tasks as login/logout support.
Every request must be explicitly handled, using either an action item or an auto-dispatching component.	Dispatch components automatically respond to a variety of requests.
Only a few specialized components provide previews of the content they produce. Most development is not visual.	The WebSnap surface designer lets you build Web pages visually, and view the results at design time. Previews are available for all components.
For more information on Web Broker, see Using Web Broker.. For more information on WebSnap, see Using WebSnap.


Terminology and standards
 DevGuide: Developing Internet applications

Terminology and standards

Topic groups	See also

Many of the protocols that control activity on the Internet are defined in Request for Comment (RFC) documents that are created, updated, and maintained by the Internet Engineering Task Force (IETF), the protocol engineering and development arm of the Internet. There are several important RFCs that you will find useful when writing Internet applications:

RFC822, “Standard for the format of ARPA Internet text messages,” describes the structure and content of message headers.

RFC1521, “MIME (Multipurpose Internet Mail Extensions) Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies,” describes the method used to encapsulate and transport multipart and multiformat messages.

RFC1945, “Hypertext Transfer Protocol — HTTP/1.0,” describes a transfer mechanism used to distribute collaborative hypermedia documents.

The IETF maintains a library of the RFCs on their Web site, www.ietf.cnri.reston.va.us

These documents include, among other information, details about

Parts of a Uniform Resource Locator

HTTP request header information

HTTP server activity


Parts of a Uniform Resource Locator
 DevGuide: Developing Internet applications

Parts of a Uniform Resource Locator

Topic groups	See also

The Uniform Resource Locator (URL) is a complete description of the location of a resource that is available over the net. It is composed of several parts that may be accessed by an application. These parts are illustrated in the following figure:

The first portion (not technically part of the URL) identifies the protocol (http). This portion can specify other protocols such as https (secure http), ftp, and so on.

The Host portion identifies the machine that runs the Web server and Web server application. Although it is not shown in the preceding picture, this portion can override the port that receives messages. Usually, there is no need to specify a port, because the port number is implied by the protocol.

The ScriptName portion specifies the name of the Web server application. This is the application to which the Web server passes messages.

Following the script name is the pathinfo. This identifies the destination of the message within the Web server application. Path info values may refer to directories on the host machine, the names of components that respond to specific messages, or any other mechanism the Web server application uses to divide the processing of incoming messages.

The Query portion contains a set a named values. These values and their names are defined by the Web server application.

URI vs. URL

The URL is a subset of the Uniform Resource Identifier (URI) defined in the HTTP standard, RFC1945. Web server applications frequently produce content from many sources where the final result does not reside in a particular location, but is created as necessary. URIs can describe resources that are not location-specific.


HTTP request header information
 DevGuide: Developing Internet applications

HTTP request header information

Topic groups	See also

HTTP request messages contain many headers that describe information about the client, the target of the request, the way the request should be handled, and any content sent with the request. Each header is identified by a name, such as “Host” followed by a string value. For example, consider the following HTTP request:

GET /art/gallery.dll/animals?animal=dog&color=black HTTP/1.0

Connection: Keep-Alive

User-Agent: Mozilla/3.0b4Gold (WinNT; I)

Host: www.TSite.com:1024

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

The first line identifies the request as a GET. A GET request message asks the Web server application to return the content associated with the URI that follows the word GET (in this case /art/gallery.dll/animals?animal=doc&color=black). The last part of the first line indicates that the client is using the HTTP 1.0 standard.

The second line is the Connection header, and indicates that the connection should not be closed once the request is serviced. The third line is the User-Agent header, and provides information about the program generating the request. The next line is the Host header, and provides the Host name and port on the server that is contacted to form the connection. The final line is the Accept header, which lists the media types the client can accept as valid responses.


HTTP server activity
 DevGuide: Developing Internet applications

HTTP server activity

Topic groups	See also

The client/server nature of Web browsers is deceptively simple. To most users, retrieving information on the World Wide Web is a simple procedure: click on a link, and the information appears on the screen. More knowledgeable users have some understanding of the nature of HTML syntax and the client/server nature of the protocols used. This is usually sufficient for the production of simple, page-oriented Web site content. Authors of more complex Web pages have a wide variety of options to automate the collection and presentation of information using HTML.

Before building a Web server application, it is useful to understand how the client issues a request and how the server responds to client requests:

Composing client requests

Serving client requests

Responding to client requests


Composing client requests
 DevGuide: Developing Internet applications

Composing client requests

Topic groups	See also

When an HTML hypertext link is selected (or the user otherwise specifies a URL), the browser collects information about the protocol, the specified domain, the path to the information, the date and time, the operating environment, the browser itself, and other content information. It then composes a request.

For example, to display a page of images based on criteria selected by clicking buttons on a form, the client might construct this URL:

http://www.TSite.com/art/gallery.dll/animals?animal=dog&color=black

which specifies an HTTP server in the www.TSite.com domain. The client contacts www.TSite.com, connects to the HTTP server, and passes it a request. The request might look something like this:

GET /art/gallery.dll/animals?animal=dog&color=black HTTP/1.0

Connection: Keep-Alive

User-Agent: Mozilla/3.0b4Gold (WinNT; I)

Host: www.TSite.com:1024

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*


Serving client requests
 DevGuide: Developing Internet applications

Serving client requests

Topic groups	See also

The Web server receives a client request and can perform any number of actions, based on its configuration. If the server is configured to recognize the /gallery.dll portion of the request as a program, it passes information about the request to that program. The way information about the request is passed to the program depends on the type of Web server application:

If the program is a Common Gateway Interface (CGI) program, the server passes the information contained in the request directly to the CGI program. The server waits while the program executes. When the CGI program exits, it passes the content directly back to the server.

If the program is WinCGI, the server opens a file and writes out the request information. It then executes the Win-CGI program, passing the location of the file containing the client information and the location of a file that the Win-CGI program should use to create content. The server waits while the program executes. When the program exits, the server reads the data from the content file written by the Win-CGI program.

If the program is a dynamic-link library (DLL), the server loads the DLL (if necessary) and passes the information contained in the request to the DLL as a structure. The server waits while the program executes. When the DLL exits, it passes the content directly back to the server.

In all cases, the program acts on the request of and performs actions specified by the programmer: accessing databases, doing simple table lookups or calculations, constructing or selecting HTML documents, and so on.


Responding to client requests
 DevGuide: Developing Internet applications

Responding to client requests

Topic groups	See also

When a Web server application finishes with a client request, it constructs a page of HTML code or other MIME content, and passes it back (via the server) to the client for display. The way the response is sent also differs based on the type of program:

When a Win-CGI script finishes it constructs a page of HTML, writes it to a file, writes any response information to another file, and passes the locations of both files back to the server. The server opens both files and passes the HTML page back to the client.

When a DLL finishes, it passes the HTML page and any response information directly back to the server, which passes them back to the client.

Creating a Web server application as a DLL reduces system load and resource use by reducing the number of processes and disk accesses necessary to service an individual request.


Types of Web server applications
 DevGuide: Developing Internet applications

Types of Web server applications

Topic groups	See also

Whether you use Web Broker or WebSnap, you can create five types of Web server applications. In addition, you can create a Web Application Debugger executable, which integrates the Web server into your application so that you can debug your application logic. The Web Application Debugger executable is intended only for debugging. When you deploy your application, you should migrate to one of the other five types.

Each of the five types of Web server application uses a type-specific descendant of TWebApplication, TWebRequest, and TWebResponse:

Application Type	Application Object	Request Object	Response Object
Microsoft Server DLL (ISAPI)	TISAPIApplication	TISAPIRequest	TISAPIResponse
Netscape Server DLL (NSAPI)	TISAPIApplication	TISAPIRequest	TISAPIResponse
Apache Server DLL	TApacheApplication	TApacheRequest	TApacheResponse
Console CGI application	TCGIApplication	TCGIRequest	TCGIResponse
Windows CGI application	TCGIApplication	TWinCGIRequest	TWinCGIResponse
ISAPI and NSAPI

An ISAPI or NSAPI Web server application is a DLL that is loaded by the Web server. Client request information is passed to the DLL as a structure and evaluated by TISAPIApplication, which creates TISAPIRequest and TISAPIResponse objects. Each request message is automatically handled in a separate execution thread.

Apache

An Apache Web server application is a DLL that is loaded by the Web server. Client request information is passed to the DLL as a structure and evaluated by TApacheApplication, which creates TApacheRequest and TApacheResponse objects. Each request message is automatically handled in a separate execution thread.

CGI stand-alone

A CGI stand-alone Web server application is a console application that receives client request information on standard input and passes the results back to the server on standard output. This data is evaluated by TCGIApplication, which creates TCGIRequest and TCGIResponse objects. Each request message is handled by a separate instance of the application.

Win-CGI stand-alone

A Win-CGI stand-alone Web server application is a Windows application that receives client request information from a configuration settings (INI) file written by the server and writes the results to a file that the server passes back to the client. The INI file is evaluated by TCGIApplication, which creates TWinCGIRequest and TWinCGIResponse objects. Each request message is handled by a separate instance of the application.


Debugging server applications
 DevGuide: Developing Internet applications

Debugging server applications

Topic groups	See also

Debugging Web server applications presents some unique problems, because they run in response to messages from a Web server. You can not simply launch your application from the IDE, because that leaves the Web server out of the loop, and your application will not find the request message it is expecting.

The following topics describe techniques you can use to debug Web server applications:

Using the Web Application Debugger

Debugging Web applications that are DLLs


Using the Web Application Debugger
 DevGuide: Developing Internet applications

Using the Web Application Debugger

Topic groups	See also

The Web Application Debugger provides an easy way to monitor HTTP requests, responses, and response times. The Web Application Debugger takes the place of the Web server. Once you have debugged your application, you can convert it to one of the supported types of Web application and install it with a commercial Web server.

To use the Web Application Debugger, you must first create your Web application as a Web Application Debugger executable. Whether you are using Web Broker or WebSnap, the wizard that creates your Web server application includes this as an option when you first begin the application. This creates a Web server application that is also a COM server.

For information on how to write this Web server application using Web Broker, see Using Web Broker. For more information on using WebSnap, see Using WebSnap.

Launching your application with the Web Application Debugger

Once you have developed your Web server application, you can run and debug it as follows:

1	With your project loaded in the IDE, set any breakpoints so that you can debug your application just like any other executable.

2	Choose Run|Run. This displays the console window of the COM server that is your Web server application. The first time you run your application, it registers your COM server so that the Web App debugger can access it.

3	Select Tools|Web App Debugger.

4	Click the Start button. This displays the ServerInfo page in your default Browser.

5	The ServerInfo page provides a drop-down list of all registered Web Application Debugger executables. Select your application from the drop-down list. If you do not find your application in this drop-down list, try running your application as an executable. Your application must be run once so that it can register itself. If you still do not find your applicaiton in the drop-down list, try refreshing the Web page. (Sometimes the Web browser caches this page, preventing you from seeing the most recent changes.)

6	Once you have selected your application in the drop-down list, press the Go button. This launches your application in the Web Application Debugger, which provides you with details on request and response messages that pass between your application and the Web Application Debugger.

Converting your application to another type of Web server application

When you have finished debugging your Web server application, you will need to convert it to another type of Web application before you install it with a commercial Web server. The following steps describe how to make these changes:

1	In the IDE, choose Project|Add New Project. This opens a new project without closing down the current one (your Web server application).

2	Launch the wizard to start a Web Broker or WebSnap application and choose the type of application you want to create.

3	Choose View|Project Manager to display the project manager.

4	In the project manager, drag all the units that make up your Web Server application from the old project to the one you just added. Omit the unit that implements the console window.

You now have a Web server application of the appropriate type.


Debugging Web applications that are DLLs
 DevGuide: Developing Internet applications

Debugging Web applications that are DLLs

Topic groups	See also

ISAPI , NSAPI, and Apache applications are actually DLLs that contain predefined entry points. The Web server passes request messages to the application by making calls to these entry points. Because these applications are DLLs, you can debug them by setting your application’s run parameters to launch the server.

To set up your application’s run parameters, choose Run|Parameters and set the Host Application and Run Parameters to specify the executable for the Web server and any parameters it requires when you launch it. For details about these values on your Web server, see the documentation provided by you Web server vendor.

Note:	Some Web Servers require additional changes before you have the rights to launch the Host Application in this way. See your Web server vendor for details.

Tip:	If you are using Windows 2000 with IIS 5, details on all of the changes you need to make to set up your rights properly are described at the following Web site:

http://community.borland.com/article/0,1410,23024,00.html

Once you have set the Host Application and Run Parameters, you can set up your breakpoints so that when the server passes a request message to your DLL, you hit one of your breakpoints, and can debug normally.

Note:	Before launching the Web server using your application’s run parameters, make sure that the server is not already running.

Debugging under Windows NT

Under Windows NT, you must have the correct user rights to debug a DLL. In the User Manager, add your name to the lists granting rights for

Log on as Service

Act as part of the operation system

Generate security audits

Tip:	Insert a hard-coded _asm int 3 into your code where you wish to begin debugging. Recreate your DLL and use Just-In-Time Debugging (Tools|Options|Debug).

Debugging under Windows 2000

Under Windows 2000, you grant the same rights as follows:

1	In the Administrative Tools portion of the Control Panel, click on Local Security Policy. Expand Local Policies and click on User Rights Assignment. Double-click on Act as part of the operating system in the right-hand panel.

2	Select Add to add a user to the list. Add your current user.

3	Reboot so the changes take effect.


Using Web Broker
 DevGuide: Developing Internet applications

Using Web Broker

Topic groups	See also

Web Broker components (located on the Internet tab of the component palette) enable you to create event handlers that are associated with a specific Uniform Resource Identifier (URI). When processing is complete, You can programmatically construct HTML or XML documents and transfer them to the client. You can use Web Broker components for cross-platform application development.

Frequently, the content of Web pages is drawn from databases. You can use Internet components to automatically manage connections to databases, allowing a single DLL to handle numerous simultaneous, thread-safe database connections.

The following sections in this series explain how you use the Web Broker components to create a Web server application.


Creating Web server applications with Web Broker
 DevGuide: Developing Internet applications

Creating Web server applications with Web Broker

Topic groups	See also

To create a new Web server application using the Web Broker architecture:

1	Select File|New|Other.

2	In the New Items dialog box, select the New tab and choose Web Server Application.

3	A dialog box appears, where you can select one of the Web server application types:

ISAPI and NSAPI: Selecting this type of application sets up your project as a DLL, with the exported methods expected by the Web server. It adds the library header to the project file and the required entries to the uses list and exports clause of the project file.

Apache: Selecting this type of application sets up your project as a DLL, with the exported methods expected by the Apache Web server. It adds the library header to the project file and the required entries to the uses list and exports clause of the project file.

CGI stand-alone: Selecting this type of application sets up your project as a console application, and adds the required entries to the uses clause of the project file.

Win-CGI stand-alone: Selecting this type of application sets up your project as a Windows application, and adds the required entries to the uses clause of the project file.

Web Application Debugger stand-alone executable: Selecting this type of application sets up an environment for developing and testing Web server applications. This type of application is not intended for deployment.

Choose the type of Web Server Application that communicates with the type of Web Server your application will use. This creates a new project configured to use Internet components. It includes

The Web module

The Web application object


The Web module
 DevGuide: Developing Internet applications

The Web module

Topic groups	See also

The Web module (TWebModule) is a descendant of TDataModule and may be used in the same way: to provide centralized control for business rules and non-visual components in the Web application.

Add any content producers that your application uses to generate response messages. These can be the built-in content producers such as TPageProducer, TDataSetPageProducer, TDataSetTableProducer, TQueryTableProducer and TInetXPageProducer, or descendants of TCustomContentProducer that you have written yourself. If your application generates response messages that include material drawn from databases, you can add data access components or special components for writing a Web server that acts as a client in a multi-tiered database application.

In addition to storing non-visual components and business rules, the Web module also acts as a Web dispatcher, matching incoming HTTP request messages to action items that generate the responses to those requests.

You may have a data module already that is set up with many of the non-visual components and business rules that you want to use in your Web application. You can replace the Web module with your pre-existing data module. Simply delete the automatically generated Web module and replace it with your data module. Then, add a TWebDispatcher component to your data module, so that it can dispatch request messages to action items, the way a Web module can. If you want to change the way action items are chosen to respond to incoming HTTP request messages, derive a new dispatcher component from TCustomWebDispatcher, and add that to the data module instead.

Your project can contain only one dispatcher. This can either be the Web module that is automatically generated when you create the project, or the TWebDispatcher component that you add to a data module that replaces the Web module. If a second data module containing a dispatcher is created during execution, the Web server application generates a runtime error.

Note:	The Web module that you set up at design time is actually a template. In ISAPI and NSAPI applications, each request message spawns a separate thread, and separate instances of the Web module and its contents are created dynamically for each thread.

Warning:	The Web module in a DLL-based Web server application is cached for later reuse to increase response time. The state of the dispatcher and its action list is not reinitialized between requests. Enabling or disabling action items during execution may cause unexpected results when that module is used for subsequent client requests.


The Web Application object
 DevGuide: Developing Internet applications

The Web Application object

Topic groups	See also

The project that is set up for your Web application contains a global variable named Application. Application is a descendant of TWebApplication (either TISAPIApplication , TApacheApplication, or TCGIApplication) that is appropriate to the type of application you are creating. It runs in response to HTTP request messages received by the Web server.

Warning:	Do not include the Forms or QForms unit in the project uses clause after the CGIApp, ApacheApp, or ISAPIApp unit. Forms also declares a global variable named Application, and if it appears after the CGIApp, ApacheApp, or ISAPIApp unit, Application will be initialized to an object of the wrong type.


The structure of a Web server application
 DevGuide: Developing Internet applications

The structure of a Web server application

Topic groups	See also

When the Web application receives an HTTP request message, it creates a TWebRequest object to represent the HTTP request message, and a TWebResponse object to represent the response that should be returned. The application then passes these objects to the Web dispatcher (either the Web module or a TWebDispatcher component).

Structure of a Server Application

The Web dispatcher controls the flow of the Web server application. The dispatcher maintains a collection of action items (TWebActionItem) that know how to handle certain types of HTTP request messages. The dispatcher identifies the appropriate action items or auto-dispatching components to handle the HTTP request message, and passes the request and response objects to the identified handler so that it can perform any requested actions or formulate a response message. The action items are responsible for reading the request and assembling a response message. Specialized content producer components aid the action items in dynamically generating the content of response messages, which can include custom HTML code or other MIME content. The content producers can make use of other content producers or descendants of THTMLTagAttributes, to help them create the content of the response message.

If you are creating the Web Client in a multi-tiered database application, your Web server application may include additional, auto-dispatching components that represent database information encoded in XML and database manipulation classes encoded in javascript. If you are creating a server that implements a Web Service, your Web server application may include an auto-dispatching component that passes SOAP-based messages on to an invoker that interprets and executes them. The dispatcher calls on these auto-dispatching components to handle the request message after it has tried all of its action items.

When all action items (or auto-dispatching components) have finished creating the response by filling out the TWebResponse object, the dispatcher passes the result back to the Web application. The application sends the response on to the client via the Web server.


The Web dispatcher
 DevGuide: Developing Internet applications

The Web dispatcher

Topic groups	See also

If you are using a Web module, it acts as a Web dispatcher. If you are using a pre-existing data module, you must add a single dispatcher component (TWebDispatcher) to that data module. The dispatcher maintains a collection of action items that know how to handle certain kinds of request messages. When the Web application passes a request object and a response object to the dispatcher, it is responsible for dispatching the request message.

Set up the Web dispatcher by adding actions to the dispatcher.


Adding actions to the dispatcher
 DevGuide: Developing Internet applications

Adding actions to the dispatcher

Topic groups	See also

Open the action editor from the Object Inspector by clicking the ellipsis on the Actions property of the dispatcher. Action items can be added to the dispatcher by clicking the Add button in the action editor.

Add actions to the dispatcher to respond to different request methods or target URIs. You can set up your action items in a variety of ways. You can start with action items that preprocess requests, and end with a default action that checks whether the response is complete and either sends the response or returns an error code. Or, you can add a separate action item for every type of request, where each action item completely handles the request.


Dispatching request messages
 DevGuide: Developing Internet applications

Dispatching request messages

Topic groups	See also

When the dispatcher receives the client request, it generates a BeforeDispatch event. This provides your application with a chance to preprocess the request message before it is seen by any of the action items.

Next, the dispatcher iterates over its list of action items, looking for an entry that matches the PathInfo portion of the request message’s target URL and that also provides the service specified as the method of the request message. It does this by comparing the PathInfo and MethodType properties of the TWebRequest object with the properties of the same name on the action item.

When the dispatcher finds an appropriate action item, it causes that action item to fire. When the action item fires, it does one of the following:

Fills in the response content and sends the response or signals that the request is completely handled.

Adds to the response and then allows other action items to complete the job.

Defers the request to other action items.

After checking all its action items, if the message is not handled the dispatcher checks any specially registered auto-dispatching components that do not use action items. These components are specific to multi-tiered database applications, which are described in Building Web applications using InternetExpress

If, after checking all the action items and any specially registered auto-dispatching components, the request message has still not been fully handled, the dispatcher calls the default action item. The default action item does not need to match either the target URL or the method of the request.

If the dispatcher reaches the end of the action list (including the default action, if any) and no actions have been triggered, nothing is passed back to the server. The server simply drops the connection to the client.

If the request is handled by the action items, the dispatcher generates an AfterDispatch event. This provides a final opportunity for your application to check the response that was generated, and make any last minute changes.


Action items
 DevGuide: Developing Internet applications

Action items

Topic groups	See also

Each action item (TWebActionItem) performs a specific task in response to a given type of request message.

Action items can completely respond to a request or perform part of the response and allow other action items to complete the job. Action items can send the HTTP response message for the request, or simply set up part of the response for other action items to complete. If a response is completed by the action items but not sent, the Web server application sends the response message.

Set up action items for your Web server application by

Adding actions to the dispatcher

Determining when action items fire

Responding to request messages with action items


Determining when action items fire
 DevGuide: Developing Internet applications

Specifying action item properties

Topic groups	See also

Most properties of the action item determine when the dispatcher selects it to handle an HTTP request message. To set the properties of an action item, you must first bring up the action editor: select the Actions property of the dispatcher in the Object Inspector and click on the ellipsis. When an action is selected in the action editor, its properties can be modified in the Object Inspector.

The action item includes properties that specify

The target URL

The request method type

Other properties that influence when the dispatcher fires an action item are described in

Enabling and disabling action items

Choosing a default action item


The target URL
 DevGuide: Developing Internet applications

The target URL

Topic groups	See also

The dispatcher compares the PathInfo property of an action item to the PathInfo of the request message. The value of this property should be the path information portion of the URL for all requests that the action item is prepared to handle. For example, given this URL,

http://www.TSite.com/art/gallery.dll/mammals?animal=dog&color=black

and assuming that the /gallery.dll part indicates the Web server application, the path information portion is

/mammals

Use path information to indicate where your Web application should look for information when servicing requests, or to divide you Web application into logical subservices.


The request method type
 DevGuide: Developing Internet applications

The request method type

Topic groups	See also

The MethodType property of an action item indicates what type of request messages it can process. The dispatcher compares the MethodType property of an action item to the MethodType of the request message. MethodType can take one of the following values:

Value	Meaning
mtGet	The request is asking for the information associated with the target URI to be returned in a response message.
mtHead	The request is asking for the header properties of a response, as if servicing an mtGet request, but omitting the content of the response.
mtPost	The request is providing information to be posted to the Web application.
mtPut	The request asks that the resource associated with the target URI be replaced by the content of the request message.
mtAny	Matches any request method type, including mtGet, mtHead, mtPut, and mtPost.


Enabling and disabling action items
 DevGuide: Developing Internet applications

Enabling and disabling action items

Topic groups	See also

Each action item has an Enabled property that can be used to enable or disable that action item. By setting Enabled to False, you disable the action item so that it is not considered by the dispatcher when it looks for an action item to handle a request.

A BeforeDispatch event handler can control which action items should process a request by changing the Enabled property of the action items before the dispatcher begins matching them to the request message.

Caution:	Changing the Enabled property of an action during execution may cause unexpected results for subsequent requests. If the Web server application is a DLL that caches Web modules, the initial state will not be reinitialized for the next request. Use the BeforeDispatch event to ensure that all action items are correctly initialized to their appropriate starting states.


Choosing a default action item
 DevGuide: Developing Internet applications

Choosing a default action item

Topic groups	See also

Only one of the action items can be the default action item. The default action item is selected by setting its Default property to True. When the Default property of an action item is set to True, the Default property for the previous default action item (if any) is set to False.

When the dispatcher searches its list of action items to choose one to handle a request, it stores the name of the default action item. If the request has not been fully handled when the dispatcher reaches the end of its list of action items, it executes the default action item.

The dispatcher does not check the PathInfo or MethodType of the default action item. The dispatcher does not even check the Enabled property of the default action item. Thus, you can make sure the default action item is only called at the very end by setting its Enabled property to False.

The default action item should be prepared to handle any request that is encountered, even if it is only to return an error code indicating an invalid URI or MethodType. If the default action item does not handle the request, no response is sent to the Web client.

Caution:	Changing the Default property of an action during execution may cause unexpected results for the current request. If the Default property of an action that has already been triggered is set to True, that action will not be re-evaluated and the dispatcher will not trigger that action when it reaches the end of the action list.


Responding to request messages with action items
 DevGuide: Developing Internet applications

Responding to request messages with action items

Topic groups	See also

The real work of the Web server application is performed by action items when they execute. When the Web dispatcher fires an action item, that action item can respond to the current request message in two ways:

If the action item has an associated producer component as the value of its Producer property, that producer automatically assigns the Content of the response message using its Content method. The Internet page of the component palette includes a number of content producer components that can help construct an HTML page for the content of the response message.

After the producer has assigned any response content (if there is an associated producer), the action item receives an OnAction event. The OnAction event handler is passed the TWebRequest object that represents the HTTP request message and a TWebResponse object to fill with any response information.

If the action item’s content can be generated by a single content producer, it is simplest to assign the content producer as the action item’s Producer property. However, you can always access any content producer from the OnAction event handler as well. The OnAction event handler allows more flexibility, so that you can use multiple content producers, assign response message properties, and so on.

Both the content-producer component and the OnAction event handler can use any objects or runtime library methods to respond to request messages. They can access databases, perform calculations, construct or select HTML documents, and so on. For more information about generating response content using content-producer components, see Generating the content of response messages.

Sending the response

An OnAction event handler can send the response back to the Web client by using the methods of the TWebResponse object. However, if no action item sends the response to the client, it will still get sent by the Web server application as long as the last action item to look at the request indicates that the request was handled.

Using multiple action items

You can respond to a request from a single action item, or divide the work up among several action items. If the action item does not completely finish setting up the response message, it must signal this state in the OnAction event handler by setting the Handled parameter to False.

If many action items divide up the work of responding to request messages, each setting Handled to False so that others can continue, make sure the default action item leaves the Handled parameter set to True. Otherwise, no response will be sent to the Web client.

When dividing the work among several action items, either the OnAction event handler of the default action item or the AfterDispatch event handler of the dispatcher should check whether all the work was done and set an appropriate error code if it is not.


Accessing client request information
 DevGuide: Developing Internet applications

Accessing client request information

Topic groups	See also

When an HTTP request message is received by the Web server application, the headers of the client request are loaded into the properties of a TWebRequest object. In NSAPI and ISAPI applications, the request message is encapsulated by a TISAPIRequest object. Console CGI applications use TCGIRequest objects, and Windows CGI applications use TWinCGIRequest objects.

The properties of the request object are read-only. You can use them to gather all of the information available in the client request, including

Request header information

The content of the request message


Properties that contain request header information
 DevGuide: Developing Internet applications

Properties that contain request header information

Topic groups	See also

Most properties in a request object contain information about the request that comes from the HTTP request header. Not every request supplies a value for every one of these properties. Also, some requests may include header fields that are not surfaced in a property of the request object, especially as the HTTP standard continues to evolve. To obtain the value of a request header field that is not surfaced as one of the properties of the request object, use the GetFieldByName method.

The request header properties can be categorized by function:

Properties that identify the target

Properties that describe the Web client

Properties that identify the purpose of the request

Properties that describe the expected response

Properties that describe the content


Properties that identify the target
 DevGuide: Developing Internet applications

Properties that identify the target

Topic groups	See also

The full target of the request message is given by the URL property. Usually, this is a URL that can be broken down into the protocol (HTTP), Host (server system), ScriptName (server application), PathInfo (location on the host), and Query.

Each of these pieces is surfaced in its own property. The protocol is always HTTP, and the Host and ScriptName identify the Web server application. The dispatcher uses the PathInfo portion when matching action items to request messages. The Query is used by some requests to specify the details of the requested information. Its value is also parsed for you as the QueryFields property.


Properties that describe the Web client
 DevGuide: Developing Internet applications

Properties that describe the Web client

Topic groups	See also

The request includes several properties that provide information about where the request originated. These include everything from the e-mail address of the sender (the From property), to the URI where the message originated (the Referer or RemoteHost property). If the request contains any content, and that content does not arise from the same URI as the request, the source of the content is given by the DerivedFrom property. You can also determine the IP address of the client (the RemoteAddr property), and the name and version of the application that sent the request (the UserAgent property).


Properties that identify the purpose of the request
 DevGuide: Developing Internet applications

Properties that identify the purpose of the request

Topic groups	See also

The Method property is a string describing what the request message is asking the server application to do. The HTTP 1.1 standard defines the following methods:

Value	What the message requests
OPTIONS	Information about available communication options.
GET	Information identified by the URL property.
HEAD	Header information from an equivalent GET message, without the content of the response.
POST	The server application to post the data included in the Content property, as appropriate.
PUT	The server application to replace the resource indicated by the URL property with the data included in the Content property.
DELETE	The server application to delete or hide the resource identified by the URL property.
TRACE	The server application to send a loop-back to confirm receipt of the request.
The Method property may indicate any other method that the Web client requests of the server.

The Web server application does not need to provide a response for every possible value of Method. The HTTP standard does require that it service both GET and HEAD requests, however.

The MethodType property indicates whether the value of Method is GET (mtGet), HEAD (mtHead), POST (mtPost), PUT (mtPut) or some other string (mtAny). The dispatcher matches the value of the MethodType property with the MethodType of each action item.


Properties that describe the expected response
 DevGuide: Developing Internet applications

Properties that describe the expected response

Topic groups	See also

The Accept property indicates the media types the Web client will accept as the content of the response message. The IfModifiedSince property specifies whether the client only wants information that has changed recently. The Cookie property includes state information (usually added previously by your application) that can modify the response.


Properties that describe the content
 DevGuide: Developing Internet applications

Properties that describe the content

Topic groups	See also

Most requests do not include any content, as they are requests for information. However, some requests, such as POST requests, provide content that the Web server application is expected to use. The media type of the content is given in the ContentType property, and its length in the ContentLength property. If the content of the message was encoded (for example, for data compression), this information is in the ContentEncoding property. The name and version number of the application that produced the content is specified by the ContentVersion property. The Title property may also provide information about the content.


The content of HTTP request messages
 DevGuide: Developing Internet applications

The content of HTTP request messages

Topic groups	See also

In addition to the header fields, some request messages include a content portion that the Web server application should process in some way. For example, a POST request might include information that should be added to a database maintained by the Web server application.

The unprocessed value of the content is given by the Content property. If the content can be parsed into fields separated by ampersands (&), a parsed version is available in the ContentFields property.


Creating HTTP response messages
 DevGuide: Developing Internet applications

Creating HTTP response messages

Topic groups	See also

When the Web server application creates a TWebRequest object for an incoming HTTP request message, it also creates a corresponding TWebResponse object to represent the response message that will be sent in return. In NSAPI and ISAPI applications, the response message is encapsulated by a TISAPIResponse object. Console CGI applications use TCGIResponse objects, and Windows CGI applications use TWinCGIResponse objects.

The action items that generate the response to a Web client request fill in the properties of the response object. In some cases, this may be as simple as returning an error code or redirecting the request to another URI. In other cases, this may involve complicated calculations that require the action item to fetch information from other sources and assemble it into a finished form. Most request messages require some response, even if it is only the acknowledgment that a requested action was carried out.

Responding to HTTP requests involves

Filling in the response header

Setting the response content

Sending the response


Filling in the response header
 DevGuide: Developing Internet applications

Filling in the response header

Topic groups	See also

Most of the properties of the TWebResponse object represent the header information of the HTTP response message that is sent back to the Web client. An action item sets these properties from its OnAction event handler.

Not every response message needs to specify a value for every one of the header properties. The properties that should be set depend on the nature of the request and the status of the response.

Use the response object properties for

Indicating the response status

Indicating the need for client action

Describing the server application

Describing the content


Indicating the response status
 DevGuide: Developing Internet applications

Indicating the response status

Topic groups	See also

Every response message must include a status code that indicates the status of the response. You can specify the status code by setting the StatusCode property. The HTTP standard defines a number of standard status codes with predefined meanings. In addition, you can define your own status codes using any of the unused possible values.

Each status code is a three-digit number where the most significant digit indicates the class of the response, as follows:

1xx: Informational (The request was received but has not been fully processed).

2xx: Success (The request was received, understood, and accepted).

3xx: Redirection (Further action by the client is needed to complete the request).

4xx: Client Error (The request cannot be understood or cannot be serviced).

5xx: Server Error (The request was valid but the server could not handle it).

Associated with each status code is a string that explains the meaning of the status code. This is given by the ReasonString property. For predefined status codes, you do not need to set the ReasonString property. If you define your own status codes, you should also set the ReasonString property.


Indicating the need for client action
 DevGuide: Developing Internet applications

Indicating the need for client action

Topic groups	See also

When the status code is in the 300-399 range, the client must perform further action before the Web server application can complete its request. If you need to redirect the client to another URI, or indicate that a new URI was created to handle the request, set the Location property. If the client must provide a password before you can proceed, set the WWWAuthenticate property.


Describing the server application
 DevGuide: Developing Internet applications

Describing the server application

Topic groups	See also

Some of the response header properties describe the capabilities of the Web server application. The Allow property indicates the methods to which the application can respond. The Server property gives the name and version number of the application used to generate the response. The Cookies property can hold state information about the client’s use of the server application which is included in subsequent request messages.


Describing the content
 DevGuide: Developing Internet applications

Describing the content

Topic groups	See also

Several properties describe the content of the response. ContentType gives the media type of the response, and ContentVersion is the version number for that media type. ContentLength gives the length of the response. If the content is encoded (such as for data compression), indicate this with the ContentEncoding property. If the content came from another URI, this should be indicated in the DerivedFrom property. If the value of the content is time-sensitive, the LastModified property and the Expires property indicate whether the value is still valid. The Title property can provide descriptive information about the content.


Setting the response content
 DevGuide: Developing Internet applications

Setting the response content

Topic groups	See also

For some requests, the response to the request message is entirely contained in the header properties of the response. In most cases, however, action item assigns some content to the response message. This content may be static information stored in a file, or information that was dynamically produced by the action item or its content producer.

You can set the content of the response message by using either the Content property or the ContentStream property.

The Content property is a string. Delphi strings are not limited to text values, so the value of the Content property can be a string of HTML commands, graphics content such as a bit-stream, or any other MIME content type.

Use the ContentStream property if the content for the response message can be read from a stream. For example, if the response message should send the contents of a file, use a TFileStream object for the ContentStream property. As with the Content property, ContentStream can provide a string of HTML commands or other MIME content type. If you use the ContentStream property, do not free the stream yourself. The Web response object automatically frees it for you.

Note:	If the value of the ContentStream property is not nil, the Content property is ignored.


Sending the response
 DevGuide: Developing Internet applications

Sending the response

Topic groups	See also

If you are sure there is no more work to be done in response to a request message, you can send a response directly from an OnAction event handler. The response object provides two methods for sending a response: SendResponse and SendRedirect. Call SendResponse to send the response using the specified content and all the header properties of the TWebResponse object. If you only need to redirect the Web client to another URI, the SendRedirect method is more efficient.

If none of the event handlers send the response, the Web application object sends it after the dispatcher finishes. However, if none of the action items indicate that they have handled the response, the application will close the connection to the Web client without sending any response.


Generating the content of response messages
 DevGuide: Developing Internet applications

Generating the content of response messages

Topic groups	See also

Delphi provides a number of objects to assist your action items in producing content for HTTP response messages. You can use these objects to generate strings of HTML commands that are saved in a file or sent directly back to the Web client. You can write your own content producers, deriving them from TCustomContentProducer or one of its descendants.

TCustomContentProducer provides a generic interface for creating any MIME type as the content of an HTTP response message. Its descendants include page producers and table producers:

Page producers scan HTML documents for special tags that they replace with customized HTML code. They are described in Using page producer components.

Table producers create HTML commands based on the information in a dataset. They are described in Using database information in responses.


Using page producer components
 DevGuide: Developing Internet applications

Using page producer components

Topic groups	See also

Page producers (TPageProducer and its descendants) take an HTML template and convert it by replacing special HTML-transparent tags with customized HTML code. You can store a set of standard response templates that are filled in by page producers when you need to generate the response to an HTTP request message. You can chain page producers together to iteratively build up an HTML document by successive refinement of the HTML-transparent tags.


HTML templates
 DevGuide: Developing Internet applications

HTML templates

Topic groups	See also

An HTML template is a sequence of HTML commands and HTML-transparent tags. An HTML-transparent tag has the form

<#TagName Param1=Value1 Param2=Value2 ...>

The angle brackets (< and >) define the entire scope of the tag. A pound sign (#) immediately follows the opening angle bracket (<) with no spaces separating it from the angle bracket. The pound sign identifies the string to the page producer as an HTML-transparent tag. The tag name immediately follows the pound sign with no spaces separating it from the pound sign. The tag name can be any valid identifier and identifies the type of conversion the tag represents.

Following the tag name, the HTML-transparent tag can optionally include parameters that specify details of the conversion to be performed. Each parameter is of the form ParamName=Value, where there is no space between the parameter name, the equals symbol (=) and the value. The parameters are separated by whitespace.

The angle brackets (< and >) make the tag transparent to HTML browsers that do not recognize the #TagName construct.

When working with HTML templates, you will

Optionally, Use predefined HTML-transparent tag Names

Specify the HTML template

Convert HTML-transparent tags


Using predefined HTML-transparent tag names
 DevGuide: Developing Internet applications

Using predefined HTML-transparent tag names

Topic groups	See also

While you can create your own HTML-transparent tags to represent any kind of information processed by your page producer, there are several predefined tag names associated with values of the TTag data type. These predefined tag names correspond to HTML commands that are likely to vary over response messages. They are listed in the following table:

Tag Name	TTag value	What the tag should be converted to
Link	tgLink	A hypertext link. The result is an HTML sequence beginning with an <A> tag and ending with an </A> tag.
Image	tgImage	A graphic image. The result is an HTML <IMG> tag.
Table	tgTable	An HTML table. The result is an HTML sequence beginning with a <TABLE> tag and ending with a </TABLE> tag.
ImageMap	tgImageMap	A graphic image with associated hot zones. The result is an HTML sequence beginning with a <MAP> tag and ending with a </MAP> tag.
Object	tgObject	An embedded ActiveX object. The result is an HTML sequence beginning with an <OBJECT> tag and ending with an </OBJECT> tag.
Embed	tgEmbed	A Netscape-compliant add-in DLL. The result is an HTML sequence beginning with an <EMBED> tag and ending with an </EMBED> tag.
Any other tag name is associated with tgCustom. The page producer supplies no built-in processing of the predefined tag names. They are simply provided to help applications organize the conversion process into many of the more common tasks.

Note:	The predefined tag names are case insensitive.


Specifying the HTML template
 DevGuide: Developing Internet applications

Specifying the HTML template

Topic groups	See also

Page producers provide you with many choices in how to specify the HTML template. You can set the HTMLFile property to the name of a file that contains the HTML template. You can set the HTMLDoc property to a TStrings object that contains the HTML template. If you use either the HTMLFile property or the HTMLDoc property to specify the template, you can generate the converted HTML commands by calling the Content method.

In addition, you can call the ContentFromString method to directly convert an HTML template that is a single string which is passed in as a parameter. You can also call the ContentFromStream method to read the HTML template from a stream. Thus, for example, you could store all your HTML templates in a memo field in a database, and use the ContentFromStream method to obtain the converted HTML commands, reading the template directly from a TBlobStream object.


Converting HTML-transparent tags
 DevGuide: Developing Internet applications

Converting HTML-transparent tags

Topic groups	See also

The page producer converts the HTML template when you call one of its Content methods. When the Content method encounters an HTML-transparent tag, it triggers the OnHTMLTag event. You must write an event handler to determine the type of tag encountered, and to replace it with customized content. See Using page producers from an action item for a simple example of converting HTML-transparent tags.

If you do not create an OnHTMLTag event handler for the page producer, HTML-transparent tags are replaced with an empty string.


Using page producers from an action item
 DevGuide: Developing Internet applications

Using page producers from an action item

Topic groups	See also

A typical use of a page producer component uses the HTMLFile property to specify a file containing an HTML template. The OnAction event handler calls the Content method to convert the template into a final HTML sequence:

procedure WebModule1.MyActionEventHandler(Sender: TObject; Request: TWebRequest;

   Response: TWebResponse; var Handled: Boolean);

begin

  PageProducer1.HTMLFile := 'Greeting.html';

  Response.Content := PageProducer1.Content;

end;

Greeting.html is a file that contains this HTML template:

<HTML>

<HEAD><TITLE>Our Brand New Web Site</TITLE></HEAD>

<BODY>

Hello <#UserName>!  Welcome to our Web site.

</BODY>

</HTML>

The OnHTMLTag event handler replaces the custom tag (<#UserName>) in the HTML during execution:

procedureWebModule1.PageProducer1HTMLTag(Sender : TObject;Tag: TTag;

   const TagString: string; TagParams: TStrings;varReplaceText:string);

begin

  if CompareText(TagString,'UserName') = 0 then

    ReplaceText := TPageProducer(Sender).Dispatcher.Request.Content;

end;

If the content of the request message was the string Mr. Ed, the value of Response.Content would be

<HTML>

<HEAD><TITLE>Our Brand New Web Site</TITLE></HEAD>

<BODY>

Hello Mr. Ed!  Welcome to our Web site.

</BODY>

</HTML>

Note:	This example uses an OnAction event handler to call the content producer and assign the content of the response message. You do not need to write an OnAction event handler if you assign the page producer’s HTMLFile property at design time. In that case, you can simply assign PageProducer1 as the value of the action item’s Producer property to accomplish the same effect as the OnAction event handler above.


Chaining page producers together
 DevGuide: Developing Internet applications

Chaining page producers together

Topic groups	See also

The replacement text from an OnHTMLTag event handler need not be the final HTML sequence you want to use in the HTTP response message. You may want to use several page producers, where the output from one page producer is the input for the next.

The simplest way is to chain the page producers together is to associate each page producer with a separate action item, where all action items have the same PathInfo and MethodType. The first action item sets the content of the Web response message from its content producer, but its OnAction event handler makes sure the message is not considered handled. The next action item uses the ContentFromString method of its associated producer to manipulate the content of the Web response message, and so on. Action items after the first one use an OnAction event handler such as the following:

procedure WebModule1.Action2Action(Sender: TObject; Request: TWebRequest;

   Response: TWebResponse; var Handled: Boolean);

begin

  Response.Content := PageProducer2.ContentFromString(Response.Content);

end;

For example, consider an application that returns calendar pages in response to request messages that specify the month and year of the desired page. Each calendar page contains a picture, followed by the name and year of the month between small images of the previous month and next months, followed by the actual calendar. The resulting image looks something like this:

The general form of the calendar is stored in a template file. It looks like this:

<HTML>

<Head></HEAD>

<BODY>

<#MonthlyImage> <#TitleLine><#MainBody>

</BODY>

</HTML>

The OnHTMLTag event handler of the first page producer looks up the month and year from the request message. Using that information and the template file, it does the following:

Replaces <#MonthlyImage> with <#Image Month=January Year=2000>.

Replaces <#TitleLine> with <#Calendar Month=December Year=1999 Size=Small> January 2000 <#Calendar Month=February Year=2000 Size=Small>.

Replaces <#MainBody> with <#Calendar Month=January Year=2000 Size=Large>.

The OnHTMLTag event handler of the next page producer uses the content produced by the first page producer, and replaces the <#Image Month=January Year=2000> tag with the appropriate HTML <IMG> tag. Yet another page producer resolves the #Calendar tags with appropriate HTML tables.


Using database information in responses
 DevGuide: Developing Internet applications

Using database information in responses

Topic groups	See also

The response to an HTTP request message may include information taken from a database. Specialized content producers on the Internet palette page can generate the HTML to represent the records from a database in an HTML table.

To return database information in an HTTP response, you would typically

Add a session to the Web module

Represent the database information in HTML

As an alternate approach, special components on the InternetExpress page of the component palette let you build Web servers that are part of a multi-tiered database application. See Building Web applications using InternetExpress for details.


Adding a session to the Web module
 DevGuide: Developing Internet applications

Adding a session to the Web module

Topic groups	See also

Both console CGI applications and Win-CGI applications are launched in response to HTTP request messages. When working with databases in these types of applications, you can use the default session to manage your database connections, because each request message has its own instance of the application. Each instance of the application has its own distinct, default session.

When writing an ISAPI application or an NSAPI application, however, each request message is handled in a separate thread of a single application instance. To prevent the database connections from different threads from interfering with each other, you must give each thread its own session.

Each request message in an ISAPI or NSAPI application spawns a new thread. The Web module for that thread is generated dynamically at runtime. Add a TSession object to the Web module to handle the database connections for the thread that contains the Web module.

Separate instances of the Web module are generated for each thread at runtime. Each of those modules contains the session object. Each of those sessions must have a separate name, so that the threads that handle separate request messages do not interfere with each other’s database connections. To cause the session objects in each module to dynamically generate unique names for themselves, set the AutoSessionName property of the session object. Each session object will dynamically generate a unique name for itself and set the SessionName property of all datasets in the module to refer to that unique name. This allows all interaction with the database for each request thread to proceed without interfering with any of the other request messages. For more information on sessions, see Managing database sessions.


Representing a dataset in HTML
 DevGuide: Developing Internet applications

Representing a dataset in HTML

Topic groups	See also

Specialized Content producer components on the Internet palette page supply HTML commands based on the records of a dataset. There are two types of data-aware content producers:

The dataset page producer, which formats the fields of a dataset into the text of an HTML document.

Table producers, which format the records of a dataset as an HTML table.


Using dataset page producers
 DevGuide: Developing Internet applications

Using dataset page producers

Topic groups	See also

Dataset page producers work like other page producer components: they convert a template that includes HTML-transparent tags into a final HTML representation. They include the special ability, however, of converting tags that have a tagname which matches the name of a field in a dataset into the current value of that field. For more information about using page producers in general, see Using page producer components.

To use a dataset page producer, add a TDataSetPageProducer component to your Web module and set its DataSet property to the dataset whose field values should be displayed in the HTML content. Create an HTML template that describes the output of your dataset page producer. For every field value you want to display, include a tag of the form

<#FieldName>

in the HTML template, where FieldName specifies the name of the field in the dataset whose value should be displayed.

When your application calls the Content, ContentFromString, or ContentFromStream method, the dataset page producer substitutes the current field values for the tags that represent fields.


Using table producers
 DevGuide: Developing Internet applications

Using table producers

Topic groups	See also

The Internet palette page includes two components that create an HTML table to represent the records of a dataset:

Dataset table producers, which format the fields of a dataset into the text of an HTML document.

Query table producers, which runs a query after setting parameters supplied by the request message and formats the resulting dataset as an HTML table.

Using either of the two table producers, you can customize the appearance of a resulting HTML table by specifying properties for the table’s color, border, separator thickness, and so on. To set the properties of a table producer at design time, double-click the table producer component to display the Response Editor dialog.

Specifying the table attributes

Specifying the row attributes

Specifying the columns

Embedding tables in HTML documents


Specifying the table attributes
 DevGuide: Developing Internet applications

Specifying the table attributes

Topic groups	See also

Table producers use the THTMLTableAttributes object to describe the visual appearance of the HTML table that displays the records from the dataset. The THTMLTableAttributes object includes properties for the table’s width and spacing within the HTML document, and for its background color, border thickness, cell padding, and cell spacing. These properties are all turned into options on the HTML <TABLE> tag created by the table producer.

At design time, specify these properties using the Object Inspector. Select the table producer object in the Object Inspector and expand the TableAttributes property to access the display properties of the THTMLTableAttributes object.

You can also specify these properties programmatically at runtime.


Specifying the row attributes
 DevGuide: Developing Internet applications

Specifying the row attributes

Topic groups	See also

Similar to the table attributes, you can specify the alignment and background color of cells in the rows of the table that display data. The RowAttributes property is a THTMLTableRowAttributes object.

At design time, specify these properties using the Object Inspector by expanding the RowAttributes property. You can also specify these properties programmatically at runtime.

You can also adjust the number of rows shown in the HTML table by setting the MaxRows property.


Specifying the columns
 DevGuide: Developing Internet applications

Specifying the columns

Topic groups	See also

If you know the dataset for the table at design time, you can use the Columns editor to customize the columns’ field bindings and display attributes. Select the table producer component, and right-click. From the context menu, choose the Columns editor. This lets you add, delete, or rearrange the columns in the table. You can set the field bindings and display properties of individual columns in the Object Inspector after selecting them in the Columns editor.

If you are getting the name of the dataset from the HTTP request message, you can’t bind the fields in the Columns editor at design time. However, you can still customize the columns programmatically at runtime, by setting up the appropriate THTMLTableColumn objects and using the methods of the Columns property to add them to the table. If you do not set up the Columns property, the table producer creates a default set of columns that match the fields of the dataset and specify no special display characteristics.


Embedding tables in HTML documents
 DevGuide: Developing Internet applications

Embedding tables in HTML documents

Topic groups	See also

You can embed the HTML table that represents your dataset in a larger document by using the Header and Footer properties of the table producer. Use Header to specify everything that comes before the table, and Footer to specify everything that comes after the table.

You may want to use another content producer (such as a page producer) to create the values for the Header and Footer properties.

If you embed your table in a larger document, you may want to add a caption to the table. Use the Caption and CaptionAlignment properties to give your table a caption.


Using TDataSetTableProducer
 DevGuide: Developing Internet applications

Using TDataSetTableProducer

Topic groups	See also

TDataSetTableProducer is a table producer that creates an HTML table for a dataset. Set the DataSet property of TDataSetTableProducer to specify the dataset that contains the records you want to display. You do not set the DataSource property, as you would for most data-aware objects in a conventional database application. This is because TDataSetTableProducer generates its own data source internally.

You can set the value of DataSet at design time if your Web application always displays records from the same dataset. You must set the DataSet property at runtime if you are basing the dataset on the information in the HTTP request message.


Using TQueryTableProducer
 DevGuide: Developing Internet applications

Using TQueryTableProducer

Topic groups	See also

You can produce an HTML table to display the results of a query, where the parameters of the query come from the HTTP request message. Specify the TQuery object that uses those parameters as the Query property of a TQueryTableProducer component.

If the request message is a GET request, the parameters of the query come from the Query fields of the URL that was given as the target of the HTTP request message. If the request message is a POST request, the parameters of the query come from the content of the request message.

When you call the Content method of TQueryTableProducer, it runs the query, using the parameters it finds in the request object. It then formats an HTML table to display the records in the resulting dataset.

As with any table producer, you can customize the display properties or column bindings of the HTML table, or embed the table in a larger HTML document.


Debugging with a Microsoft IIS server
 DevGuide: Developing Internet applications

Debugging with a Microsoft IIS server

Topic groups	See also

To debug a Web server application using Microsoft IIS server (version 3 or earlier), choose Run|Parameters and set your application’s run parameters as follows:

Host Application: c:\winnt\system32\inetsrv\inetinfo.exe

Run Parameters:   -e w3svc

This starts the IIS Server and allows you to debug your ISAPI DLL.

Note:	Your directory path for inetinfo.exe may differ from the example.

If you are using version 4 or later, you must first make some changes to the Registry and the IIS Administration service:

1	Use DCOMCnfg to change the identity of the IIS Admin Service to your user account.

2	Use the Registry Editor (REGEDIT) or other utility to remove the “LocalService” keyword from all IISADMIN-related subkeys under HKEY_CLASSES_ROOT/AppID and HKEY_CLASSES_ROOT/CLSID. This keyword appears in the following subkeys:

{61738644-F196-11D0-9953-00C04FD919C1} // IIS WAMREG admin Service

{9F0BD3A0-EC01-11D0-A6A0-00A0C922E752} // IIS Admin Crypto Extension

{A9E69610-B80D-11D0-B9B9-00A0C922E750} // IISADMIN Service

In addition, under the AppID node, remove the “RunAs” keyword from the first two of these subkeys. To the last subkey listed, add “Interactive User” as the value of the “RunAs” keyword.

3	Still using the Registry Editor, add “LocalService32” subkeys to all IISADMIN-related subkeys under the CLSID node. That is, for every subkey listed in step 2 (and any others under which you found the “LocalService” keyword), add a “LocalService32” subkey under the CLSID/<subkey> node. Set the default value of these new keys to

c:\\winnt\\system32\\inetsrv\\inetinfo.exe -e w3svc

(the path for inetinfo.exe may differ for your system).

4	Add a value of “dword:3” to the “Start” keyword for the following subkeys:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\IISADMIN]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSDTC]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC]

5	Stop the WWW, FTP, and IISAdmin services from the Microsoft Management Console or the Services dialog box in the control panel. As an alternative, you can simply do KILL INETINFO using KILL.EXE from the NT Resource Kit.

Now you are ready to debug in the same way as when using IIS version 3 or earlier. That is, choose Run|Parameters and set your application’s run parameters as follows:

Host Application: c:\winnt\system32\inetsrv\inetinfo.exe

Run Parameters:   -e w3svc

Note:	When you have finished debugging, you will need to back out all the Registry changes you made in steps 2 through 4.

Debugging under MTS

Another approach you can take when using IIS is to configure your Web directory as an MTS Library package. You can then debug your ISAPI dll by running it under MTS.

To configure the Web directory as an MTS Library package, use the following steps:

1	Start the Internet Service Manager. You should see both the Internet Information Server and the Microsoft Transaction Server trees.

2	Expand the Internet Information Server tree to view the items under “Default Web Site”. Select the Web directory where your ISAPI dll is installed. Right click and choose Properties.

3	On the Virtual Directory tab page, check Run in separate memory space (isolated process), and click OK.

4	Expand the Microsoft Transaction Server tree to view the items under “Packages Installed”. Right click on the “Packages Installed” node and select Refresh.

5	You will see a package with the same suffix as the Web directory. Right click this package and choose Properties.

6	On the Identity tab page, select the Interactive User radio button, and click OK.

The previous steps configure your Web directory. After doing so, you can debug your ISAPI DLL as follows:

1	In Delphi, choose Run|Parameters. In the Host Application field, enter the fully qualified pathname of the MTS executable. Typically, this is

c:\winnt\system32\mtx.exe

2	In the parameters field, you must use the /p option with the name of the MTS package. To get this value, start the Internet Service Manager and expand the Microsoft Transaction Server tree to view the items under “Packages Installed”. Right click on the package with the same suffix as the Web directory. Choose Properties, and copy the package name from the General tab page to the clipboard.

In the parameters field, paste the name of the package, and then surround it with double quotes and precede the quoted string with /p:. The resulting parameters field should look similar to the following:

/p:"IIS-{Default Web Site//ROOT/WEBPUB/DEMO}"

Note that there should not be a space between the colon and the package name.

Tip:	When the Web directory is installed as an MTS package, you can also use MTS to easily shut down the DLL. Just expand the Microsoft Transaction Server tree in the Internet Service Manager so that you can see the items under the “Packages Installed” node. Right click on the package with the same suffix as the Web directory and choose Shut Down.


Debugging with a Windows 95 Personal Web Server
 DevGuide: Developing Internet applications

Debugging with a Windows 95 Personal Web Server

Topic groups	See also

To debug a Web server application using Personal Web Server, set your application’s run parameters as follows:

Host Application: c:\Program Files\websvc\system\inetsw95.exe

Run Parameters:   -w3svc

This starts the Personal Web Server and allows you to debug your ISAPI DLL.

Note:	Your directory path for inetsw95.exe may differ from the example.


Debugging with Netscape Server Version 2.0
 DevGuide: Developing Internet applications

Debugging with Netscape Server Version 2.0

Topic groups	See also

Before using Web server applications on Netscape servers, you must make certain configuration changes.

First, copy the ISAPITER.DLL file (from the Bin directory) into the C:\Netscape\Server\Nsapi\Examples directory. (Your directory path may differ.)

Next, make the following modifications to the server configuration files located in the C:\Netscape\Server\Httpd-<servername>\Config directory.

1	In the OBJ.CONF file, insert the line

Init funcs="handle_isapi,check_isapi,log_isapi" fn="load_modules"

shlib="c:/netscape/server/nsapi/examples/ISAPIter.dll"

after the line

Init fn=load-types mime-types=mime.types

2	In the <Object name=default> section of OBJ.CONF, insert the lines

NameTrans from="/scripts" fn="pfx2dir" dir="C:/Netscape/Server/docs/scripts"

name="isapi"

before the line

NameTrans fn=document-root root="C:/Netscape/Server/docs"

3	Add the following section to the end of OBJ.CONF:

<Object name="isapi">

PathCheck fn="check_isapi"

ObjectType fn="force-type" type="magnus-internal/isapi"

Service fn="handle_isapi"

</Object>

4	Add the following line to the end of the MIME.TYPES file:

type=magnus-internal/isapi exts=dll

This should be the last line in the file.

Note:	Line breaks are included in steps 1 and 2 above only to enhance readability. Do not type carriage-returns when you place these lines in configuration files.

To debug a Web server application using Netscape Fast Track server, set the application’s run parameters as follows:

Host Application: c:\Netscape\server\bin\httpd\httpd.exe

Run Parameters:   c:\Netscape\server\httpd-<servername>\config

This starts the server and indicates to the server where the configuration files are located.


Debugging CGI and Win-CGI applications
 DevGuide: Developing Internet applications

Debugging CGI and Win-CGI applications

Topic groups	See also

It is more difficult to debug CGI and Win-CGI applications, because the application itself must be launched by the Web server.

Simulating the server

For Win-CGI applications, you can simulate the server by manually writing the configuration settings file that contains the request information. Then launch the Win-CGI application, passing the location of the file containing the client information and the location of a file that the Win-CGI program should use to create content. You can then debug normally.

Debugging as a DLL

Another approach you can take with both CGI and Win-CGI applications is first to create and debug your application as an ISAPI or NSAPI application. Once your ISAPI or NSAPI application is working smoothly, convert it to a CGI or Win-CGI application. To convert your application, use the following steps:

1	Right-click the Web module and choose Add To Repository.

2	In the Add To Repository dialog, give your Web module a title, text description, repository page (probably Data Modules), author name, and icon.

3	Choose OK to save your web module as a template.

4	From the main menu, choose File|New and select Web Server Application. In the New Web Server Application dialog, choose CGI or Win-CGI, as appropriate.

5	Delete the automatically generated Web Module.

6	From the main menu, choose File|New and select the template you saved in step 3. This will be on the page you specified in step 2.

CGI and Win-CGI applications are simpler than ISAPI and NSAPI applications. Each instance of a CGI or Win-CGI application must handle only a single thread. Thus, these applications do not encounter the multi-threading issues that ISAPI and NSAPI applications must deal with. They also are immune to the problems that can arise from the caching of Web modules in ISAPI and NSAPI applications.


Using WebSnap
 DevGuide: Developing Internet applications

Using WebSnap

Topic groups	See also

WebSnap augments WebBroker with new components, wizards, and views—making it easier to build Web applications that contain complex, data-driven Web pages. WebSnap's support for multiple modules and for server-side scripts makes team development easier.

The dispatcher components automatically handle requests for page content, HTML form submissions, and requests for dynamic images. New components called adapters provide a means to define a scriptable interface to the business rules of your application. For example, the TDataSetAdapter object is used to make data-set components scriptable. You can use new producer components to quickly build complex, data-driven forms and tables, or to use XSL to generate a page. You can use the session component to keep track of end-users. You can use the user list component to provide access to user names, passwords, and access rights.

The Web application wizard allows you to quickly build an application that is customized with the components that you will need. The Web page module wizard allows you to create a module that defines a new page in your application. Or use the Web data module wizard to create a container for components that are shared across your Web application.

The page module views make it possible to see the result of server-side script without running the application. The Preview tab shows the page in an embedded browser. The HTML Result view shows the generated HTML. The XSL Tree and XML Tree views make it easier to work with XML and XSL.

To support a team of developers, you can use WebSnap's multiple-module support to partition the application into units that can be worked on independently. When creating a new page module, you can have the page module wizard create an external template file. You can edit the template file outside of the IDE and test it without recompiling the application.

The following topics explain how to use the WebSnap components to create a Web server application:

Creating Web server applications with WebSnap

Web modules

Adapters

Page producers

Server-side scripting in WebSnap

Dispatching requests

WebSnapTutorial


Creating Web server applications with WebSnap
 DevGuide: Developing Internet applications

Creating Web server applications with WebSnap

Topic groups	See also

To create a new Web server application using the WebSnap architecture:

1	Select File|New|Other.

2	In the New Items dialog box, select the WebSnap tab and choose WebSnap Application.

3	A dialog box appears which requires the following information:

Server type

Web application module types

Web application module options

Application components


Server type
 DevGuide: Developing Internet applications

Server type

Topic groups	See also

Select one of the following types of Web server application, depending on your application’s type of Web server:

ISAPI and NSAPI: Selecting this type of application sets up your project as a DLL with the exported methods expected by the Web server. It adds the library header to the project file, and adds the required entries to the uses list and to the exports clause of the project file.

Apache: Selecting this type of application sets up your project as a DLL with the exported methods expected by the Apache Web server. It adds the library header to the project file and the required entries to the uses list and exports clause of the project file.

CGI stand-alone: Selecting this type of application sets up your project as a console application, and adds the required entries to the uses clause of the project file.

Win-CGI stand-alone: Selecting this type of application sets up your project as a Windows application and adds the required entries to the uses clause of the project file.

Web Application Debugger executable: Selecting this type of application sets up an environment for developing and testing Web server applications. This type of application is not intended for deployment.

Choose the type of Web server application that communicates with the type of Web server your application will use.


Web application module types
 DevGuide: Developing Internet applications

Web application module types

Topic groups	See also

The Web application module provides centralized control for business rules and non-visual components in the Web application. There are two types of Web application modules:

Page Module: Selecting this type of module creates a content page. The page module contains a page producer which is responsible for generating the content of a page. The page producer displays its associated page when the HTTP request pathinfo matches the page name. The page can act as the default page when the pathinfo is blank.

Data Module: Selecting this type of module does not create a content page. This module is used as a container for components shared by other modules—for example, database components used by two Web Page modules.


Web application module options
 DevGuide: Developing Internet applications

Web application module options

Topic groups	See also

If the selected application module type is page module, you can associate a name with the page by entering a name in the Page Name field in the dialog box. At runtime, the instance of this module can be either kept in cache, or removed from memory when the request has been serviced. Select either of the options from the Caching field. You can select more page module options through the Page Options button. You can set the following categories:

Producer: The producer type for the page can be set to one of AdapterPageProducer, DataSetPageProducer, InetXPageProducer, PageProducer, or XSLPageProducer. If the selected page producer supports scripting, then use the Script Engine drop-down list to select the language used to script the page.

Note:	The AdapterPageProducer supports only JScript.

HTML: When the selected producer uses an HTML template this group will be visible.

XSL: When the selected producer uses an XSL template, such as TXSLPageProducer, this group will be visible.

New File: Check New File if you want a template file to be created and managed as part of the unit. A managed template file will appear in the project manager and have the same file name and location as the unit source file. Uncheck New File if you want to use the properties of the producer component (typically the HTMLDoc or HTMLFile property).

Template: When New File is checked, choose the default content for the template file from the Template drop-down. The “Default” template displays the title of the application, the title of the page, and hyperlinks to published pages.

Page: Enter a page name and title for the page module. The page name is used to reference the page in an HTTP request or within the application's logic, whereas the title is the name that the end user will see when the page is displayed in a browser.

Published: Check Published to allow the page to automatically respond to HTTP requests where the page name matches the pathinfo in the request message.

Login Required: Check Login Required to require the user to log on before the page can be accessed.


Application components
 DevGuide: Developing Internet applications

Application components

Topic groups	See also

Application components provide the Web application’s functionality. For example, including an adapter dispatcher component automatically handles HTML form submissions and the return of dynamically generated images. Including a page dispatcher automatically displays the content of a page when the HTTP request pathinfo contains the name of the page.

Selecting the Components button displays a dialog box where you can select one or more of the Application components:

Application Adapter: Contains information about the application, such as the title. The default type is TApplicationAdapter.

End User Adapter: Contains information about the user, such as their name, access rights, and whether they are logged in. The default type is TEndUserAdapter. TEndUserSessionAdapter may also be selected.

Page Dispatcher: Examines the HTTP request’s pathinfo, and calls the appropriate page module to return the content of a page. The default type is TPageDispatcher.

Adapter Dispatcher: Automatically handles HTML form submissions, and requests for dynamic images, by calling adapter action and field components. The default type is TAdapterDispatcher.

Dispatch Actions: Allows you to define a collection of action items to handle requests based on pathinfo and method type. Action items call user-defined events, or request the content of page-producer components. The default type is TWebDispatcher.

Locate File Service: Provides control over the loading of template files, and script include files, when the Web application is running. The default type is TLocateFileService.

Sessions Service: Used to store information about an end-users that is needed for a short period of time. For example, you can use sessions to keep track of logged-in users, and to automatically log a user out after a period of inactivity. The default type is TSessionService.

User List Service: Keeps track of authorized users, and their passwords and access rights. The default type is TWebUserList.

For each of the above components, the component types listed are the default types shipped with the Delphi software product. Users can create their own component types or use third-party component types.

Next topic Web modules


Web modules
 DevGuide: Developing Internet applications

Web modules

Topic groups	See also

There are four Web module types:

TWebAppPageModule

TWebAppDataModule

TWebPageModule

TWebDataModule

The Web application module (TWebAppPageModule or TWebAppDataModule) is a container for the application components that perform functions for the application as a whole—such as dispatching requests, managing sessions, and maintaining user lists. Your project can contain only one of these types of application modules.

The Web page module (TWebPageModule) provides content to a page and the Web data module (TWebDataModule) acts as a container for components shared across your application. You can optionally include one or more Web page and Web data modules in the Web application module.

The following topics describe Web modules:

Web data modules

Web page modules

Web application modules


Web data modules
 DevGuide: Developing Internet applications

Web data modules

Topic groups	See also

Like standard data modules, a Web data module is a container for components from the palette. Data modules provide a design surface for adding, removing, and selecting components. When the application is running, a data module does not create a window.

The Web data module differs from a standard data module in the structure of the unit and the interfaces that the Web data module implements.

Use the Web data module as a container for components that are shared across your application. For example, you can put a dataset component in a data module and access the dataset from both:

a page module that displays a grid, and

a page module that displays an input form.

Structure of a Web data module unit

Standard data modules have a variable called the form variable, which is used to access the data module object. Web data modules replace this with a function. The purpose is the same. However, because WebSnap applications may be multi-threaded and may have multiple instances of a particular module that service multiple requests concurrently, this function is implemented to return the correct instance.

The unit also registers a factory. The factory specifies how the module should be managed by the WebSnap application. For example, flags indicate whether to cache the module and reuse it for other requests, or to destroy the module after a request has been serviced.

Interfaces implemented by a Web data module

A Web data module implements the following interfaces:

INotifyWebActivate: This interface is called when the module is activated to service a Web request, and before the module is deactivated after a Web request is serviced.

IWebVariablesContainer: This interface is called during script execution to resolve variable references. The adapteradapter dispatcher also calls this interface to locate adapter actions and fields that are referenced in an HTTP request.

IGetScriptObject: This interface is called to retrieve the module’s IDispatch implementation. The returned object is the interface between the module and the active scripting engine.

IIteratorObjectSupport: This interface is used to iterate through all of the objects within the module that can be accessed by active scripting.


Web page modules
 DevGuide: Developing Internet applications

Web page modules

Topic groups	See also

The page module has a page producer component associated with it. When a request is received, the page dispatcher analyses the request and calls the appropriate page module to process the request and return the content of the page.

Like Web data modules, Web page modules are containers for components. The difference between a Web data module and a Web page module is that a Web page module is used to produce a Web page.

Page producer component

Web page modules have a property that identifies the page producer component responsible for generating content for the page. The WebSnap wizards automatically adds a producer when creating a Web page module. You can change the page producer component later by dropping in a different producer from the WebSnap palette. However, if the page module has a template file, be sure that the content of this file is compatible with the producer component.

Page name

Web page modules have a page name that can be used to reference the page in an HTTP request or within the application's logic. A factory in the Web page module’s unit specifies the page name for the Web page module.

Producer template

Most page producers use a template. HTML templates typically contain some static HTML mixed in with transparent tags or server-side script. When page producers create their content, they replace the transparent tags with appropriate values and execute the server-side script to produce the HTML that is displayed by a client browser. The XSLPageProducer is an exception to this. It uses XSL templates, which contain XSL rather than HTML. The XSL templates do not support transparent tags or server-side script.

Web page modules may have an associated template file that is managed as part of the unit. A managed template file appears in the project manager and has the same base file name and location as the unit service file. If the Web page module does not have an associated template file then the properties of the page producer component specify the template.

Interfaces that the Web page module implements

A Web page module implements all of the interfaces of a Web data module, in addition to the following:

IDefaultPageFileName: The WebSnap surface designer uses this interface to ensure that a page module uses the proper template file.

ISetWebContentOptions: The WebSnap surface designer uses this interface to control the content that the page module generates. For example, an option can be used to retrieve the content before the Active Script executes.

IGetProducerComponent: The WebSnap surface designer uses this interface to retrieve the producer component associated with the page module.

IProducerEditorViewSupport: The WebSnap surface designer uses this interface to retrieve information about the editor views that it should display when the page module is active. The available editor views include HTML Script, Preview, HTML Result, XSL Tree, and XML Tree.

IPageResult: This interface provides access to the result that a page module produces. This interface supports three types of results: HTTP Content, HTTP Redirection, and Page Include.

IGetDefaultAction: This interface retrieves the default adapter action (if any) that is associated with the page module.


Web application modules
 DevGuide: Developing Internet applications

Web application modules

Topic groups	See also

The Web application module implements interfaces that are not implemented by TWebPageModule or TWebDataModule.

Interfaces implemented by a Web application data module

A Web application data module implements all the interfaces of a Web data module, in addition to the following:

IGetWebAppServices: Retrieves the interface to the application's Web request handler.

IGetWebAppComponents: Retrieves the interface to the application-level components, including the AdapterDispatcher, PageDispatcher, SessionsService, and EndUserAdapter.

Interfaces implemented by a Web application page module

A Web application page module implements all the interfaces of a Web Application data module and a Web page module.

Next topic Adapters


Adapters
 DevGuide: Developing Internet applications

Adapters

Topic groups	See also

Adapters provide a way to create an interface to the application data. They allow you to insert scripting languages into a page, and to retrieve information by making calls from your script code to the adapters.

For example, you can use an adapter to define data fields to be displayed on an HTML page. A scripted HTML page can then contain HTML content and script statements that retrieve the values of those data fields.

Fields

Fields are components that the page producer uses to retrieve data from your application and to display the content on a Web page. Fields can also be used to retrieve an image. In this case, the field returns the address of the image written to the Web page. When a page displays its content, a request sent to the Web application, invokes the adapter dispatcher to retrieve the actual image from the field component.

Actions

Actions are components that execute commands on behalf of the adapter. When a page producer generates its page, the scripting language calls adapter action components to return the name of the action along with any parameters necessary to execute the command. For example, consider clicking a button on an HTML form to delete a row from a table. This returns, in the HTTP request, the action name associated with the button and a parameter indicating the row number. The adapter dispatcher locates the named action component and passes the row number as a parameter to the action.

Errors

Adapters keep a list of errors that occur while executing an action. Page producers can access this list of errors and display them in the Web page that the application returns to the end user.

Records

Some adapter components, such as TDataSetAdapter, represent multiple rows. The adapter provides a scripting interface which allows iteration through the rows. Some adapters support paging, and iterate over only the rows on the current page.

Next topic Page producers


Page producers
 DevGuide: Developing Internet applications

Page producers

Topic groups	See also

You use page producers to generate content on behalf of a Web page module. You can also use producers in the same way as they are used in WebBroker applications, by associating the producer with a Web dispatcher action item. The advantages of using the Web page module are:

the ability to preview the page’s layout without running the application, and

the ability to associate a page name with the module, so that the page dispatcher can call the page producer automatically.

Templates

Producers provide the following functionality:

They generate HTML content.

They can reference an external file using the HTMLfile property, or the internal string using the HTMLDoc property.

When the producers are used in conjunction with a Web page module, the template can be a file associated with a unit.

Producers dynamically generate HTML which can be inserted into the template using transparent tags or active scripting. Transparent tags can be used in the same way as WebBroker applications. For more details, see Converting HTML-transparent tags. Active scripting support allows you to embed JavaScript or VBscript inside the HTML page.

Next topic Server-side scripting in WebSnap


Server-side scripting in WebSnap
 DevGuide: Developing Internet applications

Server-side scripting in WebSnap

Topic groups	See also

Page producer templates can include scripting languages such as JScript or VBScript. The page producer executes the script in response to a request for the producer's content. Because the Web application evalueates the script, it is called server-side script, as opposed to client-side script (which is evaluated by the browser).

Active scripting

WebSnap relies on active scripting to implement server-side script. Active scripting is a technology created by Microsoft to allow a scripting language to be used with application objects through COM interfaces. Microsoft ships two active scripting languages, VBScript and JScript. Support for other languages is available through third parties.

Script engine

The page producer’s ScriptEngine property identifies the active scripting engine that evaluates the script within a template.

Script blocks

Script blocks are delimited by <% and %>. The script engine evaluates any text inside script blocks. The result becomes part of the page producer's content. The page producer writes text outside of a script block after translating any embedded transparent tags. Script blocks can also enclose text, allowing conditional logic and loops to dictate the output of text. For example, the following JScript block generates a list of five numbered lines:

<ul>

<% for (i=0;i<5;i++) { %>

     <li>Item <% Response.Write(i) %></li>

<% } %>

</ul>

The following script block is equivalent:

<ul>

<% for (i=0;i<5;i++) { %>

     <li>Item <%=i %></li>

<% } %>

</ul>

The <%= delimiter is short for Response.Write.

Creating script

Developers can take advantage of WebSnap features to automatically generate script.

Wizard templates

When they create a new WebSnap application or page module, WebSnap wizards provide a template field that is used to select the initial content for the page module template. For example, the template called "Default" generates JScript to display the application title, page name, and links to published pages.

TAdapterPageProducer

The TAdapterPageProducer builds forms and tables by generating HTML and JScript. The generated JScript calls adapter objects to retrieve field values, field image parameters, and action parameters.

Editing and viewing script

The WebSnap surface designer provides a view of your Web Page modules which lets you preview a scripted page. Use the HTML Result tab to view the HTML resulting from the executed script. Use the Preview tab to view the result in a browser. The HTML Script tab is available when the Web Page module uses TAdapterPageProducer. The HTML Script tab displays the HTML and JScript generated by the TAdapterPageProducer object. Consult this view to see how to write script that builds HTML forms to display adapter fields and execute adapter actions.

Including script in a page

A template can include script from a file or from another page. To include script from a file, use the following code statement:

<!-- #include file="filename.html" -->

When the template includes script from another page, the script is evaluated by the including page, use the following code statement to include the unevaluated content of page1.

<!-- #include page="page1" -- >

Refer to Script objects for objects you can refer to in a script.


Script objects
 DevGuide: Developing Internet applications

Script objects

Topic groups	See also

Script objects are either VCL or CLX objects that can be referenced by script. You make VCL or CLX objects available for scripting by registering an IDispatch interface to the object with the active scripting engine. The following objects are available for scripting:

Application—The application object (which may be null) provides access to the application adapter of the Web Application module. The following JScript block writes the application title:

<%= Application.Title %>

EndUser—The EndUser object provides access to the end-user adapter of the Web Application module. The following JScript block writes the end-user name:

<%= EndUser.DisplayName %>

Session—The session object provides access to the session object of the Web Application module. The following JScript block writes the session ID:

<%= Session.SessionID %>

Pages—The pages object (Pages) provides access to the application pages. The following JScript block writes links to all published pages:

<%  e = new Enumerator(Pages)

     for (; !e.atEnd(); e.moveNext())

     {

       if (e.item().Published)

       {

           Response.Write('<A HREF="' + e.item().HREF +'">' + e.item().Title + '</A>')

       }

     }

%>

Note that the editor's Preview tab will not display the proper result of this script block. The pages object is always empty at design time because the Web page module factories have not been registered.

Modules—The modules object provides access to the application modules. The following JScript block writes the content of an adapter field in a module called DM.

<%= Modules.DM.Adapter1.Field1.DisplayText %>

Page—The Page object provides access to the current page. The following JScript block writes the title of the current page:

<%= Page.Title %>

Producer—The Producer object provides access to the page producer of the Web Page module. The following JScript block evaluates a transparent tag before writing the content:

<% Producer.Write('Here is a tag <#TAG>') %>

Note that the editor's Preview tab will probably not display the proper result of this script block. The event handlers that usually replace transparent tags do not execute unless the application is running.

Response—The Response object provides access to the WebResponse. Use this object when tag replacement is not desired.

<% Response.Write('Hello World!') %>

Request—The Request object provides access to the WebRequest. The following JScript block displays the pathinfo.

<%= Request.PathInfo %>

Adapter Objects—All of the adapter's components on the current page can be referenced without qualification. Adapter's in other modules must be qualified using the Modules objects. The following JScript block displays the text value of the FirstName field from of all rows of Adapter1:

<% e = new Enumerator(Adapter1.Records) %>

  <% for (; !e.atEnd(); e.moveNext()) %>

  <% { %>

      <p><%= Adapter1.FirstName.DisplayText %>

  <% } %>

Next topic Dispatching requests


Dispatching requests
 DevGuide: Developing Internet applications

Dispatching requests

Topic groups	See also

When the WebSnap application receives an HTTP request message, it creates a TWebRequest object to represent the HTTP request message, and a TWebResponse object to represent the response that should be returned.

WebContext

Before handling the request, the Web application module initializes the WebContext object (of type TWebContext). The WebContext is a thread variable that provides global access to variables used by components servicing the request. For example, the WebContext contains the TWebResponse and TWebRequest objects, as well as the adapter request and adapter response objects discussed

The following topics describe Web dispatching:

Dispatcher components

Adapter dispatcher operation

Dispatching action items

Page dispatcher operation


Dispatcher components
 DevGuide: Developing Internet applications

Dispatcher components

Topic groups	See also

The dispatcher components within the Web Application module control the flow of the application. The dispatchers determine how to handle certain types of HTTP request messages by examining the HTTP request.

The adapter dispatcher component (TAdapterDispatcher) looks for a content field, or a query field, that identifies an adapter action component or an adapter image field component. If the adapter dispatcher finds a component, it will pass control to that component.

The Web Dispatcher component (TWebDispatcher) maintains a collection of action items (TWebActionItem) that know how to handle certain types of HTTP request messages. The Web dispatcher looks for an action item that matches the request. If it finds one, it passes control to that action item. The Web dispatcher also looks for auto-dispatching components that can handle the request.

The page dispatcher component (TPageDispatcher) examines the pathInfo property of the TWebRequest object, looking for the name of a registered Web page module. If the dispatcher finds a Web page module name, it passes control to that Web page module.


Adapter dispatcher operation
 DevGuide: Developing Internet applications

Adapter dispatcher operation

Topic groups	See also

The adapter dispatcher component automatically handles HTML form submissions, and requests for dynamic images, by calling adapter action and field components.

Using adapter components to generate content

In order for WebSnap applications to automatically execute adapter actions and retrieve dynamic images from adapter fields, the HTML content must be properly constructed. If the HTML content is not properly constructed, then the resulting HTTP request will not contain the information that the adapter dispatcher needs to call adapter action and field components.

To reduce errors in constructing the HTML page, adapter components indicate what the names and values of HTML elements must be. Adapter components have methods that retrieve the names and values of hidden fields that must appear on an HTML form used to update adapter fields. Typically, page producers use server-side scripts to retrieve names and values from adapter components and generates HTML using these names and values. For example, the following script constructs an <IMG> element that references the field called Graphic from Adapter1:

<img src="<%=Adapter1.Graphic.Image.AsHREF%>" alt="<%=Adapter1.Graphic.DisplayText%>">

When the Web application evaluates the script, the HTML src attribute will contain the information necessary to identify the field and any parameters that the field component needs to retrieve the image. The resulting HTML might look like this:

<img src="?_lSpecies No=90090&__id=DM.Adapter1.Graphic" alt="(GRAPHIC)">

When the browser sends an HTTP request to retrieve this image to the Web application, the adapter dispatcher will be able to determine that the Graphic field of Adapter1, in the module DM, should be called with the parameter "Species No=90090". The adapter dispatcher will call the Graphic field to write an appropriate HTTP response.

The following script constructs an <A> element referencing the EditRow action of Adapter1 and the page called "Details":

<a href="<%=Adapter1.EditRow.LinkToPage("Details", Page.Name).AsHREF%>">Edit...</a>

The resulting HTML might look like this:

<a href="?&_lSpecies No=90310&__sp=Edit&__fp=Grid&__id=DM.Adapter1.EditRow">Edit...</a>

When the end-user clicks this hyperlink and the browser sends an HTTP request, the adapter dispatcher will be able to determine that the EditRow action of Adapter1, in the module DM, should be called with the parameter "Species No=903010". The adapter dispatcher will also indicate that the Edit page is to be displayed if the action executes successfully, and that the Grid page is to be displayed if action execution fails. It will then call the EditRow action to locate the row to be edited, and the page named Edit will be called to generate an HTTP response. The following figure shows how adapter components are used to generate content.

Generating content flow


Adapter requests and responses
 DevGuide: Developing Internet applications

Adapter requests and responses

Topic groups	See also

When the adapter dispatcher receives the client request, the adapter dispatcher creates adapter request and adapter response objects to hold information about the HTTP request. The adapter request and adapter response objects are stored in the WebContext to allow access during the processing of the request.

The adapter dispatcher creates two types of adapter request objects: action and image. It creates the action request object when executing an adapter action. It creates the image request object when retrieving an image from an adapter field.

The adapter response object is used by the adapter component to indicate the response to an adapter action or adapter image request. There are two types of adapter response objects, action and image.

Action request

The action request object is responsible for breaking the HTTP request down into information needed to execute an adapter action. The types of information needed for executing an adapter action may include:

Component Name—Identifies the adapter action component.

Adapter Mode—Adapters can define a mode. For example, TDataSetAdapter supports Edit, Insert, and Browse modes. An adapter action may execute differently depending on the mode. For example, the TDataSetAdapter Apply action adds a new record when in Insert mode, and updates a record when in Edit mode.

Success Page—The success page identifies the page displayed after successful execution of the action.

Failure Page—The failure page identifies the page displayed if an error occurs during execution of the action.

Action Request Parameters—This identifies the parameters need by the adapter action. For example, the TDataSetAdapter Apply action will include the key values identifying the record to be updated.

Adapter Field Values—These are the values for the adapter fields passed in the HTTP request when an HTML form is submitted. A field value can include new values entered by the end-user, the original values of the adapter field, and uploaded files.

Record Keys—If an HTML form submits changes to multiple records, keys used by the adapter action component are required to uniquely identify each record so that the adapter action can be performed on each record. For example, when the TDataSetAdapter Apply action is performed on multiple records, the record keys are used to locate each record in the dataset before updating the dataset fields.

Action response

The Action Response object generates an HTTP response on behalf of an adapter action component. The adapter action indicates the type of response by setting properties within the object, or by calling methods in the Action Response object. The properties include:

Redirect Options—The redirect options indicate whether to perform an HTTP redirect instead of returning HTML content.

Execution Status—Setting the status to success causes the default action response to be the content of the success page identified in the Action Request.

The Action response methods include:

RespondWithPag —The adapter action calls this method when a particular Web page module should generate the response.

RespondWithComponent—The adapter action calls this method when the response should come from the Web page module containing this component.

RespondWithURL—The adapter action calls this method when the response is a redirect to a specified URL.

When responding with a page, the Action response object attempts to use the page dispatcher to generate page content. If it does not find the page dispatcher, it calls the Web Page module directly.

The following figure illustrates how action request and action response objects handle a request.

Action request and response

Image request

The Image Request object is responsible for breaking the HTTP request down into the information required by the adapter image field to generate an image. The types of information represented by the Image Request include:

Component Name - Identifies the adapter field component.

Image Request Parameters - Identifies the parameters needed by the adapter image. For example, the TDataSetAdapterImageField object needs key values to identify the record that contains the image.

Image response

The Image response object contains the TWebResponse object. Adapter fields respond to an adapter request by writing an image to the Web response object.

The following figure illustrates how adapter image fields respond to a request.

Image response to a request


Dispatching action items
 DevGuide: Developing Internet applications

Dispatching action items

Topic groups	See also

The Web dispatcher ( TWebDispatcher) searches through its list of action items for one that:

matches the Pathinfo portion of the target URL’s request message, and

can provide the service specified as the method of the request message.

It accomplishes this by comparing the PathInfo and MethodType properties of the TWebRequest object with the properties of the same name on the action item.

When the dispatcher finds the appropriate action item, it causes that action item to fire. When the action item fires, it does one of the following:

Fills in the response content and sends the response, or signals that the request has been completely handled.

Adds to the response, and then allows other action items to complete the job.

Defers the request to other action items.

After the dispatcher has checked all of its action items, if the message has not been handled correctly, the dispatcher checks for specially registered auto-dispatching components that do not use action items. These components are specific to multi-tiered database applications. If the request message has still not been fully handled, the dispatcher calls the default action item. The default action item does not need to match either the target URL or the method of the request.


Page dispatcher operation
 DevGuide: Developing Internet applications

Adapter dispatcher operation

Topic groups	See also

When the page dispatcher recieves a client request, it determines the page name by checking the Pathinfo portion of the target URL’s request message. If the pathinfo portion is not blank, the page dispatcher uses the ending word of pathinfo as the page name. If the pathinfo portion is blank, the page dispatcher tries to determine a default page name.

If the page dispatcher’s DefaultPage property contains a page name, then the page dispatcher uses this name as the default page name. If the DefaultPage property is blank, and the Web application module is a page module, then the page dispatcher uses the name of the Web application module as the default page name.

If the page name is not blank, the page dispatcher searches for a Web page module with a matching name. If it finds a Web page module, then it calls that module to generated a response. If the page name is blank, or if the page dispatcher does not find a Web page module, the page dispatcher raises an exception.

The following figure shows how the page dispatcher responds to a request.

Dispatching a page


WebSnap tutorial
 DevGuide: Developing Internet applications

WebSnap tutorial

Topic groups	See also

The following topics describe how to build a WebSnap application. Completing the tutorial will familiarize you with the WebSnap architecture and new concepts, by incorporating the new dispatcher and adapter components into a Web Page module. The WebSnap application demonstrates how to use WebSnap HTML components to build an application that edits the content of a table.

The tutorial contains the following parts:

WebSnap Tutorial Part I: Create a new application

WebSnap Tutorial Part II: Create a CountryTable page

WebSnap Tutorial Part III: Add data components to the CountryTable module

WebSnap Tutorial Part IV: Create a grid to display the data

WebSnap Tutorial Part V: Add an edit form

WebSnap Tutorial Part VI: Add error reporting

WebSnap Tutorial Part VII: Run the completed application

Use the browse buttons (<< and >>) to move from topic to topic or select the jump at the end of each topic.


WebSnap Tutorial Part I: Create a new application
 DevGuide: Developing Internet applications

WebSnap Tutorial Part I: Create a new application

Topic groups	See also

To create a new WebSnap application:

Step 1. Start the WebSnap application wizard

1	Run the Delphi application and select File|New|Other.

2	In the New Items dialog box, select the WebSnap tab and choose WebSnap Application.

3	In the New WebSnap Application dialog box:

Select the Web App Debugger Executable.

In the CoClass Name edit control, type CountryTutorial.

Select Page Module as the component type.

In the Page Name field type Home.

4	Click OK.

Step 2. Save the generated files and project

To save the pascal unit file and project:

1	Select File|Save All.

2	In the File name field enter HomeU.pas and Click OK.

3	In the File name field enter CountryU.pas and Click OK.

4	In the File name field enter CountryTutorial.dpr and Click OK.

5	Click OK.

Note:	Save the unit and the project to the same directory since the application will look for the HomeU.html file in the same directory as the executable.

Step 3. Specify the application title

The application title is the name displayed to the end user. To specify the application title:

1	Select View|Project Manager.

2	In the Project Manager window expand CountryTutorial.exe and double click the HomeU entry.

3	In the Object Inspector window (bottom left), select ApplicationAdapter from the pull down list.

4	In the Properties tab, enter Country Tutorial in the ApplicationTitle field.

5	Click on the Preview tab in the editor window. The application title is displayed at the top of the page.

Next topic is WebSnap Tutorial Part II: Create a CountryTable page


WebSnap Tutorial Part II: Create a CountryTable page
 DevGuide: Developing Internet applications

WebSnap Tutorial Part II: Create a CountryTable page

Topic groups	See also

A Web page module is used to define a published page, and it also acts as a container for data components.

Step 1. Add a new module

To add a new module:

1	Select File|New|Other.

2	In the New Items dialog box, select the WebSnap tab and choose WebSnap Page Module.

3	In the dialog box, set the Producer Type to AdapterPageProducer from the list.

4	In the Page Name field enter CountryTable.

5	Leave the rest of the fields and selection at their default values.

6	Click OK.

Step 2. Save the new module

Save the unit to the directory of the project file. When the application runs, it searches for the CountryTableU.html file in the same directory as the executable.

1	Select File|Save.

2	In the File name field, enter CountryTableU.pas and Click OK.

Next topic is WebSnap Tutorial Part III: Add data components to the CountryTable module


WebSnap Tutorial Part III: Add data components to the CountryTable module
 DevGuide: Developing Internet applications

WebSnap Tutorial Part III: Add data components to the CountryTable module

Topic groups	See also

A TTable component provides the data for the HTML table. The TDataSetAdapter component allows server side script to access the TTable component.

Step 1. Add data-aware components

1	Select View|Project Manager.

2	In the Project Manager window expand CountryTutorial.exe and double click the CountryTableU entry.

3	Select View|Object TreeView. The Object TreeView window (left side) becomes active.

4	Select the BDE in the Component palette.

5	Select a Table component and add it to the CountryTable Web module.

6	Select a Session component and add it to the CountryTable Web module.

7	Select the Session component in the Object TreeView window. This displays the Session component values in the Object Inspector window.

8	In the Object Inspector window, set the AutoSessionName property to True.

9	Select the Table component in the Object TreeView window. This displays the Table component values in the Object Inspector window.

10	In the Object Inspector window, change the following properties:

Set the DatabaseName property to DBDEMOS .

In the Name property, type Country.

Set the TableName property to country.db.

Set the Active property to True.

Note:	The Session component is required because we are using the BDE component (TTable) in a multithreaded application.

Step 2. Specify a key field

The key field is used to identify records within a table. This becomes important when we add an edit page to the application. To specify a key field:

1	In the Object Tree View window, expand the Session and DBDemos node, and select the country.db node. This node is the Country Table component.

2	Right-click on the country.db node and select Fields Editor.

3	Right-click in the CountryTable.Country editor window and select the Add All Fields command.

4	Select the Name field from the list of added fields.

5	In the Object Inspector window, expand the ProviderFlags property.

6	Set the pfInKey property value to True.

Step 3. Add an adapter component

To expose the data in the TTable server-side scripting, you must include a DataSetAdapter (TDataSetAdapter) component. To add such a component:

1	Select the WebSnap tab in the tool palette.

2	Select the DataSetAdapter component and add it to the CountryTable Web module.

3	In the Object Inspector window, change the following properties:

Set the DataSet field to Country.

In the Name field type Adapter.

Next topic is WebSnap Tutorial Part IV: Create a grid to display the data


WebSnap Tutorial Part IV: Create a grid to display the data
 DevGuide: Developing Internet applications

WebSnap Tutorial Part IV: Create a grid to display the data

Topic groups	See also

The AdapterPageProducer leverages server-side script to quickly build an HTML table.

Step 1. Add a grid

To add a grid to display the data from the Country table:

1	Select View|Project Manager.

2	In the Project Manager window, expand CountryTutorial.exe and double-click the CountryTableU entry.

3	Select View|Object TreeView. The Object TreeView window (left-hand side) becomes active.

4	Expand the AdapterPageProducer component.

5	Right-click on WebPageItems entry and select New Component.

6	In the Add Web Component window, select AdapterForm, then Click OK. An AdapterForm1 component appears in the Object TreeView window.

7	Right-click on AdapterForm1 and select New Component.

8	In the Add Web Component window, select AdapterGrid then click OK. An AdapterGrid1 component appears in the Object TreeView window.

9	In the Object Inspector window, set the Adapter property to Adapter.

10	To preview the Page, select the CountryTableU.pas tab in the code editor window, and select the Preview tab at the bottom. If the Preview tab is not shown, use the right arrow at the bottom to scroll through the tabs.

11	Select the HTML Script tab to view the JScript generated by the WebSnap components.

Step 2. Add editing commands to the grid

Users may need to update the content of the table. To allow users to make such updates, such as deleting or inserting a row, add command components.

To add command components:

1	In the Object TreeView window for the CountryTable, expand the AdapterPageProducer component and all its branches.

2	Right-click on the AdapterGrid1 component and select Add All Columns.

3	Right-click on the AdapterGrid1 component and select New Component.

4	Select AdapterCommandColumn1 and then click OK. An AdapterCommandColumn1 entry is added to the AdapterGrid1 component.

5	Right-click on AdapterCommandColumn1 and choose Add Commands.

6	Multi-select the DeleteRow, EditRow, and NewRow commands; then click OK.

7	To preview the Page, click on the Preview tab at the bottom of the code editor.

Next topic is WebSnap Tutorial Part V: Add an edit form


WebSnap Tutorial Part V: Add an edit form
 DevGuide: Developing Internet applications

WebSnap Tutorial Part V: Add an edit form

Topic groups	See also

Create a Web page module to be the Edit form for the country table.

Step 1. Add a new module

To add a new WebSnap page module:

1	Select File|New|Other.

2	In the New Items dialog box, select the WebSnap tab and choose WebSnap Page Module.

3	In the dialog box, set the Producer Type to AdapterPageProducer from the list.

4	In the Page Name field, enter CountryForm.

5	Uncheck the Published box.

6	Leave the rest of the fields and selections at their default values.

7	Click OK.

Step 2. Save the new module

Save the unit to the directory as the project file. When the application runs, it will look for the CountryFormU.html file in the same directory as the executable.

1	Select File|Save.

2	In the File name field enter CountryFormU.pas and Click OK.

Step 3. Use the CountryTableU unit

Add CountryTableU unit to the uses clause to allow the module access to the Adapter component.

1	Select File|Use Unit.

2	Select CountryTableU from the list then click OK.

Step 4. Add input fields

Add components to the AdapterPageProducer component to generate data entry fields in the HTML form.

To add input fields:

1	Select View|Project Manager.

2	In the Project Manager window, expand CountryTutorial.exe and double-click the CountryFormU entry.

3	Select View|Object TreeView. The Object TreeView window (left-hand side) becomes active.

4	In the Object TreeView window, expand the AdapterPageProducer component, right-click on WebPageItems, and select New Component.

5	Select AdapterForm, then click OK. An AdapterForm1 entry appears in the Object TreeView window.

6	Right-click on AdapterForm1 and select New Component.

7	Select AdapterFieldGroup then click OK. An AdapterFieldGroup1 entry appears in the Object TreeView window.

8	In the Object Inspector window, set the Adapter property to CountryTable.Adapter.

9	To preview the Page, click the Preview tab at the bottom of the code editor.

Step 5. Add buttons

Add components to the AdapterPageProducer component to generate the submit buttons in the HTML form. To add components:

1	In the Object TreeView, expand the AdapterPageProducer component and all its branches.

2	Right-click on AdapterForm1 entry and select New Component.

3	Select AdapterCommandGroup then click OK. An AdapterCommandGroup1 entry appears in the Object TreeView window.

4	In the Object Inspector window, set the DisplayComponent property to AdapterFieldGroup1.

5	Right-click on AdapterCommandGroup1 entry and select Add Commands.

6	Multi-select the Cancel, Apply, and Refresh Row commands; then click OK.

7	To preview the Page, click the Preview tab at the bottom of the code editor window. If the preview does not show the country form, click on the Code tab and then re-click the Preview tab.

Step 6. Link form actions to the grid page

When the user clicks a button, an adapter action is executed. To specify which page to display after an adapter action is executed:

1	In the Object TreeView, expand AdapterCommandGroup1 to show the CmdCancel, CmdApply, and CmdRefreshRow entries.

2	Select CmdCancel. In the Object Inspector window, type CountryTable in the PageName property.

3	Select CmdApply. In the Object Inspector window, type CountryTable in the PageName property.

Step 7. Link grid actions to the form page

To specify which page to display after an adapter action is executed by pushing a button in the grid:

1	Select View|Project Manager.

2	In the Project Manager window, expand CountryTutorial.exe and double-click the CountryTableU entry.

3	In the Object TreeView window, expand the AdapterPageProducer component and all its branches, to show the CmdNewRow, CmdEditRow, and CmdDeleteRow entries. These entries appear under the AdapterCommandColumn1 entry.

4	Select CmdNewRow. In the Object Inspector window, type CountryForm in the PageName property.

5	Select CmdEditRow. In the Object Inspector window, type CountryForm in the PageName property.

6	To verify that the application is working and that all buttons perform some action, run the application. When you run the application, you are running a server. To check that the application is working, you must view it in a Web Browser. You can do this by launching it from the Web Application debugger. For information on how to do this, see Run the completed application.

Note:	There will be no indication of database errors, such as an invalid type. For example, try adding a new country with an invalid value (for example, 'abc') in the Area field.

Next topic is WebSnap Tutorial Part VI: Add error reporting


WebSnap Tutorial Part VI: Add error reporting
 DevGuide: Developing Internet applications

WebSnap Tutorial Part VI: Add error reporting

Topic groups	See also

To report errors to the end user, an AdapterErrorList component is used to display errors that occur while executing adapter actions that edit the country table.

Step 1. Add error support to the grid

1	In the Object TreeView for CountryTable, expand the AdapterPageProducer component and all its branches to show AdapterForm1.

2	Right-click on AdapterForm1 and select New Component.

3	Select AdapterErrorList from the list, then click OK. An AdapterErrorList1 entry appears in the Object TreeView window.

4	Move AdapterErrorList1 above AdapterGrid1 (either by dragging it or by using the upward-pointing arrow in the Object TreeView toolbar).

5	In the Object Inspector window, set the Adapter property to Adapter.

Step 2. Add error support to the form

1	In the Object TreeView for CountryForm, expand the AdapterPageProducer component and all its branches to show AdapterForm1.

2	Right-click on AdapterForm1 and select New Component.

3	Select AdapterErrorList from the list, then click OK. An AdapterErrorList1 entry appears in the Object TreeView window.

4	Move AdapterErrorList1 above AdapterFieldGroup1 (either by dragging it or by using the upward-pointing arrow in the Object TreeView toolbar).

5	In the Object Inspector window, set the Adapter property to CountryTable.Adapter.

Step 3. Test the error-reporting mechanism

To test for grid errors:

1	Run the application, and browse to the CountryTable page using the Web Application debugger. For information on how to do this, see Run the completed application.

2	Start up another instance of your browser and browse to the CountryTable page.

3	Click the DeleteRow button on the first row in the grid.

4	Without refreshing the second browser, click the DeleteRow button on the first row in the grid.

5	An error message will be displayed above the grid.

To test for form errors:

1	Run the application, and browse to the CountryTable page using the Web Application debugger.

2	Click on the EditRow Button.

3	The CountryForm page is displayed.

4	Change the area field to 'abc', and click the Apply Button.

5	An error message will be displayed above the first field.

Next topic is WebSnap Tutorial Part VII: Run the completed application


WebSnap Tutorial Part VII: Run the completed application
 DevGuide: Developing Internet applications

WebSnap Tutorial Part VII: Run the completed application

Topic groups	See also

To run the completed application:

1	Select Run|Run. A form is displayed. Web App Debugger executable Web applications are COM servers, and the form you see is the console window for the COM server. The first time you run the project, it registers the COM object that the Web App Debugger can access directly.

2	Select Tools|Web App Debugger.

3	Click on the default URL link to display the ServerInfo page. The ServerInfo page displays the names of all registered Web Application Debugger executables.

4	Select CountryTutorial in the drop-down list and click on the Go button.


Working with XML documents
 DevGuide: Developing Internet applications

Working with XML documents

Topic groups	See also

XML (Extensible Markup Language) is a markup language for describing structured data. It is similar to HTML, except that the tags describe the structure of information rather than its display characteristics. XML documents provide a simple, text-based way to store information so that it is easily searched or edited. They are often used as a standard, transportable format for data in Web applications, business-to-business communication, and so on.

XML documents provide a hierarchical view of a body of data. Tags in the XML document describe the role or meaning of each data element, as illustrated in the following document, which describes a collection of stock holdings:

<?xml version="1.0" standalone='yes' ?>

<!DOCTYPE stockholdings SYSTEM "sth.dtd">

<StockList>

   <Stock exchange=NASDAQ>

      <name>Inprise (Borland)</name>

      <price>15.375</price>

      <symbol>INPR</symbol>

      <shares>100</shares>

   </Stock>

   <Stock exchange=NYSE>

      <name>Pfizer</name>

      <price>42.75</price>

      <symbol>PFE</symbol>

      <shares type=preferred>25</shares>

   </Stock>

</StockList>

This example illustrates a number of typical elements in an XML document. The first line is a processing instruction. It provides information on how to interpret the file, but does not include any data.

The second line, which begins with the <!DOCType> tag, is a document type declaration. It names the structure of the document and references another file (sth.dtd) that describes that structure. In this case, the structure is described by a Document Type Definition (DTD) file. Other types of files that describe the structure of an XML document include Reduced XML Data (XDR) and XML schemas (XSD).

The remaining lines are organized into a hierarchy with a single root node (the <StockList> tag). Each node in this hierarchy contains either a set of child nodes, or a text value. Some of the tags (the <Stock> and <shares> tags) include attributes, which are Name=Value pairs that provide details on how to interpret the tag.

Although it is possible to work directly with the text in an XML document, typically applications use some sort of additional tools for parsing and editing the data. W3C defines a set of standard interfaces for representing a parsed XML document called the Document Object Model (DOM). A number of vendors provide XML parsers that implement the DOM interfaces to let you interpret and edit XML documents more easily.

Delphi provides a number of additional tools for working with XML documents. These tools use a DOM parser that is provided by another vendor, and make it even easier to work with XML documents.They include

VCL components and interfaces for working with XML documents.

An XML Data Binding wizard for generating classes to represent a particular XML document.

Tools and components for converting between XML documents and data packets, which let you integrate XML documents into database applications.


Using the Document Object Model
 DevGuide: Developing Internet applications

Using the Document Object Model

Topic groups	See also

The Document Object Model (DOM) is a set of standard interfaces for representing a parsed XML document. Delphi ships with two DOM implementations (from Microsoft and from IBM). In addition, it includes a registration mechanism that lets you integrate additional DOM implementations by other vendors into the Delphi XML framework.

The XMLDOM unit includes declarations for all the DOM interfaces defined in the W3C XML DOM level 2 specification. Each DOM vendor provides an implementation for these interfaces.

To use the Microsoft implementation, include the MSXMLDOM unit in your uses clause. Because the Microsoft implementation is COM-based, you must also register the msxml.dll library as a COM server. You can use Regsvr32.exe to register this DLL.

To use the IBM implementation, include the IBMXMLDOM unit in your uses clause.

To use another DOM implementation, you must create a unit that includes a function to return the top-level interface (IDOMImplementation). Your unit should register this function by calling the global RegisterDOMImplementation procedure.

Some vendors supply extensions to the standard DOM interfaces. To allow you to uses these extensions, the XMLDOM unit also defines an IDOMNodeEx interface. IDOMNodeEx is a descendant of the standard IDOMNode that includes the most useful of these extensions.

You can work directly with the DOM interfaces to parse and edit XML documents. Simply call the GetDOM function to obtain an IDOMImplementation interface, which you can use as a starting point.

Note:	For detailed descriptions of the DOM interfaces, see the declarations in the XMLDOM unit, the documentation supplied by your DOM Vendor, or the specifications provided on the W3C web site (www.w3.org).

You may find it more convenient to use Delphi’s XML classes rather than working directly with the DOM interfaces. These are described in:

Working with XML components

Abstracting XML documents with the Data Binding wizard


Working with XML components
 DevGuide: Developing Internet applications

Working with XML components

Topic groups	See also

Delphi defines a number of classes and interfaces for working with XML documents. These simplify the process of loading, editing, and saving XML documents.

To use the XML classes for examining or editing an XML document you start by setting up an instance of TXMLDocument. You can then work with the nodes of the XML document component to examine or edit the body of the XML document.


Using TXMLDocument
 DevGuide: Developing Internet applications

Using TXMLDocument

Topic groups	See also

The starting point for working with an XML document is the TXMLDocument component. The following steps describe how to use TXMLDocument to work directly with an XML document:

1	Add a TXMLDocument component into your form or data module. TXMLDocument appears on the Internet page of the Component palette.

2	Set the DOMVendor property to specify the DOM implementation you want the component to use for parsing and editing an XML document. The Object Inspector lists all the currently registered DOM vendors. For information on DOM implementations, see Using the Document Object Model.

3	Depending on your implementation, you may want to set the ParseOptions property to configure how the underlying DOM implementation parses the XML document.

4	If you are working with an existing XML document, specify the document:

If the XML document is stored in a file, set the FileName property to the name of that file.

You can specify the XML document as a string instead by using the XML property.

5	Set the Active property to True.

Once you have an active TXMLDocument object, you can traverse the hierarchy of its nodes, reading or setting their values. The root node of this hierarchy is available as the DocumentElement property.

For information on working with the nodes of the XML document, see Working with XML nodes.


Working with XML nodes
 DevGuide: Developing Internet applications

Working with XML nodes

Topic groups	See also

Once an XML document has been parsed by a DOM implementation, the data it represents is available as a hierarchy of nodes. Each node corresponds to a tagged element in the document. For example, given the following XML:

Component palette<?xml version="1.0" standalone='yes' ?>

<!DOCTYPE stockholdings SYSTEM "sth.dtd">

<StockList>

   <Stock exchange=NASDAQ>

      <name>Inprise (Borland)</name>

      <price>15.375</price>

      <symbol>INPR</symbol>

      <shares>100</shares>

   </Stock>

   <Stock exchange=NYSE>

      <name>Pfizer</name>

      <price>42.75</price>

      <symbol>PFE</symbol>

      <shares type=preferred>25</shares>

   </Stock>

</StockList>

TXMLDocument would generate a hierarchy of nodes as follows: The root of the hierarchy would be the StockList node. StockList would have two child nodes, which correspond to the two Stock tags. Each of these two child nodes would have four child nodes of its own (name, price, symbol, and shares). Those four child nodes would act as leaf nodes. The text they contain would appear as the value of each of the leaf nodes.

Note:	This division into nodes differs slightly from the way a DOM implementation generates nodes for an XML document. In particular, a DOM parser treats all tagged elements as internal nodes. Additional nodes (of type text node) would be created for the values of the name, price, symbol, and shares nodes. These text nodes would then appear as the children of the name, price, symbol, and shares nodes.

Each node is accessed through an IXMLNode interface, starting with the root node, which is the value of the XML document component’s DocumentElement property.

Working with a node’s value

Given an IXMLNode interface, you can check whether it represents an internal node or a leaf node by checking the IsTextElement property.

If it represents a leaf node, you can read or set its value using the Text property.

If it represents an internal node, you can access its child nodes using the ChildNodes property.

Thus, for example, using the XML document above, you can read the price of Inprise’s stock as follows:

InpriseStock := XMLDocument1.DocumentElement.ChildNodes[0];

Price := InpriseStock.ChildNodes['price'].Text;

Working with a node’s attributes

If the node includes any attributes, you can work with them using the Attributes property. You can read or change an attribute value by specifying an existing attribute name. You can add new attributes by specifying a new attribute name when you set the Attributes property:

InpriseStock := XMLDocument1.DocumentElement.ChildNodes[0];

InpriseStock.ChildNodes['shares'].Attributes['type'] := 'common';

Adding and deleting child nodes

You can add child nodes using the AddChild method. AddChild creates new nodes that correspond to tagged elements in the XML document. Such nodes are called element nodes.

To create a new element node, specify the name that appears in the new tag and, optionally, the position where the new node should appear. For example, the following code adds a new stock listing to the document above:

var

  NewStock: IXMLNode;

  ValueNode: IXMLNode;

begin

  NewStock := XMLDocument1.DocumentElement.AddChild('stock');

  NewStock.Attributes['exchange'] := 'NASDAQ';

  ValueNode := NewStock.AddChild('name');

  ValueNode.Text := 'Cisco Systems'

  ValueNode := NewStock.AddChild('price');

  ValueNode.Text := '62.375';

  ValueNode := NewStock.AddChild('symbol');

  ValueNode.Text := 'CSCO';

  ValueNode := NewStock.AddChild('shares');

  ValueNode.Text := '25';

end;

An overloaded version of AddChild lets you specify the namespace in which the tag name is defined.

You can delete child nodes using the methods of the ChildNodes property. ChildNodes is an IXMLNodeList interface, which manages the children of a node. You can use its ~JMP Delete~!Alink(ixmlnodelist_delete,1,TopicNotFound,main) JMP~> method to delete a single child node that is identified by position or by name. For example, the following code deletes the last stock listed in the document above:

StockList := XMLDocument1.DocumentElement;

StockList.ChildNodes.Delete(StockList.ChildNodes.Count - 1);


Abstracting XML documents with the Data Binding wizard
 DevGuide: Developing Internet applications

Abstracting XML documents with the Data Binding wizard

Topic groups	See also

Although it is possible to work with an XML document using only the TXMLDocument component and the IXMLNode interface it surfaces for the nodes in that document, or even to work exclusively with the DOM interfaces (avoiding even TXMLDocument), you can write code that is much simpler and more readable by using the XML Data Binding wizard.

The Data Binding wizard takes an XML schema or data file and generates a set of interfaces that map on top of it. For example, given XML data that looks like the following:

<customer id=1>

  <name>Mark</name>

  <phone>(831) 431-1000</phone>

</customer>

The Data Binding wizard generates the following interface (along with a class to implement it):

ICustomer = interface(IXMLNode)

  property id: Integer read Getid write Setid;

  property name: DOMString read Getname write Setname;

  property phone: DOMString read Getphone write Setphone;

  function Getid: Integer;

  function Getname: DOMString;

  function Getphone: DOMString;

  procedure Setid(Value: Integer);

  procedure Setname(Value: DOMString);

  procedure Setphone(Value: DOMString);

end;

Every child node is mapped to a property whose name matches the tag name of the child node and whose value is the interface of the child node (if the child is an internal node) or the value of the child node (for leaf nodes). Every node attribute is also mapped to a property, where the property name is the attribute name and the property value is the attribute value.

In addition to creating interfaces (and implementation classes) for each tagged element in the XML document, the wizard creates a global function for obtaining the interface to the root node. For example, if the XML above came from a document whose root node had the tag <Customers>, the Data Binding wizard would create the following global routine:

function GetCustomers(XMLDoc: TXMLDocument): ICustomers;

Using the generated interfaces simplifies your code, because they reflect the structure of the XML document more directly. For example, instead of writing code such as the following:

CustName := XMLDocument1.DocumentElement.ChildNodes[0].ChildNodes['name'].Value;

Your code would look as follows:

CustName := GetCustomers(XMLDocument1)[0].Name;

Note that the interfaces generated by the Data Binding wizard all descend from IXMLNode. This means you can still add and delete child nodes in the same way as when you do not use the Data Binding wizard. (See Adding and deleting child nodes.) In addition, when child nodes represent repeating elements (when all of the children of a node are of the same type), the parent node is given two methods, Add, and Insert, for adding additional repeats. These methods are simpler than using AddChild, because you do not need to specify the type of node to create.

The following topics provide detailed information on using the XML Data Binding wizard:

Using the XML Data Binding wizard

Using Code that the XML Data Binding wizard generates


Using the XML Data Binding wizard
 DevGuide: Developing Internet applications

Using the XML Data Binding wizard

Topic groups	See also

To use the Data Binding wizard,

1	Choose File|New|Other and select the icon labeled XML Data Binding from the bottom of the New page.

2	The XML Data Binding wizard appears.

3	On the first page of the wizard

specify the XML document or schema for which you want to generate interfaces. This can be a sample XML document, a Document Type Definition (.dtd) file, a Reduced XML Data (.xdr) file, or an XML schema (.xsd) file.

4	Click the Options button to specify the naming strategies you want the wizard to use when generating interfaces and implementation classes and the default mapping of types defined in the schema to Pascal data types.

5	Move to the second page of the wizard. This page lets you provide detailed information about every node type in the document or schema. At the left is a tree view that shows all of the node types in the document. For complex nodes (nodes that have children), the tree view can be expanded to display the child elements. When you select a node in this tree view, the righthand side of the dialog displays information about that node and lets you specify how you want the wizard to treat that node.

The Source Name control displays the name of the node type in the XML schema.

The Source Type control displays the type of the node’s value, as specified in the XML schema.

The Documentation control lets you add comments to the schema describing the use or purpose of the node.

If the wizard generates code for the selected node (that is, if it is a complex type for which the wizard generates an interface and implementation class, or if it is one of the child elements of a complex type for which the wizard generates a property on the complex type’s interface), you can use the Generate Binding check box to specify whether you want the wizard to generate code for the node. If you uncheck Generate Binding, the wizard does not generate the interface or implementation class for a complex type, or does not create a property in the parent interface for a child element or attribute.

The Binding Options section lets you influence the code that the wizard generates for the selected element. For any node, you can specify the Identifier Name (the name of the generated interface or property). In addition, for interfaces, you must indicate which one represents the root node of the document. For nodes that represent properties, you can specify the type of the property and, if the property is not an interface, whether it is a read-only property.

6	Once you have specified what code you want the wizard to generate for each node, move to the third page. This page lets you choose some global options about how the wizard generates its code and lets you preview the code that will be generated, and lets you tell the wizard how to save your choices for future use.

To preview the code the wizard generates, select an interface in the Binding Summary list and view the resulting interface definition in the Code Preview control.

Use the Data Binding Settings to indicate how the wizard should save your choices. You can store the settings as annotations in a schema file that is associated with the document (the schema file specified on the first page of the dialog), or you can name an independant schma file that is used only by the wizard.

7	When you click Finish, the Data Binding wizard generates a new unit that defines interfaces and implementation classes for all of the node types in your XML document. In addition, it creates a global function that takes a TXMLDocument object and returns the interface for the root node of the data hierarchy.


Using Code that the XML Data Binding wizard generates
 DevGuide: Developing Internet applications

Using Code that the XML Data Binding wizard generates

Topic groups	See also

Once the wizard has generated a set of interfaces and impelementation classes, you can use them to work with XML documents that match the structure of the document or schema you supplied to the wizard. Just as when you are using only the built-in XML components that ship with Delphi, your starting point is the TXMLDocument component that appears on the Internet page of the Component palette.

To work with an XML document, use the following steps:

1	Place a TXMLDocument component in your form or data module.

2	Bind the TXMLDocument to an XML document by setting the FileName property. (As an alternative approach, you can use a string of XML by setting the XML property at runtime.)

3	In your code, call the global function that the wizard created to obtain an interface for the root node of the XML document. For example, if the root element of the XML document was the tag <StockList>, by default, the wizard generates a function GetStockListType, which returns an IStockListType interface:

var

  StockList: IStockListType;

begin

  StockList := GetStockListType(XMLDocument1);

4	This interface has properties that correspond to the subnodes of the document’s root element, as well as properties that correspond to that root element’s attributes. You can use these to traverse the hierarchy of the XML document, modify the data in the document, and so on.

5	To save any changes you make using the interfaces generated by the wizard, call the TXMLDocument component’s SaveToFile method or read its XML property.


Using Web Services
 DevGuide: Developing Internet applications

Using Web Services

Topic groups	See also

Web Services are self-contained modular applications that can be published and invoked over a network (such as the World Wide Web). Web Services provide well-defined interfaces that describe the services provided.

Web Services are designed to allow a loose coupling between client and server. That is, server implementations do not require clients to use a specific platform or programming language. In addition to defining interfaces in a language-neutral fashion, they are designed to allow multiple communications mechanisms as well.

Delphi’s support for Web Services is designed to work using SOAP (Simple Object Access Protocol). SOAP is a standard lightweight protocol for exchanging information in a decentralized, distributed environment. It uses XML to encode remote procedure calls and typically uses HTTP as a communications protocol. For more information about SOAP, see the SOAP specification available at

http://www.w3.org/TR/SOAP/

Note:	Although Delphi’s support for Web Services is based on SOAP and HTTP, the framework is sufficiently general that it can be expanded to use other encoding and communications protocols.

Delphi’s SOAP-based technology is available on Windows and will later be implemented on Linux, so that it can form the basis of cross-platform distributed applications. There is no special client runtime software to install, as you must have when distributing applications using CORBA. Because this technology is based on HTTP messages, it has the advantage that it is widely available on a variety of machines. Support for Web Services is built on top of Delphi’s cross-platform Web server application architecture.

You can use Delphi to build both servers that implement Web Services and clients that call on those services. If you use Delphi to create both the server and client applications, you can share a single unit that defines the interfaces for the Web Services. In addition, you can write Delphi clients for arbitrary servers that implement Web Services that respond to SOAP messages, and Delphi servers that publish Web Services that can be used by arbitrary clients.

When either the client or server is not written using Delphi, you can publish or import information on what interfaces are available and how to call them using a WSDL (Web Service Definition Language) document. On the server side, your application can publish a WSDL document that describes your Web Service. On the client side, a wizard can import a published WSDL document, providing you with the interface definitions and connection information you need.

The following topics describe Delphi’s support for working with Web Services in greater detail:

Writing Servers that support Web Services

Writing clients for Web Services


Writing Servers that support Web Services
 DevGuide: Developing Internet applications

Writing Servers that support Web Services

Topic groups	See also

In Delphi, servers that support Web Services are built using invokable interfaces. Invokable interfaces are interfaces that are compiled to include runtime type information (RTTI). This RTTI is used when interpreting incoming method calls from clients so that they can be correctly marshaled.

In addition to the invokable interfaces, and the classes that implement them, your server requires two components: a dispatcher and an invoker. The dispatcher (THTTPSoapDispatcher) is an auto-dispatching component that receives incoming SOAP messages and passes them on to the invoker. The invoker (THTTPSoapPascalInvoker) interprets the SOAP message, identifies the invokable interface it calls, executes the call and assembles the response message.

Note:	THTTPSoapDispatcher and THTTPSoapPascalInvoker are designed to respond to HTTP messages containing a SOAP request. The underlying architecture is sufficiently general, however, that it can support other protocols with the substitution of different dispatcher and invoker components.

Once you register your invokable interfaces and their implementation classes, the dispatcher and invoker automatically handle any messages that identify those interfaces in the SOAP Action header of the HTTP request message.

Building a Web Service server

Use the following steps to build a server application that implements a Web Service:

1	Define the interfaces that make up your Web Service. These interface definitions must be invokable interfaces. It is a good idea to create your interface definitions in their own units, separate from the unit that contains the implementation classes. In this way, the unit that defines the interfaces can be included in both the server and client applications. In the initialization section of this unit, add code to register the interfaces.

2	If your interface uses any complex (non-scalar) types, you must make sure these can be marshalled correctly. The Web Service application can only handle these using special objects that contain runtime type information (RTTI) that describes their structure. For details on creating and registering objects to represent complex types, see Using complex types in invokable interfaces.

3	Define and implement classes that implement the invokable interfaces you defined in step 1. For each implementation class, you may also need to create a factory procedure that instantiates the class. In the initialization section of this unit, add code to register the implementation class. This process is described in Creating and registering the implementation.

4	If your application raises an exception when attempting to execute a SOAP request, the exception will be automatically encoded in a SOAP fault packet, which is returned instead of the results of the method call. If you want to convey more information than a simple error message, you can create your own exception classes that are encoded and passed to the client. This is described in Creating custom exception classes for Web Services.

5	Choose File|New|Other, and on the WebServices page, double-click the Soap Server application icon. Choose the type of Web server application you want to have implement your Web Service. For information about different types of Web Server applications, see Types of Web server applications.

6	The wizard generates a new Web Service application that includes three components:

An invoker component (THTTPSOAPPascalInvoker). The invoker converts between SOAP messages and the methods of any interfaces you registered in step 1.

A dispatcher component (THTTPSoapDispatcher). The dispatcher automatically responds to incoming SOAP messages and forwards them to the invoker. You can use its WebDispatch property to identify the HTTP request messages to which your application responds. This involves setting the PathInfo property to indicate the path portion of any URL directed to your application, and the MethodType property to indicate the method header for request messages.

A WSDL publisher (TWSDLHTMLPublisher). The WSDL publisher publishes a WSDL document that describes your interfaces and how to call them. It enables clients that are not written using Delphi to call on your Web Service application. For details on using the WSDL publisher, see Generating WSDL documents for a Web Service application

7	Choose Project|Add To Project, and add the units you created in steps 1 through 4 to your Web server application.


Defining invokable interfaces
 DevGuide: Developing Internet applications

Defining invokable interfaces

Topic groups	See also

To create an invokable interface, you need only compile an interface with the {$M+} compiler option. The descendant of any invokable interface is also invokable. However, if an invokable interface descends from another interface that is not invokable, clients of your Web Service server can only call the methods defined in the invokable interface and its descendants. Methods inherited from the non-invokable ancestors are not compiled with type information and so can’t be called by clients.

Delphi defines a base invokable interface, IInvokable, that can be used as the basis of any interface exposed to clients by a Web Service server. IInvokable is the same as the base interface (IInterface), except that it is compiled using the {$M+} compiler option so that it and all its descendants are compiled to include RTTI.

For example, the following code defines an invokable interface that contains two methods for encoding and decoding numeric values:

IEncodeDecode = interface(IInvokable)

  ['{C527B88F-3F8E-1134-80e0-01A04F57B270}']

    function EncodeValue(Value: Integer): Double; stdcall;

    function DecodeValue(Value: Double): Integer; stdcall;

end;

Before a Web Service application can use this invokable interface, it must be registered with the invocation registry. On the server, the invocation registry entry allows the invoker component (THTTPSOAPPascalInvoker) to identify an implementation class to use for executing interface calls. On client applications, an invocation registry entry allows components to look up information that identifies the invokable interface and supplies information on how to call it.

In the initialization section of the unit that defines the interface, add code to register the interface with the invocation registry. To access the invocation registry, add the InvokeRegistry unit to the uses clause of your unit. The InvokeRegistry unit declares a global function, InvRegistry, which returns a catalog of all registered invokable interfaces, their implementation classes, and the factories that create instances of the implementation classes.

When you are finished, the unit that defines the interface should look something like the following:

unit EncodeDecode;

interface

type

IEncodeDecode = interface(IInvokable)

  ['{C527B88F-3F8E-1134-80e0-01A04F57B270}']

    function EncodeValue(Value: Integer): Double; stdcall;

    function DecodeValue(Value: Double): Integer; stdcall;

end;

implementation

uses  InvokeRegistry;

initialization

InvRegistry.RegisterInterface(TypeInfo(IEncodeDecode));

end.

Because the interfaces of Web Services must have a namespace to identify them among all the interfaces in all possible Web Services, when you register an interface the invocation registry automatically generates a namespace for the interface. The default namespace is built from a string that uniquely identifies the application (the AppNamespacePrefix variable), the interface name, and the name of the unit in which it is defined.

Tip:	It is a good idea to keep the unit that defines your invokable interfaces separate from the unit in which you write the classes that implement them. This unit can then be included in both the client and the server application. Because the generated namespace includes the name of the unit in which the interface is defined, sharing the same unit in both client and server applications enables them to automatically use the same namespace.


Using complex types in invokable interfaces
 DevGuide: Developing Internet applications

Using complex types in invokable interfaces

Topic groups	See also

The invoker component (THTTPSOAPPascalInvoker) automatically knows how to marshal scalar types on invokable interfaces. It can also handle dynamic arrays, as long as they are registered with the remotable type registry (see below). However, you can’t transmit data in more complex types such as static arrays, interfaces, records, sets, or classes. Instead, you must map these complex types to a class that includes runtime type information (RTTI), which the invoker can use to convert between data in the SOAP stream and type values. The invokable interface then uses that class rather than a static array, record, set, or non-remotable class.

Use TRemotable as a base class when defining a class to represent a complex data type on an invokable interface. For example, in the case where you would ordinarily pass a record as a parameter, you would instead define a TRemotable descendant where every member of the record is a published property on your new class.

If the value of your new TRemotable descendant represents to a scalar type in a WSDL document that does not correspond to an Object Pascal scalar type, you should use TRemotableXS as a base class instead. TRemotableXS is a TRemotable descendant that introduces two methods for converting between your new class and its string representation. Provide these methods by overriding the XSToNative and NativeToXS methods.

In the initialization section of the unit that defines the TRemotable descendant, you must register this class with the remotable type registry. Access the remotable type registry by adding the InvokeRegistry unit to the uses clause. This unit declares two global functions, RemClassRegistry and RemTypeRegistry, which return the remotable type registry. You can use either function to obtain an object for registering your remotable class (they refer to the same registry.) For example, the following line comes from the XSBuiltIns unit. It registers TXSDateTime, a TRemotable descendant that represents TDateTime values:

RemClassRegistry.RegisterXSClass(TXSDateTime, XMLSchemaNameSpace, 'dateTime', True);

The first parameter is the name of the TRemotable descendant. The second is a uniform resource identifier (URI) that uniquely identifies the namespace of the new class. If you supply an empty string, the registry can generate a URI for you. The third parameter is the name of the data type your class represents. If you supply an empty string, the registry simply uses the class name. The last parameter indicates whether the value of class instances can be transmitted as a string (whether you implemented the XSToNative and NativeToXS methods).

Tip:	It is a good idea to implement and register TRemotable descendants in a separate unit from the rest of your server application, including from the units that declare and register invokable interfaces. In this way, you can use the unit that defines your type in both the client and server, and you can use the type for more than one interface.

If you are using dynamic arrays, enumerated types, or boolean types for parameters, you do not need to create a remotable class to represent them, but you do have to register them with the remotable type registry. Thus, for example, if your interface uses a type such as the following:

type

  TDateTimeArray = array ofTXSDateTime;

You must add the following registration to the initialization section of the unit where you declare this dynamic array:

RemTypeRegistry.RegisterXSInfo(TypeInfo(TDateTimeArray), MyNameSpace, 'DTarray', False);

The parameters are the same as those used by RegisterXSClass, except for the first which takes a pointer to the type information of the dynamic array rather than a class reference.


Creating and registering the implementation
 DevGuide: Developing Internet applications

Creating and registering the implementation

Topic groups	See also

The simplest way to write an implementation for an invokable interface is to create a class that descends from TInvokableClass. Add the class declaration, including the invokable interfaces you are supporting, and then type Ctrl+Shift+C to invoke class completion. The interface members appear in your class declaration, and empty methods appear in the implementation section of the unit.

For example, the declaration for an implementation class implement the interface declared in Defining invokable interfaces might look like the following:

TEncodeDecode = class(TInvokableClass, IEncodeDecode)

protected

  function EncodeValue(Value: Integer): Double; stdcall;

  function DecodeValue(Value: Double): Integer; stdcall;

end;

In the implementation section of the unit that declares this class, fill in the EncodeValue and DecodeValue methods.

Once you have created an implementation class, you must register this class with the invocation registry. The invocation registry uses this to identify the class that implements a registered interface and to make it available to the invoker component when the invoker needs to call the interface. To register the implementation class, add a call the RegisterInvokableClass method of the object returned by the global InvRegistry function to the initialization section of your implementation unit:

InvRegistry.RegisterInvokableClass(TEncodeDecode);

You can also create implementation classes that do not descend from TInvokableClass. In this case, however, you must provide a factory procedure that the invocation registry can call to create instances of your class.

The factory procedure must be of type TCreateInstanceProc. It returns an instance of your implementation class. If the procedure creates a new instance, the object should free itself when the reference count on its interface drops to zero, as the invocation registry does not explicitly free object instances. As an alternative, the factory procedure can return a reference to a global instance that is shared by all callers. The following code illustrates this latter approach:

procedure CreateEncodeDecode(out obj: TObject);

begin

  if FEncodeDecode = nil then

  begin

    FEncodeDecode := TEncodeDecode.Create;

    {save a reference to the interface so that the global instance doesn't free itself }

    FEncodeDecodeInterface := FEncodeDecode as IEncodeDecode;

  end;

  obj := FEncodeDecode; { return global instance }

end;

When using a factory procedure, supply the factory procedure as a second parameter to the RegisterInvokableClass method:

InvRegistry.RegisterInvokableClass(TEncodeDecode, CreateEncodeDecode);


Creating custom exception classes for Web Services
 DevGuide: Developing Internet applications

Creating custom exception classes for Web Services

Topic groups	See also

When your Web Service application raises an exception in the course of trying to execute a SOAP request, it automatically encodes information about that exception in a SOAP fault packet, which it returns instead of the results of the method call. The client application then raises the exception.

By default, the client application merely raises a generic exception (Exception) with the error message in the SOAP fault packet. However, you can transmit additional exception information by using an exception class that descends from ERemotableException. The values of any published properties you add to your exception class are included in the SOAP fault packet so that the client can raise an equivalent exception.

To use an ERemotableException descendant, you must register it with the remotable type registry. Thus, in the unit that defines your ERemotableException descendant, you must add the InvokeRegistry unit to the uses clause and add a call to the RegisterXSClass method of the object that the global RemTypeRegistry function returns.

If the client uses the same unit that defines and registers your ERemotableException descendant, then when it receives the SOAP fault packet, it automatically raises an instance of the appropriate exception class, with all properties set to the values in the SOAP fault packet.


Generating WSDL documents for a Web Service application
 DevGuide: Developing Internet applications

Generating WSDL documents for a Web Service application

Topic groups	See also

If you include the same units that define and register your invokable interfaces, the classes that represent complex type information, and your remotable exceptions in a Delphi client application, it can generate calls to use your Web Service. All you need to do is supply the URL where you install your Web Service application.

However, you may want to make your Web Service available to a wider range of clients. For example, you may have clients that are not written in Delphi. If you are deploying several versions of your server application, you may not want to use a single hard-coded URL for the server, but rather let the client look up the server location dynamically. For these cases, you may want to publish a WSDL document that describes the types and interfaces in your Web Service, with information on how to call them.

To publish a WSDL document that describes your Web Service, simply include a TWSDLHTMLPublish component in your Web Module. TWSDLHTMLPublish is an auto-dispatching component, which means it automatically responds to incoming messages that request a list of WSDL documents for your Web Service. Use the WebDispatch property to specify the path information of the URL clients must use to access the list of WSDL documents. The Web browser can then request the list of WSDL documents by specifying an URL that is made up of the location of the server application followed by the path in the WebDispatch property. This URL looks something like the following:

http://www.myco.com/MyService.dll/WSDL

Tip:	If you want a physical WSDL file instead, you can display the WSDL document in your Web browser and then save it to generate a WSDL document file.

It is not necessary to publish the WSDL document from the same application that implements your Web Service. To create an application that simply publishes the WSDL document, omit the units that contain the implementation objects, and only include the units that define and register invokable interfaces, remotable classes that represent complex types, and any remotable exceptions.

By default, when you publish a WSDL document, it indicates that the services are available at the same URL as the one where you published the WSDL document (but with a different path). If you are deploying multiple versions of your Web Service application, or if you are publishing the WSDL document from a different application than the one that implements the Web Service, you will need to change the WSDL document so that includes updated information on where to locate the Web Service.

To change the URL, use the WSDL administrator. The first step is to enable the administrator. You do this by setting the AdminEnabled property of the TWSDLHTMLPublish component to True. Then, when you use your browser to display the list of WSDL documents, it includes a button to administer them as well. Use the WSDL administrator to specify the locations (URLs) where you have deployed your Web Service application.


Writing SOAP clients
 DevGuide: Developing Internet applications

Writing clients for Web Services

Topic groups	See also

Delphi provides client-side support for calling Web Services that use a SOAP-based binding. These Web Services can be supplied by a server written in Delphi, or by any other server that defines its Web Service in a WSDL document.

If the server is not written in Delphi, you can first import the WSDL document that describes the server. This process is described below. If the server was written using Delphi, you do not need to use a WSDL document: you can simply add any units that define the invokable interfaces you want to use to your project, as well as any units that define remotable classes that represent complex types and that define remotable exceptions that the Web Service application can raise.

Note:	For information about creating the unit that defines an invokable interface in a Delphi Web Service server, see Defining invokable interfaces. For information about creating a unit that defines a remotable class for a complex type, see Using complex types in invokable interfaces. For information about creating a unit that defines a remotable exception, see Creating custom exception classes for Web Services.

Importing WSDL documents

Before you can use a Web Service that was not written using Delphi, you must import a WSDL document (or XML schema file) that defines the service. The Web Services importer creates a unit that defines and registers the interfaces and types you need to use.

To use the Web Services importer, choose File|New|Other, and on the WebServices page double-click the icon labelled Web Services importer. In the dialog that appears, specify the file name of a WSDL document (or XML schema file) or provide the URL where that document is published. When you click Generate, the importer creates new units that define and register invokable interfaces for the operations defined in the document, and that define and register remotable classes for the types that the document defines.

If the WSDL document or XML schema file uses identifiers that are also Object Pascal keywords, the importer automatically adjusts their names so that the generated code can compile. When complex types are declared inline, the importer adds code to define and register the corresponding remotable class in the same unit as the invokable interface that uses them. Otherwise, types are defined and registered in a separate unit.

Calling invokable interfaces

To call an invokable interface, your client application must include any units that define the invokable interfaces and any remotable classes that implement complex types. If the server is written in Delphi, these should be the same units that the server application uses to define and register these interfaces and classes. It is best to use the same unit, because when you register an invokable interface or remotable class, it is given a uniform resource identifier (URI) that uniquely identifies it. That URI is derived from the name of the interface (or class) and the name of the unit in which it is defined. If the client and server do not register the interface (or class) using the same URI, they can’t communicate. If you do not use the same unit, the code that registers the interface and implementation class must explicitly specify a namespace URI to ensure that client and server use the same namespace.

If the server is not written in Delphi, or if you do not want to use the same unit in the client that you used in the server, these units can be created by the Web Services importer.

Once the client application has the declaration of an invokable interface, create an instance of THTTPRio for the desired interface:

X := THTTPRio.Create(nil);

Next, provide the THTTPRio object with the information it needs to identify the server interface and locate the server. There are two ways to supply this information:

If the server is written in Delphi, the identification of the interface on the server is handled automatically, based on the URI that is generated for it when the interface is registered. You need only set the URL property to indicate the location of the server. The path portion of this URL should match the path of the dispatcher component in the server’s Web Module:

X.URL := 'http://www.myco.com/MyService.dll/SOAP/';

If the server is not written in Delphi, THTTPRio must look up the URI for the interface, the information that must be included in the Soap Action header, and the location of the server from a WSDL document. You tell it how to do this using the WSDLLocation, Service, and Port properties:

X.WSDLLocation := 'Cryptography.wsdl';

X.Service := 'Cryptography';

X.Port := 'SoapEncodeDecode';

You can then use the as operator to cast the instance of THTTPRio to the invokable interface. When you do this, it creates a vtable for the associated interface dynamically in memory, enabling you to make interface calls:

InterfaceVariable := X as IEncodeDecode;

Code := InterfaceVariable.EncodeValue(5);

THTTPRio relies on the invocation registry to obtain information about the invokable interface. If the client application does not have an invocation registry, or if the invokable interface is not registered, THTTPRio can’t build its in-memory vtable.


Working with sockets
 DevGuide: Developing Internet applications

Working with sockets

Topic groups	See also

The socket components let you create an application that can communicate with other systems using TCP/IP and related protocols. Using sockets, you can read and write over connections to other machines without worrying about the details of the underlying networking software. Sockets provide connections based on the TCP/IP protocol, but are sufficiently general to work with related protocols such as User Datagram Protocol (UDP), Xerox Network System (XNS), Digital’s DECnet, or Novell’s IPX/SPX family.

Using sockets, you can write network servers or client applications that read from and write to other systems. A server or client application is usually dedicated to a single service such as Hypertext Transfer Protocol (HTTP) or File Transfer Protocol (FTP). Using server sockets, an application that provides one of these services can link to client applications that want to use that service. Client sockets allow an application that uses one of these services to link to server applications that provide the service.

To write applications that use sockets, you should understand

Implementing services

Types of socket connections

Describing sockets

Using socket components

Responding to socket events

Reading and writing over socket connections


Implementing services
 DevGuide: Developing Internet applications

Implementing services

Topic groups	See also

Sockets provide one of the pieces you need to write network servers or client applications. For many services, such as HTTP or FTP, third party servers are readily available. Some are even bundled with the operating system, so that there is no need to write one yourself. However, when you want more control over the way the service is implemented, a tighter integration between your application and the network communication, or when no server is available for the particular service you need, then you may want to create your own server or client application. For example, when working with distributed data sets, you may want to write a layer to communicate with databases on other systems.

To implement or use a service using sockets, you must understand

service protocols

services and ports


Service protocols
 DevGuide: Developing Internet applications

Service protocols

Topic groups	See also

Before you can write a network server or client, you must understand the service that your application is providing or using. Many services have standard protocols that your network application must support. If you are writing a network application for a standard service such as HTTP, FTP, or even finger or time, you must first understand the protocols used to communicate with other systems. See the documentation on the particular service you are providing or using.

If you are providing a new service for an application that communicates with other systems, the first step is designing the communication protocol for the servers and clients of this service. What messages are sent? How are these messages coordinated? How is the information encoded?

Communicating with applications

Often, your network server or client application provides a layer between the networking software and an application that uses the service. For example, an HTTP server sits between the Internet and a Web server application that provides content and responds to HTTP request messages.

Sockets provide the interface between your network server or client application and the networking software. You must provide the interface between your application and the clients that use it. You can copy the API of a standard third party server (such as Apache), or you can design and publish your own API.


Services and ports
 DevGuide: Developing Internet applications

Services and ports

Topic groups	See also

Most standard services are associated, by convention, with specific port numbers. When implementing services, you can consider the port number a numeric code for the service.

If you are implementing a standard service for use in cross-platform applications, Linux socket objects provide methods for you to look up the port number for the service. If you are providing a new service, you can specify the associated port number in the /etc/services file. See your Linux documentation for more information on the services file.


Types of socket connections
 DevGuide: Developing Internet applications

Types of socket connections

Topic groups	See also

Socket connections can be divided into three basic types, which reflect how the connection was initiated and what the local socket is connected to. These are

Client connections.

Listening connections.

Server connections.

Once the connection to a client socket is completed, the server connection is indistinguishable from a client connection. Both end points have the same capabilities and receive the same types of events. Only the listening connection is fundamentally different, as it has only a single endpoint.


Client connections
 DevGuide: Developing Internet applications

Client connections

Topic groups	See also

Client connections connect a client socket on the local system to a server socket on a remote system. Client connections are initiated by the client socket. First, the client socket must describe the server socket to which it wishes to connect. The client socket then looks up the server socket and, when it locates the server, requests a connection. The server socket may not complete the connection right away. Server sockets maintain a queue of client requests, and complete connections as they find time. When the server socket accepts the client connection, it sends the client socket a full description of the server socket to which it is connecting, and the connection is completed by the client.


Listening connections
 DevGuide: Developing Internet applications

Listening connections

Topic groups	See also

Server sockets do not locate clients. Instead, they form passive “half connections” that listen for client requests. Server sockets associate a queue with their listening connections; the queue records client connection requests as they come in. When the server socket accepts a client connection request, it forms a new socket to connect to the client, so that the listening connection can remain open to accept other client requests.


Server connections
 DevGuide: Developing Internet applications

Server connections

Topic groups	See also

Server connections are formed by server sockets when a listening socket accepts a client request. A description of the server socket that completes the connection to the client is sent to the client when the server accepts the connection. The connection is established when the client socket receives this description and completes the connection.


Describing sockets
 DevGuide: Developing Internet applications

Describing sockets

Topic groups	See also

Sockets let your network application communicate with other systems over the network. Each socket can be viewed as an endpoint in a network connection. It has an address that specifies

The system on which it is running.

The types of interfaces it understands.

The port it is using for the connection.

A full description of a socket connection includes the addresses of the sockets on both ends of the connection. You can describe the address of each socket endpoint by supplying both the IP address or host and the port number.

Before you can make a socket connection, you must fully describe the sockets that form its endpoints. Some of the information is available from the system your application is running on. For instance, you do not need to describe the local IP address of a client socket—this information is available from the operating system.

The information you must provide depends on the type of socket you are working with. Client sockets must describe the server they want to connect to. Listening server sockets must describe the port that represents the service they provide.


Describing the host
 DevGuide: Developing Internet applications

Describing the host

Topic groups	See also

The host is the system that is running the application that contains the socket. You can describe the host for a socket by giving its IP address, which is a string of four numeric (byte) values in the standard Internet dot notation, such as

123.197.1.2

A single system may support more than one IP address.

IP addresses are often difficult to remember and easy to mistype. An alternative is to use the host name. Host names are aliases for the IP address that you often see in Uniform Resource Locators (URLs). They are strings containing a domain name and service, such as

http://www.ASite.com

Most Intranets provide host names for the IP addresses of systems on the Internet. You can learn the host name associated with any IP address (if one already exists) by executing the following command from a command prompt:

nslookup IPADDRESS

where IPADDRESS is the IP address you’re interested in. If your local IP address doesn’t have a host name and you decide you want one, contact your network administrator.

Server sockets do not need to specify a host. The local IP address can be read from the system. If the local system supports more than one IP address, server sockets will listen for client requests on all IP addresses simultaneously. When a server socket accepts a connection, the client socket provides the remote IP address.

Client sockets must specify the remote host by providing either its host name or IP address.

Choosing between a host name and an IP address

Most applications use the host name to specify a system. Host names are easier to remember, and easier to check for typographical errors. Further, servers can change the system or IP address that is associated with a particular host name. Using a host name allows the client socket to find the abstract site represented by the host name, even when it has moved to a new IP address.

If the host name is unknown, the client socket must specify the server system using its IP address. Specifying the server system by giving the IP address is faster. When you provide the host name, the socket must search for the IP address associated with the host name, before it can locate the server system.


Using ports
 DevGuide: Developing Internet applications

Using ports

Topic groups	See also

While the IP address provides enough information to find the system on the other end of a socket connection, you also need a port number on that system. Without port numbers, a system could only form a single connection at a time. Port numbers are unique identifiers that enable a single system to host multiple connections simultaneously, by giving each connection a separate port number.

One way to look at port numbers is as numeric codes for the services implemented by network applications. This is a convention that allows listening server connections to make themselves available on a fixed port number so that they can be found by client sockets. Server sockets listen on the port number associated with the service they provide. When they accept a connection to a client socket, they create a separate socket connection that uses a different, arbitrary, port number. This way, the listening connection can continue to listen on the port number associated with the service.

Client sockets use an arbitrary local port number, as there is no need for them to be found by other sockets. They specify the port number of the server socket to which they want to connect so that they can find the server application. Often, this port number is specified indirectly, by naming the desired service.


Using socket components
 DevGuide: Developing Internet applications

Using socket components

Topic groups	See also

The Internet palette page includes three socket components that allow your network application to form connections to other machines, and that allow you to read and write information over that connection. These are:

TcpServer

TcpClient

UdpSocket

Associated with each of these socket components are socket objects, which represent the endpoint of an actual socket connection. The socket components use the socket objects to encapsulate the socket server calls, so that your application does not need to be concerned with the details of establishing the connection or managing the socket messages.

If you want to customize the details of the connections that the socket components make on your behalf, you can use the properties, events, and methods of the socket objects.


Getting information about the connection
 DevGuide: Developing Internet applications

Getting information about the connection

Topic groups	See also

After completing the connection to a client or server socket, you can use the client or server socket object associated with your socket component to obtain information about the connection. Use the LocalHost and LocalPort properties to determine the address and port number used by the local client or server socket, or use the RemoteHost and RemotePort properties to determine the address and port number used by the remote client or server socket. Use the GetSocketAddr method to build a valid socket address based on the host name and port number. You can use the LookupPort method to look up the port number. Use the LookupProtocol method to look up the protocol number. Use the LookupHostName method to look up the host name based on the host machine’s IP address.

To view network traffic in and out of the socket, use the BytesSent and BytesReceived propeties.


Using client sockets
 DevGuide: Developing Internet applications

Using client sockets

Topic groups	See also

Add a TcpClient or UdpSocket component to your form or data module to turn your application into a TCP/IP or UDP client. Client sockets allow you to specify the server socket you want to connect to, and the service you want that server to provide. Once you have described the desired connection, you can use the client socket component to complete the connection to the server.

Each client socket component uses a single client socket object to represent the client endpoint in a connection.

Use client sockets to

Specify the desired server.

Connect to the server.

Get information about the connection.

Read from or write to the server.

Close the connection.


Specifying the desired server
 DevGuide: Developing Internet applications

Specifying the desired server

Topic groups	See also

Client socket components have a number of properties that allow you to specify the server system and port to which you want to connect. Use the RemoteHost property to specify the remote host server by either its host name or IP address.

In addition to the server system, you must specify the port on the server system that your client socket will connect to. You can use the RemotePort property to specify the server port number directly or indirectly by naming the target service.


Forming the connection
 DevGuide: Developing Internet applications

Forming the connection

Topic groups	See also

Once you have set the properties of your client socket component to describe the server you want to connect to, you can form the connection at runtime by calling the Open method. If you want your application to form the connection automatically when it starts up, set the Active property to True at design time, using the Object Inspector.


Getting information about the connection
 DevGuide: Developing Internet applications

Getting information about the connection

Topic groups	See also

After completing the connection to a server socket, you can use the client socket object associated with your client socket component to obtain information about the connection. Use the LocalHost and LocalPort properties to determine the address and port number used by the client and server sockets to form the end points of the connection. You can use the Handle property to obtain a handle to the socket connection to use when making socket calls.


Closing the connection
 DevGuide: Developing Internet applications

Closing the connection

Topic groups	See also

When you have finished communicating with a server application over the socket connection, you can shut down the connection by calling the Close method. The connection may also be closed from the server end. If that is the case, you will receive notification in an OnDisconnect event.


Using server sockets
 DevGuide: Developing Internet applications

Using server sockets

Topic groups	See also

Add a server socket component (TcpServer or UdpSocket) to your form or data module to turn your application into an IP server. Server sockets allow you to specify the service you are providing or the port you want to use to listen for client requests. You can use the server socket component to listen for and accept client connection requests.

Each server socket component uses a single server socket object to represent the server endpoint in a listening connection. It also uses a server client socket object for the server endpoint of each active connection to a client socket that the server accepts.

Use server sockets to

Specify the port.

Listen for client requests.

Connect to clients.

Read from or write to the server.

Close server connections.


Specifying the port
 DevGuide: Developing Internet applications

Specifying the port

Topic groups	See also

Before your server socket can listen to client requests, you must specify the port that your server will listen on. You can specify this port using the LocalPort property. If your server application is providing a standard service that is associated by convention with a specific port number, you can also specify the service name using the LocalPort property. It is a good idea to use the service name instead of a port number, because it is easy to introduce typographical errors when specifying the port number.


Listening for client requests
 DevGuide: Developing Internet applications

Listening for client requests

Topic groups	See also

Once you have set the port number of your server socket component, you can form a listening connection at runtime by calling the Open method. If you want your application to form the listening connection automatically when it starts up, set the Active property to True at design time, using the Object Inspector.


Connecting to clients
 DevGuide: Developing Internet applications

Connecting to clients

Topic groups	See also

A listening server socket component automatically accepts client connection requests when they are received. You receive notification every time this occurs in an OnAccept event.


Closing server connections
 DevGuide: Developing Internet applications

Closing server connections

Topic groups	See also

When you want to shut down the listening connection, call the Close method or set the Active property to False. This shuts down all open connections to client applications, cancels any pending connections that have not been accepted, and then shuts down the listening connection so that your server socket component does not accept any new connections.

When TCP clients shut down their individual connections to your server socket, you are informed by an OnDisconnect event.


Responding to socket events
 DevGuide: Developing Internet applications

Responding to socket events

Topic groups	See also

When writing applications that use sockets, you can write or read to the socket anywhere in the program. You can write to the socket using the SendBuf , SendStream, or Sendln methods in your program after the socket has been opened. You can read from the socket using the similarly-named methods ReceiveBuf and Receiveln . The OnSend and OnReceive events are triggered every time something is written or read from the socket. They can be used for filtering. Every time you read or write, a read or write event is triggered.

Both client sockets and server sockets generate error events when they receive error messages from the connection.

Socket components also receive two events in the course of opening and completing a connection. If your application needs to influence how the opening of the socket proceeds, you must use the SendBuf and ReceiveBuf methods to respond to these client or server events.


Error events
 DevGuide: Developing Internet applications

Error events

Topic groups	See also

Client and server sockets generate OnError events when they receive error messages from the connection. You can write an OnError event handler to respond to these error messages. The event handler is passed information about

What socket object received the error notification.

What the socket was trying to do when the error occurred.

The error code that was provided by the error message.

You can respond to the error in the event handler, and change the error code to 0 to prevent the socket from raising an exception.


Client events
 DevGuide: Developing Internet applications

Client events

Topic groups	See also

When a client socket opens a connection, the following events occur:

The socket is set up and initialized for event notification.

An OnCreateHandle event occurs after the server and server socket is created. At this point, the socket object available through the Handle property can provide information about the server or client socket that will form the other end of the connection. This is the first chance to obtain the actual port used for the connection, which may differ from the port of the listening sockets that accepted the connection.

The connection request is accepted by the server and completed by the client socket.

When the connection is established, the OnConnect notification event occurs.


Server events
 DevGuide: Developing Internet applications

Server events

Topic groups	See also

Server socket components form two types of connections: listening connections and connections to client applications. The server socket receives events during the formation of each of these connections.

Events when listening

Just before the listening connection is formed, the OnListening event occurs. You can use its Handle property to make changes to the socket before it is opened for listing. For example, if you want to restrict the IP addresses the server uses for listening, you would do that in an OnListening event handler.

Events with client connections

When a server socket accepts a client connection request, the following events occur:

An OnAccept event occurs, passing in the new TTcpClient object to the event handler. This is the first point when you can use the properties of TTcpClient to obtain information about the server endpoint of the connection to a client.

If BlockMode is bmThreadBlocking an OnGetThread event occurs. If you want to provide your own customized descendant of TServerSocketThread, you can create one in an OnGetThread event handler, and that will be used instead of TServerSocketThread. If you want to perform any initialization of the thread, or make any socket API calls before the thread starts reading or writing over the connection, you should use the OnGetThread event handler for these tasks as well.

The client completes the connection and an OnAccept event occurs. With a non-blocking server, you may want to start reading or writing over the socket connection at this point.


Reading and writing over socket connections
 DevGuide: Developing Internet applications

Reading and writing over socket connections

Topic groups	See also

The reason you form socket connections to other machines is so that you can read or write information over those connections. What information you read or write, or when you read it or write it, depends on the service associated with the socket connection.

Reading and writing over sockets can occur asynchronously, so that it does not block the execution of other code in your network application. This is called a non-blocking connection. You can also form blocking connections, where your application waits for the reading or writing to be completed before executing the next line of code.


Non-blocking connections
 DevGuide: Developing Internet applications

Non-blocking connections

Topic groups	See also

Non-blocking connections read and write asynchronously, so that the transfer of data does not block the execution of other code in you network application. To create a non-blocking connection for client or server sockets, set the BlockMode property to bmNonBlocking.

When the connection is non-blocking, reading and writing events inform your socket when the socket on the other end of the connection tries to read or write information.


Reading and writing events
 DevGuide: Developing Internet applications

Reading and writing events

Topic groups	See also

Non-blocking sockets generate reading and writing events when it needs to read or write over the connection. You can respond to these notifications in an OnReceive or OnSend event handler.

The socket object associated with the socket connection is provided as a parameter to the read or write event handlers. This socket object provides a number of methods to allow you to read or write over the connection.

To read from the socket connection, use the ReceiveBuf or Receiveln method. To write to the socket connection, use the SendBuf, SendStream, or Sendln method.


Blocking connections
 DevGuide: Developing Internet applications

Blocking connections

Topic groups	See also

When the connection is blocking your socket must initiate reading or writing over the connection rather than waiting passively for a notification from the socket connection. Use a blocking socket when your end of the connection is in charge of when reading and writing takes place.

For client or server sockets, set the BlockMode property to bmBlocking to form a blocking connection. Depending on what else your client application does, you may want to create a new execution thread for reading or writing, so that your application can continue executing code on other threads while it waits for the reading or writing over the connection to be completed.

For server sockets, set the BlockMode property to bmBlocking or bmThreadBlocking to form a blocking connection. Because blocking connections hold up the execution of all other code while the socket waits for information to be written or read over the connection, server socket components always spawn a new execution thread for every client connection when the BlockMode is bmThreadBlocking. When the BlockMode is bmBlocking, program execution is blocked until a new connection is established.


Using threads with blocking connections
 DevGuide: Developing Internet applications

Using threads with blocking connections

Topic groups	See also

Client sockets do not automatically spawn new threads when reading or writing using a blocking connection. If your client application has nothing else to do until the information has been read or written, this is what you want. If your application includes a user interface that must still respond to the user, however, you will want to generate a separate thread for the reading or writing.

When server sockets form blocking connections, they always spawn separate threads for every client connection, so that no client must wait until another client has finished reading or writing over the connection. By default, server sockets use TClientSocketThread objects to implement the execution thread for each connection.

When writing client threads or writing server threads, you can use TTcpClient to do the actual reading and writing.


Writing client threads
 DevGuide: Developing Internet applications

Writing client threads

Topic groups	See also

To write a thread for client connections, define a new thread object using the New Thread Object dialog. The Execute method of your new thread object handles the details of reading and writing over the thread connection. It creates a TWinSocketStream object, and uses that to read or write. For example:

procedure TMyClientThread.Execute;

var

  TheStream: TWinSocketStream;

  buffer: string;

begin

  { create a TWinSocketStream for reading and writing }

  TheStream := TWinSocketStream.Create(ClientSocket1.Socket, 60000);

  try

    { fetch and process commands until the connection or thread is terminated }

    while (not Terminated) and (ClientSocket1.Active) do

    begin

      try

        GetNextRequest(buffer); { GetNextRequest must be a thread-safe method }

        { write the request to the server }

        TheStream.Write(buffer, Length(buffer) + 1);

        { continue the communication (e.g. read a response from the server) }

        ...

      except

        if not(ExceptObject is EAbort) then

          Synchronize(HandleThreadException); { you must write HandleThreadException }

      end;

    end;

  finally

   TheStream.free;

  end;

end;

To use your thread, create it in an OnConnect event handler. For more information about creating and running threads, see Executing thread objects.


Writing server threads
 DevGuide: Developing Internet applications

Writing server threads

Topic groups	See also

Threads for server connections are descendants of TServerSocketThread. Because of this, you can’t use the New Thread object dialog. Instead, declare your thread manually as follows:

 TMyServerThread = class(TServerClientThread);

To implement this thread, you override the ClientExecute method instead of the Execute method.

Implementing the ClientExecute method is much the same as writing the Execute method of the thread for a client connection. However, instead of using a client socket component that you place in your application from the Component palette, the server client thread must use the TTcpClient object that is created when the listening server socket accepts a client connection. This is available as the public ClientSocket property. In addition, you can use the protected HandleException method rather than writing your own thread-safe exception handling. For example:

procedure TMyServerThread.ClientExecute;

var

  Stream : TWinSocketStream;

  Buffer : array[0 .. 9] of Char;

begin

  { make sure connection is active }

  while (not Terminated) and ClientSocket.Connected do

  begin

    try

      Stream := TWinSocketStream.Create(ClientSocket, 60000);

      try

        FillChar(Buffer, 10, 0); { initialize the buffer }

        { give the client 60 seconds to start writing }

        if Stream.WaitForData(60000) then

        begin

          if Stream.Read(Buffer, 10) = 0 then { if can't read in 60 seconds }

            ClientSocket.Close;               { close the connection }

          { now process the request }

          ...

        end

        else

          ClientSocket.Close; { if client doesn't start, close }

      finally

        Stream.Free;

      end;

    except

      HandleException;

    end;

  end;

end;

Warning:	Server sockets cache the threads they use. Be sure the ClientExecute method performs any necessary initialization so that there are no adverse results from changes made when the thread last executed.

To use your thread, create it in an OnGetThread event handler. When creating the thread, set the CreateSuspended parameter to False.


Related topic groups
Developing Internet applications

•	Writing distributed applications using SOAP

•	Web Broker

•	Creating Internet server applications

•	WebSnap

•	Working with sockets

•	Working with XML documents


Writing distributed applications using SOAP

Related topic groups

•	Using Web Services

•	Writing Servers that support Web Services

•	Defining invokable interfaces

•	Using complex types in invokable interfaces

•	Creating and registering the implementation

•	Creating custom exception classes for Web Services

•	Generating WSDL documents for a Web Service application

•	Writing SOAP clients


Web Broker

Related topic groups

•	Using Web Broker

•	Creating Web server applications with Web Broker

•	The Web module

•	The Web Application object

•	The structure of a Web server application

•	The Web dispatcher

•	Adding actions to the dispatcher

•	Dispatching request messages

•	Action items

•	Determining when action items fire

•	Debugging server applications

•	The target URL

•	The request method type

•	Enabling and disabling action items

•	Choosing a default action item

•	Responding to request messages with action items

•	Accessing client request information

•	Properties that contain request header information

•	Properties that identify the target

•	Properties that describe the Web client

•	Properties that identify the purpose of the request

•	Properties that describe the expected response

•	Properties that describe the content

•	The content of HTTP request messages

•	Creating HTTP response messages

•	Filling in the response header

•	Indicating the response status

•	Indicating the need for client action

•	Describing the server application

•	Describing the content

•	Setting the response content

•	Sending the response

•	Generating the content of response messages

•	Using page producer components

•	HTML templates

•	Using predefined HTML-transparent tag names

•	Specifying the HTML template

•	Converting HTML-transparent tags

•	Using page producers from an action item

•	Chaining page producers together

•	Using database information in responses

•	Adding a session to the Web module

•	Representing a dataset in HTML

•	Using dataset page producers

•	Using table producers

•	Specifying the table attributes

•	Specifying the row attributes

•	Specifying the columns

•	Embedding tables in HTML documents

•	Using TDataSetTableProducer

•	Using TQueryTableProducer


Creating Internet server applications

Related topic groups

•	Creating Internet applications: Overview

•	About Web Broker and WebSnap

•	Terminology and standards

•	Parts of a Uniform Resource Locator

•	HTTP request header information

•	HTTP server activity

•	Composing client requests

•	Serving client requests

•	Responding to client requests

•	Types of Web server applications

•	Using the Web Application Debugger

•	Debugging Web applications that are DLLs

•	Debugging with a Microsoft IIS server

•	Debugging with a Windows 95 Personal Web Server

•	Debugging with Netscape Server Version 2.0

•	Debugging CGI and Win-CGI applications


WebSnap

Related topic groups

•	Using WebSnap

•	Creating Web server applications with WebSnap

•	Server type

•	Web application module types

•	Web application module options

•	Application components

•	Web modules

•	Web data modules

•	Web page modules

•	Web application modules

•	Adapters

•	Page producers

•	Server-side scripting in WebSnap

•	Script objects

•	Dispatching requests

•	Dispatcher components

•	Adapter dispatcher operation

•	Adapter requests and responses

•	Dispatching action items

•	Page dispatcher operation

•	WebSnap tutorial

•	WebSnap Tutorial Part I: Create a new application

•	WebSnap Tutorial Part II: Create a CountryTable page

•	WebSnap Tutorial Part III: Add data components to the CountryTable module

•	WebSnap Tutorial Part IV: Create a grid to display the data

•	WebSnap Tutorial Part V: Add an edit form

•	WebSnap Tutorial Part VI: Add error reporting

•	WebSnap Tutorial Part VII: Run the completed application


Working with sockets

Related topic groups

•	Working with sockets

•	Implementing services

•	Service protocols

•	Services and ports

•	Types of socket connections

•	Client connections

•	Listening connections

•	Server connections

•	Describing sockets

•	Describing the host

•	Using ports

•	Using socket components

•	Getting information about the connection

•	Using client sockets

•	Specifying the desired server

•	Forming the connection

•	Getting information about the connection

•	Closing the connection

•	Using server sockets

•	Specifying the port

•	Listening for client requests

•	Connecting to clients

•	Closing server connections

•	Responding to socket events

•	Error events

•	Client events

•	Server events

•	Reading and writing over socket connections

•	Non-blocking connections

•	Reading and writing events

•	Blocking connections

•	Using threads with blocking connections

•	Writing client threads

•	Writing server threads


Working with XML documents

Related topic groups

•	Working with XML documents

•	Using the Document Object Model

•	Working with XML components

•	Using TXMLDocument

•	Working with XML nodes

•	Abstracting XML documents with the Data Binding wizard

•	Using the XML Data Binding wizard

•	Using Code that the XML Data Binding wizard generates


Link not found

The topic you requested is either not available or not linked to this Help system. This can occur if you launched this Help file from a system on which Delphi has not yet been installed, or if the subject matter you are requesting is not available in your edition of Delphi.


The topic you requested is now loading. If it does not appear within a few seconds, the topic is either not available or not linked to this Help system. This can occur if you launched this Help file from a system on which Delphi has not yet been installed, or if the subject matter you are requesting is not available in your edition of Delphi.