So far, we've seen only a number of WebSnap components and wizards in use. We can already compare the general working of WebSnap with that of WebBroker (see Chapter 13 of Sams C++Builder 5 Developer's Guide for WebBroker details). In this section we will discuss a number of the differences between WebBroker and WebSnap, explain why you can use WebBroker components in a WebSnap environment, but not (easily) the other way around, and finally start the description of the most important WebSnap building blocks: the adapters.
Where WebBroker was working with a single Web module, using Web action items (and PathInfo) to distinguish the incoming requests , the new WebSnap architecture uses Page Modules to prepresent individual pages (again dispatched using PathInfo). Using WebBroker you have a choice in using the HTMLDoc (internal) or HTMLFile (external) property to store the HTML template, and the default was using the internal HTMLDoc property (such as the MidasPageProducer).
The WebSnap architecture now uses external HTML templates as default, which makes it easier to connect these external HTML files to Web editors such as Dreamweaver or FrontPage (or even Notepad). So, we see Actions versus Pages as one of the main differences.
Where a WebBroker application starts with a Web module, a WebSnap application starts with either a TWebAppDataModule or a TWebAppPageModule . Both are just a container for WebSnap system components that we'll see later, such as dispatchers, global adapters (the TApplicationAdapter), a user list, and session components.
The WebSnap Application Wizard will automatically create the Web Module of choice (either a TWebAppDataModule or a TWebAppPageModule ) including the selected components. However, you can always add more components later (or remove existing components), but you cannot change a TWebAppDataModule into a TWebApp PageModule or vice versa. TWebAppComponents is the component in a TWebAppDataModule that references all of the system components in use by the WebSnap application.
The difference between a WebAppPageModule and a TWebAppDataModule is that the former generates a page. The PageProducer property references the producer component responsible for generating content. This property must not be nil or no content will be generated. The WebSnap Application Wizard automatically adds a page producer component when it creates a new TWebAppPageModule .
A TWebPageModule holds all the components needed for generating a specific Web page. The WebSnap Page Module Wizard creates a TWebPageModule descendant as well as the selected PageProducer for generating the content of the Web page. It also adds code to the initialization section of the unit it creates that registers the TWebPageModule descendant with a factory object that the WebSnap application can use to create the Web page module.
The page producer that the wizard adds to the Web page module becomes the value of the PageProducer property (and if you replace it with another PageProducer property later, it will automatically be set to the PageProducer property). If the PageProducer property is nil, the Web page module can't generate the content of a Web page.
TWebDataModule is compatible with WebSnap applications. The initialization section of TWebDataModule registers a factory that is used by the WebSnap application to create the data module. Use TWebDataModule as a container for components that can be used by other modules in your WebSnap application.
WebBroker is Action-based, whereas WebSnap is Page-based. The support for multiple ( optionally cached) data modules and page modules make it easier to maintain bigger Web sites than was previously possible. Server side scripting adds to the flexibility as well. And finally, WebSnap wouldn't be possible without Adapter components to glue the Delphi code to the scripting side (and back).
One of the nice new features of WebSnap is the support for Server Side Scripting. In the previous version of C++Builder, we had Internet Express, which enabled support for Client Side Scripting (the JavaScript that was used to bind XML data packets to HTML input controls), but this was limited to prewritten client-side JavaScript. With WebSnap, we can not only use generated Server Side JavaScript, but can also easily add our own scripting code, or use external Web page editors (such as the aforementioned Dreamweaver or FrontPage) to help write the server-side scripting.
We can use the HTML tab in the C++Builder code editor to modify the generated HTML and even add our own scripting snippets. A very simple example script that displays the Name of the Page as HTML title is programmed as follows (inside the main WebSnap Web Module):
<html> <head> <title> <%= Page.Title %> </title> </head> <body> <h1><%= Application.Title %></h1>
In case you wonder , the <%= and %> are just shortcuts for the JavaScript code Response.Write to write the text between them.
As usual a good starting point to playing with server-side scripting is the code that C++Builder generates, such as the login and user information on the main home page, which is coded as follows:
<% if (EndUser.Logout != null) { %> <% if (EndUser.DisplayName != '') { %> <h1>Welcome <%=EndUser.DisplayName %></h1> <% } %> <% if (EndUser.Logout.Enabled) { %> <a href="<%=EndUser.Logout.AsHREF%>">Logout</a> <% } %> <% if (EndUser.LoginForm.Enabled) { %> <a href=<%=EndUser.LoginForm.AsHREF%>>Login</a> <% } %> <% } %>
We've seen that the WebSnap architecture uses adapters as a communication layer between the data layer and the presentation layer. As data layer we can use anything that can store or retrieve data, including the obvious choice: a dataset. As presentation layer, WebSnap produces HTML in different formats (or modes) such as browsing, editing, and so forth.
In this section, we'll explain how an adapter works, and which adapters are available in the C++Builder 6 Enterprise implemenation of WebSnap.
There are five available Adapter components on the WebSnap tab of C++Builder 6: the regular TAdapter , the TPagedAdapter (showing adapter output in multiple pages), TDataSetAdapter (a logic connection between an adapter and a dataset), and the TLoginFormAdapter (to provide you with a login form). Finally, we also have the TApplicationAdapter and TendUserAdapter , but these are singleton adapters and usually only added to your main WebSnap Web module.
Adapters consist of fields and actions, and if you right-click any TAdapter (or derived component) you can select the Fields Editor and the Actions Editor; usually the place to add custom fields and/or their actions.
The Adapter Fields are storage places for data. Think of them as the properties of WebSnap adapter layer. For the regular TAdapter component, there can be six different kinds of Adapter Fields: AdapterBooleanField , AdapterField (the generic value), AdapterFileField , AdapterImageField , AdapterMemoField , and finally AdapterMulti ValueField .
All Adapter Fields are derived directly or indirectly from the TCustomAdapterField , which has no published properties or events, but does call event handlers to retrieve the Adapter Field value ( OnGetValue ), validate a value ( OnValidateValue ), update the value ( OnUpdateValue ), as well as customize the displayed output ( OnGetDisplayText ).
The Adapter Fields can be seen as placeholders for the data, whereas the Adapter Actions can be seen as methods or routines that can operate on this data. Although it's useful for the user to see or be able to enter data, there is always some kind of action (login, move to the next page, submit the data, delete record, and so forth) that has to be taken, so there's always need for Adapter Action components.
For each Adapter Action, we can define the Name of the action as well as the ActionName and DisplayLabel (to be used on buttons , for example, as we'll see later when we combine Adapter Actions with AdapterCommandGroups inside AdapterPageProducers ).
An Adapter Action can also define its ExecuteAccess , which specifies the access rights needed to execute this particular action. The server-side script accesses the CanExecute property and this value is checked against the end user's rights. This is something that we'll see again when we add users to a userlist for the Login functionality.
Adapter Actions also have a number of events, namely the OnExecute (the most important one), OnAfterGetResponse , OnBeforeGetResponse , OnGetEnabled , and OnGetParams .
A regular TAdapter component has regular Adapter Fields and custom Adapter Actions. Adapter components are used in combination with a TAdapterPageProducer component ”connecting the Adapter Fields to DisplayComponents (like an AdapterField Group or AdapterGrid ) and the Adapter Actions to AdapterActionButtons (from an AdapterCommandGroup ).
A TPagedAdapter is a TAdapter component with an additional PageSize property that defines the size of the items on a particular page. If you didn't already add explicit actions to the Adapter, you'll see NextPage , PrevPage , and GotoPage actions automatically (they will disappear as soon as you set the PageSize property back to zero again).
The TDataSetAdapter is one of the most useful TAdapter components, connecting to a TDataSet , mapping dataset fields and operations to Adapter Fields and Actions. Furthermore, like the TPagedAdapter , a TDataSetAdapter also has a PageSize property that specifies the number of records that are displayed on a single page. Very useful!
The TLoginFormAdapter has default adapter fields for user name, password, and next page (which enables the user to select a Web page to open after logging in). TLoginFormAdapter has a single default action for logging in. If the WebSnap application also contains an end user adapter such as TEndUserAdapter or TEndUserSession Adapter , TLoginFormAdapter will call the end user adapter's Login() method to log the user in. This adapter will be covered in more detail in the WebSnap Login section of this chapter.
The TApplicationAdapter is a global adapter that is used only in the main WebApp Web Module. It contains a single field called Title that gets its value from the ApplicationTitle property. We can add custom adapter fields and actions to the TApplicationAdapter , use server-side script, and use the Application variable to access fields and actions of the ApplicationAdapter . For example, <%= Application.Title %> writes the title of the application.
The TEndUserAdapter is another global adapter that is used only in the main WebApp Web Module. The TEndUserAdapter has two default Adapter fields: DisplayName and LoggedIn . These fields contain the user's name and login state. We can write code in the OnGetDisplayName and OnIsLoggedIn event handlers to override their values. TEndUserAdapter also has two default actions: LoginForm and LogoutOut . The former displays a login form, whereas the latter logs the user out. We can use the LoginPage property to specify the Page Module name of the login page, and can respond to the OnLogin and OnLogout event handlers.
At the scripting side, we have the EndUser script variable, which can be used to display end user fields and execute end user actions. The following JavaScript snippet displays the name of the end user when logged in:
<% if (EndUser.LoggedIn) { %> <h1>Welcome <%= EndUser.DisplayName %> </h1> <% } %>
The following JavaScript snippet displays a login or logout hyperlink.
<% if (EndUser.Logout.Enabled) { %> <a href="<%=EndUser.Logout.AsHREF%>">Logout</a> <% } %> <% if (EndUser.LoginForm.Enabled) { %> <a href=<%=EndUser.LoginForm.AsHREF%>>Login</a> <% } %>
TEndUserAdapter also specifies the access rights for the end user. If the WebSnap application contains a TWebUserList , TEndUserAdapter uses the TWebUserList to obtain rights for the specific end user. We can also write code for the OnHasRights event handler to perform this task.
The TEndUserSessionAdapter is a special TEndUserAdapter that we will always use in combination with the TSessionsService component (more about this in the WebSnap Sessions section of this chapter).
We can derive from TAdapter or TCustomAdapter to create our own custom WebSnap adapter components. See my Web site at http://www.drbob42.com/BobAdapt for a plug-in wizard to create your own custom adapter components for Delphi, Kylix, and C++Builder.
Apart from Adapters, the WebSnap Architecture depends on a special TPageProducer to actually produce the dynamic HTML. The TTableProducer components have a small(er) role in the WebSnap world.
A regular TPageProducer uses the HTMLDoc or HTMLFile properties to store a HTML template to be filled in (using the OnHTMLTag event handler), whereas the TAdapterPageProducer uses an external template file, and generated dynamic HTML as well as scripting code to connect AdapterFields to DisplayComponents and AdapterActions to CommandButtons .
Apart from the TAdapterPageProducer , which is the WebSnap-specific PageProducer , we can also select a regular TPageProducer , a TDataSetPageProducer (both inherited from WebBroker), a TInetXPageProducer (from InternetExpress), and finally a TXSLPageProducer , which uses XML and XSL. However, it's the TAdapterPageProducer that can work with TAdapters “ ”the core of WebSnap.
Enough theoretical overview already, let's return to WebSnap and cover Login, Sessions, and the final WebSnap application combining everything together.
Top |