ROGER SEWELL
Roger's origins in programming lie in a small room in a Leicestershire school, where he spent many a happy hour punching out tape on a teletype terminal before connecting to a mainframe via an acoustic coupler modem and finding that his program didn't work. Between then and the start of his Visual basic programming career, he spent his time in the murky world of mainframes bashing out Fortran programs for scientists. Roger first saw the VB light in early 1994 and hasn't looked back since. Roger lives in Oxfordshire with his wife Kath and their young family. When not playing or watching sports Roger fights a losing battle against the jungle growing around the house.
When I first fired up Microsoft Visual Basic 5 (yes, I did say Visual Basic 5), I was surprised to be presented with a box asking me what type of project I wanted to develop. I was even more surprised to find that there were nine project templates to choose from-who would have thought that little old Visual Basic would grow into such a multitalented individual? Since that day I have become accustomed to the variety of development options given to us by Visual Basic, and now Visual Basic 6 offers us three new templates: Data Project, IIS Application, and DHTML Application.
I'll examine the IIS Application in this chapter, going through the process of developing a simple application for Internet Information Server (just in case you hadn't worked out the acronym).
This template and the new features embodied in it are intended to give Visual Basic developers the opportunity to develop Web applications without leaving (too often) the environment they know so well. I hope I'll be able to give you a feel for the development process, because it is different from the process of a normal Visual Basic project. I also want to get you thinking differently about how your application should be structured and how your users will interact with your application, because these design issues are probably the biggest change that you as a developer of a Web application (many such applications, I hope) are going to face.
Before I go any further, I ought to explain just what I mean by a "Web application." A Web application is an application that runs on a Web server and is accessed at the client end using an Internet browser program or other program with Web browsing facilities. In this model, all the processing in the application is performed on the Web server and the client receives HTML-coded pages that contain the user interface and client data. Of course, real-world applications contain a mixture of server-side and client-side processing. Browsers can download Microsoft ActiveX components and Java applets to add richer functionality to the interface of the application. Web pages can contain scripting code to run at the client end to provide further flexibility in the front end and preprocessing of data and requests for the back end.
The Web application model offers the prospect of a single client front end that is capable of accessing a variety of different applications on a remote server. While this front end might not be the thinnest client in the world, it can be a fairly universal client. This client could also be updatable remotely. If it doesn't have a particular capability required by an application (such as the display of a particular format of data), the client could download a component that it can use to give it that capability. Similarly, the versions of components the client already has could be checked to ensure that they are always up to date.
A Web application in the corporate intranet obviously is attractive for a variety of reasons. By having a single client application for all server applications, rollouts are simplified and client PC maintenance costs are reduced. Standard machine setups can be used with the client gradually updating itself as it accesses different applications. In the corporate environment, where there can be tight control over the software on a user machine, applications can be produced for a specific browser, thus allowing developers to fully exploit the capabilities of that browser. Web applications also allow people to work from home or away from their normal office location without losing functionality.
Developing applications for the Internet means you have a huge audience that can access your work. Unlike the corporate intranet environment, you can no longer assume that all browsers accessing your application will have the same capabilities, but this is by no means a barrier to deploying applications over the Internet.
Before the IIS Application template was introduced to Visual Basic, developers wanting to produce Web applications had Active Server Pages (ASP) technology available to them. The ASP model allowed developers to write pages that could be accessed from a browser and that performed some processing on the Web server before returning HTML to the browser. The server-side code could be written in a variety of languages (including client-side scripting languages, such as VBScript or Microsoft JScript), so long as the server had access to a scripting engine for that language. ASP provides a number of different objects for server scripts that allow interaction with both the client and the server.
IIS applications, while based on ASP, provide a better way for Visual Basic developers to produce Web-based applications. For example, the development environment is familiar (though there are differences for IIS application development, as you'll see). The language is the same, so you don't have to learn a new scripting language. The processing code and visual interface code can be separated out to provide a cleaner project-ASP pages have script and interface code intermingled. Visual Basic is also a much more powerful language in which to develop applications than is a scripting language (even if the scripting language can call on code components to perform any tricky processing).
At the time of this writing (on the March beta of Visual Studio 6), there is some MSDN documentation on developing IIS applications but no example code (apart from the fragments appearing in the documentation). So, while I'm not flying completely blind on this one, let's say there're some low clouds and all I have are the instruments to guide me (plus a sick bag and spare underwear!).
OK, so what do you need to start developing an IIS application? Even if you don't run your application you'll still need the Microsoft Active Server Pages Object Library, ASP.DLL. This is included in the project references in the IIS Application template, and one of its objects (the Response object) is used in the template code. However, a Web server that supports ASP is required to run your application. The Microsoft choices for development Web servers are shown in Table 3-1.
Table 3-1 Web Application Development Servers
Operating System |
Development Web Server |
Windows NT Server 4 |
Internet Information Server |
Windows NT Workstation 4 |
Peer Web Services |
Windows 9x |
Personal Web Server |
You can use any of these servers during application development, but you must use IIS for deployment.
Now that we have discussed IIS applications in general, let's try developing one of our own. First we'll see what the IIS Application template gives us for free. Then we'll develop a home page for our application and add further extensions to our home page to increase its usefulness to users and to ourselves.
Assuming you've installed and set up your Web server, the next step is to fire up Visual Basic 6. Select New Project from the File menu to display the New Project dialog box, and then select the IIS Application template to start developing your new application.
Right away you'll notice something different-the Project Explorer window contains a folder called Designers in the project tree. Designers, which act as hosts for a particular type of object, appeared in Visual Basic 5, although none of the templates supplied with Visual Basic 5 used them. Designers could (and still can) be added to a project by selecting Components from the Project menu, choosing the Designers tab of the Components dialog box, and then checking a designer in the list. Designers have features that enable the development of particular objects within the Visual Basic integrated development environment (IDE). In Visual Basic 5, two designers came as standard components; now there are seven. IIS Applications use the WebClass designer to develop WebClass objects. Each IIS application contains at least one WebClass object.
The IIS Application template provides you with a single item in your new project; a WebClass object named WebClass1. Even at this early stage your project is in a state where it can be run (and can demonstrate the fact that it is running). Clicking the Start button on the toolbar (or using any of the other methods to start a project in the IDE) brings up a scaled-down version of the Project Properties dialog box with only the Debugging tab visible. This allows you to specify which WebClass component you want to start the application with in an IIS application. This dialog box also contains a Use Existing Browser check box, which, when selected, will launch the application in a browser that's currently running. If this option is not checked, Visual Basic will launch Internet Explorer 4 to act as the client for your application. Even if Internet Explorer 4 is not your default browser, Visual Basic will still launch Internet Explorer 4 (and then ask you if you want to make it your default browser). The options available when you start the project in the IDE are shown in Table 3-2.
Table 3-2 Project Debugging Options
Startup Option |
Possible Use |
Wait For Components To Be Created |
Simulates a more normal method of operation, where the application is already running on a Web server and waits for browser requests |
Start Component |
Opens browser and automatically accesses the specified component |
Start Program |
Accesses the application using a different browser or a program with browsing capabilities |
Start Browser With URL |
Accesses a particular part of your application or a page with a link to your application |
Once you have chosen your preferred options from this dialog box, you will be prompted to save your project and its files. In an IIS application the directory where you save your project has a bit more significance than normal since this is where the temporary files created at run/debug time will be placed. It is also the same directory where the HTML template files used in the application will be stored. When your application is deployed on a Web server, the directory structure used for development will be mirrored in the production directories, the only change being to the root directory for the application. As far as IIS is concerned, all directories stemming from a virtual root directory are part of the same Web application, unless they themselves are the virtual root directory for another application.
Once you've saved your project files, you'll be prompted for the name of a virtual directory that the Web server should use to host this application during development. When you deploy your application on your production Web server, you'll be able to specify into which directory you want to place your application files. You'll also be able to specify which virtual directory you want your Web server to associate with the physical application directory. The virtual directory name will form part of the URL that browsers use to reference your application.
Finally, after selecting a name for the virtual directory, your application will start. To see your application running, you'll have to switch to a Web browser. If you've chosen to start with a particular Web class, the focus will automatically have been transferred to a browser. If you have not yet entered any code, you'll be greeted by a Web page with the heading "WebClass1's Starting Page."
It's worth taking a moment to have a look in the project directory for the application. In addition to seeing the Web class designer files and project files, you'll also see that an ASP file has been created. During development, this is a temporary file that gets created whenever you start a debug session for your application and is destroyed when you finish the debug session. If you examine this file in Notepad, you'll see that this ASP file (WEBCLASS1.ASP for the default project) contains the following code:
<%This is an ASP script (as shown by the script delimiters <% and %>) that uses the ASP Server and Response objects and creates an instance of our Web class. From this script, we can see that our IIS application is a single-page ASP application that simply runs an instance of a single object. Normally, as already mentioned, an ASP application would be made up of ASP files containing a mixture of script code to be processed by the Web server and HTML to be returned to the browser.
If we now shut down the browser and return to Visual Basic, we see that the application is still running. The temporary ASP used to access our application is still in existence, so we can start the browser and run the application again. We can even connect to our application from another computer if the Web server has been set up to allow access from that computer. You must close down your application from within Visual Basic, which causes the temporary ASP file to be deleted and thus denies access to your application.
So that's the Web application equivalent of "Hello World" done without writing even a single line of code! (As far as "Hello World" applications go, a Web application is likely to greet more of the world than a C application or a Visual Basic application.)
If you want your IIS application to do anything useful, now is the time to get familiar with HTML. There is no getting away from HTML in a Web application-without it you have no user interface to your application. You can distance yourself from HTML to a certain extent by having someone else design your Web pages/client interface for you, but this will probably feel alien to the majority of Visual Basic developers who are used to dragging controls from the toolbox and designing their own forms.
Using HTML to design a user interface harkens back to the days when visual elements were created by writing code that had to be executed before the developer could see what they actually looked like on screen. However, plenty of applications allow you to design your Web pages in a visual way and then generate the underlying HTML for the Web page for you automatically. An understanding of the HTML behind the page is at least useful (if not essential) for effective Web application development, because it is the HTML in your user interface that furnishes your application with events that it can respond to.
You can include HTML in your application in two ways. The most flexible technique (and the most laborious) is to include raw HTML code in your procedures. You will already have seen this approach if you've examined the code supplied by the IIS Application template. Here is an example that uses the Write method of the ASP Response object to send text to the browser:
Response.Write "<HTML><BODY>Hello World!!</BODY></HTML>"The other way of including HTML in your application is to add HTML files to your Web class through an HTML template. When an HTML template is added to a Web class, Visual Basic takes a copy of the underlying HTML file and stores the copy in the project directory. The HTML template is referenced in the Web class by the Web item name that you assign to it when it is added to the Web class.
When adding HTML templates to a Web class, the normal default naming convention of Visual Basic is followed, meaning that the item type name is suffixed with a number that makes the name unique. While this is fine in most cases, it would seem more sensible, when adding HTML templates, that the name of the original HTML file be used to refer to the template. The copies of the files held in the project directory maintain their original names (with the addition of a numeric suffix if a file of the same name already exists in the project directory), so why not default to these names in the IDE? So, when you add an HTML template to a Web class, change the default name to that of the HTML file it represents (remember to check the project directory to see if the name has been changed).
The HTML file is now in the Web class, but no one will get to see it unless the Web class is told when to display it. An HTML file is sent to the browser when the WriteTemplate method of the HTML template is called within code. This can be done from the Start event of the Web class but is better placed in the Respond event of the HTML template Web item. The Respond event is the default event of any template and is called whenever the template is referenced without a specific event procedure. To reference the HTML template in code, the NextItem property of the Web class is set. At the end of processing an event in a Web class, if the NextItem property points to a Web item, processing is transferred to that Web item. This is the statement to place in the Start event of the Web class in order to have the template displayed in the browser:
Private Sub WebClass1_Start()In the above code, when the Web class starts, the HTML template named Welcome is sent to the browser requesting the Web class's ASP.
An HTML template is able to trigger events within a Web class when the template is processed by a browser. When an HTML template is added to a Web class, its underlying HTML file is scanned for tags that have attributes that can take a URL as a value. If an attribute can have a URL for a value, it can send HTTP requests to the Web server, which can be intercepted by the Web class. The Web class can intercept these requests only if the tag attributes are connected to events in the Web items of the Web class. The connection of attributes to events is performed in the right-hand pane of the Web class designer. Attributes can be connected either to a custom event or to a Web item by right-clicking a tag in the designer and choosing one of the options presented. If the attribute is connected to a custom event, the designer automatically creates a new event for the template containing the tag. Default event names come from the tag they are connected to (combined with the name of the attribute if the tag has multiple attributes that can be connected to events, as shown in Figure 3-1).
Figure 3-1 Web class designer showing custom events
If you change an event name (using the same techniques as in Windows Explorer), it is automatically updated both in the Target column of the Web class designer and the HTML Context column, but only for that tag-attribute combination. The update is not shown in other HTML Context entries belonging to the same tag until the template is refreshed in the designer. Also, if any code has been written for a custom event and the event's name is changed, the code becomes disassociated from the event and exists as a general procedure in the Web class (as happens when renaming a control in a form-based Visual Basic application). The names used for tags in the designer come from the tags themselves unless an ID or Name attribute has been set for the tag (with the ID attribute taking precedence).
Now we have a page to display when a user connects to our application. Nothing very exciting, and just maybe our visitors will want to tell us this. Being well-adjusted individuals who aren't afraid of what people might say about our work, we'll include a guestbook in our application. (See Figure 3-2.) We'll store the comments in a database and display the five most recent ones whenever anyone accesses our guestbook. We need a place for visitors to enter their comments, a mechanism for them to register their comments, and a space to display previous comments. To be helpful, we'll provide a way of clearing the comment box.
Figure 3-2 Guestbook Web page
Although the guestbook appears to be a single Web page, it has been created from two separate Web items. Everything above the horizontal rule comes from an HTML template called Guestbook that we have added to our Web class. The horizontal rule and the table below it come from a custom Web item called RecentComments. A hypertext link has been placed on our Welcome page. A connection has been made between the HREF attribute of the hyperlink and a custom event of the Welcome template, which we have called DisplayGuestbook. This custom event simply sets the NextItem property of the Web class to the Guestbook template and relies on the processing in the Respond event of the template to provide output to the browser. The Respond event for the Guestbook template sets the NextItem property to the RecentComments custom Web item before calling its own WriteTemplate method. At the end of the Guestbook template's Respond event, processing passes to the RecentComments custom Web item's Respond event. In this second Respond event a private procedure, GetComments-which is defined in the Web class, not in a Web item-is called to dynamically generate an HTML table definition containing the previous five comments. This table and a horizontal rule used to split the screen are written directly to the browser using the Response object of the Web server. The GetComments procedure uses ActiveX Data Objects (ADO) code to query our guestbook database. The query returns the comments to display in the Five Most Recent Comments table.
When the user has entered a comment, he or she clicks the button labeled Submit Comments to submit it. When this button is clicked all the responses generated by the form are gathered together and sent back to the server. Although individual input elements, like buttons or the comment text box, are not listed in the Web class designer, the form that contains them is listed in the designer. By connecting a custom event to the Form tag of the Guestbook template, we can program a response to the visitor submitting comments. Input controls in HTML are contained within sections called forms. The three attributes of forms that primarily concern us as IIS application developers in Visual Basic are: the ID attribute, which sets the name under which the form will be listed in the Web designer; the Action attribute, which we will be connecting to in order to trigger our response; and the Method attribute, which sets the mechanism by which data is sent from the browser to the server. For IIS applications written using Visual Basic, POST is the only value for the Method attribute that we can use. If we try to include an HTML template containing a Form tag with the Method attribute set to GET (or even without the Method attribute at all), the Web class designer issues a warning message (as shown in Figure 3-3) and tells us what it is going to change in our template.
Figure 3-3 Warning message issued by the Web class designer
When the POST method is used, data is received by the server in the Form collection property of the Request object. Each element of the Form that generates data creates a member in the Form collection using the element's Name attribute as its key in the collection. The data returned by each element is held in the Item property of each collection member. Since this is the default property of the collection, we can determine if the SubmitComments button was clicked using the following piece of code:
If LCase$(Request.Form("submitcomments")) = "submit comments" ThenThe value returned by this type of button (a Submit button) is always the same as the text displayed on the button. If the button had not been clicked, there would be no member of the Form collection with the key "submitcomments." Having received the visitor's comment about our site (in the member of the Form collection with the key "comments"), we then store the comment in our database. Another procedure called AddComment takes care of this; again, this is a private method of the Web class. The visitor remains on the Guestbook page, which has the list of recent comments updated to reflect the visitor's newly added comment.
We have a starting page for our Web application and we have a guestbook that users of our application can write comments into, but we don't as yet really have an application. How about we use our application to provide a series of technical articles, say, a whitepaper distribution application? Now, we at TMS have invested considerable resources into creating these whitepapers, so we don't want to give them away to all and sundry with no return whatsoever. So we'll provide summaries of all our whitepapers that anyone can access but will require users to provide us with some information before they can access the full text of any of the whitepapers.
To accomplish this, the first thing we'll have to do is alter our Welcome page. At a minimum, we need to describe the application so that users know what they can expect. We also want to differentiate between anonymous users who don't want to register and those users who do. Repeat users will probably want to sign in on the Welcome page and have full access to the application from then on. New users will probably want to view some of the whitepaper summaries before parting with personal information. This means that we'll have to have the facility to dynamically disable some of the features of our Web pages. We'll also want to be able to access common Web pages (such as the Registration page) from multiple locations within the application. Having obtained personal information from users, we might feel inclined to make them more at home by customizing the pages presented to them, too.
We've redesigned our Welcome page to be more descriptive of the application, added some graphical navigation buttons, and increased the number of options that a user has on this page. (See Figure 3-4.)
Figure 3-4 New Welcome page
Graphical navigation buttons were used partly for their visual appeal (even done as simply as this!) but they were used mostly because each graphical button can trigger an event individually. This is because the buttons actually are graphical hypertext links whose HREF attributes can be connected to custom events (or Web items) if we choose. (They are not Input tag controls wrapped inside Form tags and therefore don't have to be accessed through the Request object's Form collection.) The HREF attribute of each of the buttons references the corresponding HTML template (SignIn, Guestbook, and so forth). The Respond event in each of these templates simply calls the WriteTemplate method of the template to display the HTML page in the browser. So the only new feature in the Welcome template is the use of graphical buttons instead of straight text links or "proper" input buttons inside an HTML form. The guestbook itself remains the same, but there is more to comment about in the application, so it serves more of a purpose!
The Registration page is new, but the techniques behind it aren't. A single form contains all the input fields. The data entered on the page is returned in the Request.Form collection. To handle the registration of users in our WEBAPP.MDB database, we have added a class module to provide us with a CUser object. This class has properties that match the information we want to capture about our users. The CUser class also has a method, RegisterUser, which adds the data held in the properties of a CUser object to the database. This method has a return value of True if the user was successfully added to the database (the value is otherwise False). Armed with this information, we can control what happens next. If the RegisterUser method fails, we want to redisplay the registration form to allow the user to re-enter their details. If the user was successfully added to the database, several things should happen. First we ought to move the user to a different area of the application, away from the registration form, maybe by sending them back to the page where they jumped from to get to the registration page. Alternatively, we could send them to a fixed page of our choosing, perhaps with a "Thank you for registering" message. To make our application more welcoming, we also want to personalize the pages that we send back to users who have signed in.
Now that we have more pages in our application, we've decided that we want to use the same toolbar on several of those pages. To this end we've created a separate template called Toolbar which duplicates the functionality of the Welcome page toolbar. The next task is to edit the Welcome template to remove the section of HTML connected to the toolbar buttons and allow Visual Basic to refresh the template in the designer.
Finally we need to add code to display the Toolbar Web item at the bottom of the Welcome page. We could use the following code in the Respond event of Welcome:
Welcome.WriteTemplateThis does the job of putting the buttons at the bottom of the page, but it is not the code we are going to use. The WriteTemplate method can take the name of another template as its only argument, so it would seem that we could use this code as an alternative:
Welcome.WriteTemplateIf we try this code, however, we find that instead of getting buttons at the bottom of our page we get only another copy of Welcome displayed. (See Figure 3-5.)
Figure 3-5 A doubly warm Welcome!
Toolbar.WriteTemplate Toolbar works as we would expect (perhaps "hope" would be a better word to use), which suggests that the template argument to a WriteTemplate call is ignored. However, we'll use this code:
Welcome.WriteTemplateWhy use this technique? Because accessing the Toolbar via the NextItem property of the Web class ensures that the Respond event of Toolbar fires, which won't happen if we use the Toolbar's WriteTemplate method. This way, any extra processing we specify in the Respond event is applied before the template is sent to the browser.
Now that the Toolbar Web item has been added to the Welcome page, we'll add it to the Summary page, too. This page is much more interesting, both in terms of HTML construction and also in the Web class and Web item features used. The template used to construct the Summary page is called SummaryLayout. The HTML file this template is derived from uses frames to enable different sources to be used for the content of different areas of the screen within the browser. The following fragment of the original HTML file
<FRAMESET ROWS="25%,50%,25%">produces the event candidates shown in Figure 3-6 when parsed by the Web class designer.
Figure 3-6 Event candidates for SummaryLayout frames
Now the question is, "Why have we designed the Summary page like this?" After all, if we wanted three different blocks of HTML code outputting to the browser, we could have strung three Web items together to produce the output. We've structured this part of our application like this because of the features we want it to provide to our users (as will become clear later).
Since we already have our Toolbar template written and in place, we'll connect that to SummaryLayout first. We want it to be displayed at the bottom of the page, so we connect the Toolbar Web item directly to the SummaryToolbar tag that is the source for the bottom frame of the page. (See Figure 3-7.)
Figure 3-7 The Connect To WebItem dialog box
Fatal Errors in a Web Class
In a Web application, errors can occur outside of the Visual Basic code. In such cases, traditional error handling techniques (such as those discussed in Chapter 1) are not available for handling the situation gracefully. Instead, you can make use of the FatalErrorResponse event of the Web class. This has a single Boolean argument, SendDefault, which is an output argument. By setting SendDefault to False, the default error message is prevented from being shown in the browser. By using the Response object, you can send your own text to the browser to explain to the user that there has been a problem. The Web class provides an Error object that you can query to determine the Source, Number, and Description relating to the error. Such information can be written to the browser or logged to a file as necessary. On Windows NT 4 systems, the error is also written to the Application Log, where it can be examined in the context of other errors.
There's no problem with the article list in the top frame of the page. We'd always intended this to be generated dynamically in a custom Web item, called WhitepaperList. This Web item generates the list of available whitepapers and formats the list to make best use of the space in the top frame of the page. The names of the whitepapers are presented as hyperlinks so that clicking them sends a request to the server for the whitepaper summary. In HTML, frames can be used as targets for page requests if the frame is given a name. We've done this for the middle frame so that when the browser requests the whitepaper summary from the server, the summary is displayed in the middle frame upon receipt by the browser.
To produce a server request specific to the whitepaper that the user has selected, we use the URLFor method of the Web class and the UserEvent event of the SummaryView custom Web item we've created for displaying whitepaper summaries. The URLFor method generates, at run time, a URL either for an existing Web item event or for a run-time event. The arguments for URLFor are an existing Web item (which is required) and, optionally, the name of an event to fire in the Web item. If no event name is supplied, the Respond event will be fired if a request is made with this URL. If an existing event's name is used, that particular event will be fired in the Web item. The advantage of this method is the ability to specify an event that does not exist at design time-a run-time event:
The hyperlink defined above appears as "Whitepaper 1" in the browser and when selected will send a request to the server containing the URL for the "Whitepaper 1" event in the SummaryProcessor Web item. Since this event does not exist at design time, the UserEvent event procedure of the SummaryProcessor Web item is fired. A single argument is passed into the UserEvent event procedure that is the name of the run-time event that was triggered. This technique is well suited to presenting our whitepaper summaries, since it allows us to pass a request for the whitepaper into an event that we can use to send the summary back to the browser.
To generate the Summary page we make use of the ProcessTag event, the only standard event of a Web item that we haven't used yet. This event is fired automatically when the WriteTemplate method of a Web item encounters replacement tags in the template's HTML. We could generate dynamically the HTML to send back to the browser in the UserEvent of the SummaryProcessor Web item. However, because the format of this page will be static, with only its content changing, we're using a template Web item with certain areas replaced as each whitepaper is requested. The template will display the whitepaper name and (obviously) the summary, so we insert placeholder tags into the template at design time, which are replaced at run time. Our template contains the following HTML code at a place where we want the whitepaper name to be displayed in the browser:
VB6 Book Sample Web applicationWhen the WriteTemplate method for this Web item is called, the WC@WHITEPAPERNAME tags in the template trigger the ProcessTag event of the template. This event is fired once for each pair of tags, which allows the text between the tags ("Whitepaper Name" in this case) to be substituted by whatever text is required. The same pair of tags is used throughout the template in areas where the whitepaper name is required. The whitepaper summary is replaced using the same technique. Tags are recognized as replacement tags because of their starting prefix; the TagPrefix is a property of each Web item, which is set to WC@ by default. If this prefix is changed, the new prefix should contain at least one character that is unlikely to appear elsewhere in the HTML generated by the Web item. This reduces the risk of ordinary HTML or text being processed as a replacement tag. The code used to perform the replacements is quite simple:
'Depending on the tag being processed, substitute either the whitepaperBoth TagName and TagContents are passed into the event. The two variables used to replace content are set in the SummaryProcessor_UserEvent event procedure that is the target of all the whitepaper hyperlinks in the top frame of the Summary page.
Now we're at the point where we can display summaries of our whitepapers to users of our application, but we haven't included a mechanism for displaying the full text of our whitepapers. This can easily be done by including a hyperlink (in the form of a button, perhaps), which will request the file containing the whitepaper. As we've already stated, we want users to register (or sign in if they have previously registered) before we allow them access to the full text of our whitepapers. This being the case, we should probably display a message to that effect if the user requests a whitepaper summary without having signed in. Because we are already using text replacement tags in the SummaryView template, we'll use the same technique to place either a hyperlink button or a message in the whitepaper summary section of the page.
OK, so we know what we're going to make available as replacement text in the ProcessTag event of the SummaryView Web item, but how are we going to decide what text to supply? By adding to the functionality of our CUser class, we expose a SignInUser method and SignedIn and FailureReason properties. This method and these properties let us sign in a user to the application, find out the reason for failure if they were not accepted (as shown in Figure 3-8), and also check to see if they have already been signed in.
Figure 3-8 Failed user sign-in
To make the information from the CUser object available throughout the Web class, we define an instance of the CUser class at the Web class level. We create the CUser object in the Web class Initialize event (and to be tidy, destroy it in the Terminate event) and set and query its properties and methods throughout the Web class, right? If we try this approach, what happens?
Well, we can sign in to the application and be taken to the whitepaper summary page without a problem. However, when we display a whitepaper summary, we find that the information from our sign-in has disappeared and that we are asked to sign in before being able to view the full text of our whitepaper. The problem we're facing is one of application state. Unless we do something to prolong the application lifetime, each request the browser sends to the server causes an instance of the application to be created when the HTTP request is received, and causes that instance of the application to be destroyed once the HTTP request has been completed. Thus, during the sign-in process, our CUser object accepts the sign-in and sets its SignedIn property to True. When the request arrives to display a summary article, the previous instance of CUser is long gone and we access a new instance that has no knowledge of our previous sign-in. What can we do about this?
The easiest change we can make is to set the StateManagement property of the Web class to keep the Web class alive between requests. StateManagement can be set to wcNoState (the default) so that the Web class is continually created and destroyed as requests come in from the browser. The wcRetainInstance setting, however, keeps the Web class alive between requests. Once the StateManagement property of the Web class is set to wcRetainInstance, we can sign in to the application, choose a whitepaper summary, and be presented with the opportunity to view the full whitepaper. If we look at the temporary ASP file created when we start a debugging session of our application, we can see how this property change has affected the file:
<%The difference is that the ProcessRetainInstanceWebClass method of the WebClassManager object is used instead of the ProcessNoStateWebClass method. The ProcessRetainInstanceWebClass method has an additional parameter ("~WC~BookWebApp.BookWebClass"), which is the name of the session that should be kept alive. Subsequent accesses to the application by the same user utilize the existing Web class instance by retrieving a reference to it using the same session name. Using this mechanism to maintain information between requests relies on the browser accepting cookies from the server. The server sends the name for the session as a cookie to the browser when it first accesses the application. Subsequently, whenever the browser accesses the application (until the user terminates the browser), it passes the session name cookie back to the Web server. This is how the server knows which session to associate with the request. If the user of the application has set his or her browser to refuse cookies, no session name information can be passed as a cookie. In this situation, even though we've set the StateManagement property of the Web class to wcRetainInstance, the server will generate a new session for the browser because it has no information that the browser has previously established a session on the server.
The same problem arises if we use the Session object directly from within our application-the browser cannot be associated with a session without accepting a cookie. If the Session object is available to us, we could store a user object in it to maintain our sign-in information. Alternatively, we could simply store a Boolean that gave the SignedIn state in the Session object.
We can read and write cookies directly from our application by using the Cookies collections of the Response and Request objects. We can control the existence of the cookies we write by setting the Expires property. This means that, unlike the Session object, we can keep information alive after the browser has been terminated so that the information can be used the next time the browser is started and our application accessed. Cookies that stay alive like this are stored permanently (until they expire, that is) on the user's hard drive, so even if the user has accepted a cookie, there is no absolute guarantee that it will still be there the next time the browser program is run.
Another mechanism that can be used to transfer data back and forth between the server and browser is to set and query the URLData property of the Web class. This property works by storing extra information with URLs written in pages that are sent out to the browser. If any of these URLs are activated in the browser and initiate a request on the server, the URLData property of the Web class is set to reflect the data that is sent back.
We've investigated many of the features available to Visual Basic developers who want to (or have to) develop Web applications. In the process, we've produced the skeleton of a functioning application-nothing to set the world on fire, but it's a start nonetheless.
This IIS Application template allows Visual Basic developers to use existing skills to create Web applications. However, to really start developing Web applications, developers should have a good knowledge of HTML, even if they don't have to write the code that is displayed in browsers. A knowledge of HTML will help Visual Basic developers get the most of the limited interaction between browser and server. Web developers also need to understand and control the lifetime of their applications and the data they rely on for operation. This definitely needs more careful consideration than for a standard Visual Basic project. Knowledge of ASP will also stand Web developers in good stead, since Web applications created with Visual Basic are based on this technology. The core objects within a Web class (Request and Response) are ASP objects, which is certainly a good reason to learn about ASP.
To produce powerful Web applications, the developers will almost certainly have to move away from a purely server-based application with the thinnest of clients and incorporate client-side scripting, DHTML, ActiveX components, and so forth, in their overall application code. This adds even more to the areas of knowledge that Visual Basic developers must enter.
No doubt that Visual Basic 6, with its IIS Application template, will kick start the development of many Web-based applications.
|