|Delphi Clinic||C++Builder Gate||Training & Consultancy||Delphi Notes Weblog||Dr.Bob's Webshop|
With JBuilder available to produce 100% pure Java applets, applications and JavaBeans, we should not forget that Delphi is also capable of producing interesting internet solutions with ActiveForms and Web Modules...
ActiveForms are great for Intranet Solutions, where the application itself gets executed on the client machine. For truly (client) platform-independent internet solutions, we must focus our attention to the web server. In these cases, we can use Delphi to write CGI (Common Gateway Interface) or WinCGI applications, or ISAPI/NSAPI (Internet or Netscape Server API) web server extension DLLs. We can use HTML on the client side, with CGI Forms to send data from the client to the server, while the internet application on the web server would typically generate a dynamic HTML response page.
Writing CGI, WinCGI or ISAPI/NSAPI using Delphi is a non-trivial task. Especially switching between one solution to another can be hard, so may third-party vendors are offers different ways of support for these web server applications, like WebHub (an entire Web Server Architecture).
Delphi 3 and 4 Client/Server (as well as Delphi 4 Professional with AddOn) and Delphi 5 Professional also come with special Wizard and Component support for these kinds of web server applications, called Web Modules (also known as WebBroker). Using Web Modules, we can create CGI, WinCGI and ISAPI/NSAPI web server applications, and while we can turn one type into another, the application itself totally abstracts from the implementation details. The only difference (apart from the fact that an ISAPI DLL remains loaded by the Web Server and a CGI EXE not) is that an ISAPI application is easier to debug using IntraBob than a CGI application. So, in an existing Web Module project, there's no way to tell if we're working on a CGI or ISAPI/NSAPI type of application; only the main project source code contains this info (which can be changed to generate another type of Web Server application). I think that's an important issue: the programmer uses a single set of components to handle WebActions, WebRequests, WebResponses, etc.
Using a special WebDispatcher component, we can even migrate existing Data Modules into Web Modules (so legacy code is not entirely lost). The WebDispatcher is integrated into regular Web Modules, and is used to dispatch a certain Action within the Web Module (a Web Server application can handle multiple requests and thus perform multiple different actions, and the WebDispatcher is used to determine which one).
Each WebAction can be programmed separately, but yet shares everything from the WebModule. This includes all tables, queries and business rules, as well as other routines or resources. A WebAction can directly write to the Response string, or use one of three special components to generate dynamic HTML and handle requests.
The PageProducer component can be used to generate dynamic HTML pages, including special TAGs that can be substituted for anything at run-time. The DataSetTableProducer component can be used to generate a dynamic HTML table-formatted using columns from a database table. Output can be completely configured, and requires BDE on the web server. The QueryTableProducer component is like the DataSetTableProducer, only this time using a query instead of a table. Special possibilities arise when using a parameterised query, such as direct coupling to a HTML CGI input field.
Of course, the Web Module also supports cookies, although I personally prefer to use "hidden fields" to store state information.
I conclude that Delphi Web Modules offer great support for writing Web Server applications for the internet.
Bug Report: TWinCGI OutputFile
Delphi 3 C/S owners writing WinCGI apps using Web Modules should be aware of a potential problem: the OutputFile is opened in fmOpenWrite mode, which fails if the file doesn't exist (yet). This is not a problem when using IIS/PWS (who pre-create the OutputFile), but WebSite (and IntraBob for that matter) don't create the output-file in advance, so they'll get an exception "cannot open file".
A fix is to open CGIApp.pas, and change "fmOpenWrite" to "fmCreate" in lines 410 and 507.