Component Software for Business

Total Page:16

File Type:pdf, Size:1020Kb

Component Software for Business

Database Development for the World-Wide-Web

Introduction

The Internet is a well-established fact of life, and while a lot of the Internet’s content comes in the form of ‘static’ web pages composed of text files in HTML format and images, our interest is in the methods that we can use to publish data from database tables on web pages. Web sites that derive their content from database files are often referred to as ‘dynamic’ web sites because if any of the data in the source database is changed (new data added, existing data deleted or updated), the next person to access the web site will see these changes immediately. Dynamic web sites are created by producing programs or scripts that generate the web pages on demand. While this may initially seem like a very wasteful use of computer processing power since there may be long periods during which the data does not change and yet the web server continues to slavishly re-generate web pages that it has generated many times before, the process of publishing this ‘live’ data on the web is only marginally less efficient that that required to copy existing files of HTML text stored on a disk. In these tutorials, you will discover the basic mechanisms for creating dynamic web sites and by following the included practical sessions, you will gain practice in the techniques necessary to implement dynamic, data-driven web sites.

Practical Issues

If you intend to follow the practical sessions throughout these tutorials, you will need only a few tools to allow you to do so. The first and most important tool is a Web Server: don’t panic, this does not mean you need to go out a purchase a big, industrial strength computer and start negotiating with an Internet Service Provider to provide you with a T2 connection to the Internet. In fact, web servers tend to come free with many computer operating systems, and operate perfectly well for executing web pages with active content for delivery to a browser on the local machine. If you have a computer with a copy of Windows 98, Millennium, 2000 or XP, you will almost certainly have the software necessary to set up a web server. For the practical exercises described here, you won’t even need an internet connection. If you have Windows 95, you can download a copy of Personal Web Server from the Microsoft web site (although of course you do need a connection to the web to do this). If you are running a computer installed with Linux, or an Apple Macintosh, you will also have web server software either already installed or easily available, although it is most likely that the practical sessions described here will not be compatible with your specific system – you will have to access one of the web-sites specific to your own computers, operating systems and web servers to find similar support material.

Web Sites and Web Pages

The Request-Response structure

A Website is a collection of files stored on a computer that is connected to the Internet and organised in a way that allows them to be accessed by any other computer that is connected to the internet and running a Web Browser. The World-wide-web was invented by Tim Berners-Lee, a physicist at Cern, the international atomic research facility located near Geneva in Switzerland. It was devised as a way for computers connected to the Internet to share documents easily, and is based on the idea of Hypertext – textual documents which are interlinked by a system of document references within them. Berners-Lee devised the Hyper-Text Transport Protocol (HTTP) and the Hyper-Text Mark-up Language (HTML) that became the core format for every website. HTTP is a simple system which is understood by web servers. When a request for a document arrives at a web server, the server responds by sending the document back to the address that issued the request – a very simple client-server arrangement not unlike the way database servers respond to SQL. From the client end, the request incorporates the address of the web server and the name and location (actually, a virtual location) of the document on the server. When this request is issued, a large database distributed across the internet (the Domain Name Service or DNS) is used to work out the actual Internet address of the server (a numeric address that locates it uniquely among all of the networked computers in the world) and the request is directed there. Request

Response

Web Browser Web Server Figure 1: Request-Response. The Internet Address of a web page or media file is issued at a browser and received by the web server. The HTML text of the web page is returned to the browser. Typically, the request comes from a Web Browser running on some computer, and is for a specific web page or resource, for example, www.BigBusiness.com/Documents/SomeDocument.html. In this case, the DNS would look up the Internet address for www.BigBusiness.com and pass the request for Documents/SomeDocument.html to it. The very clever part (alluded to by the word Hypertext in the acronym HTML) is that the document can contain text marked up in a special format understood by web browsers, and in particular, is likely to contain the addresses for other web pages. In this way, web pages contain links to other web pages, which may also contain links to other web pages and so on. The world-wide- web is a hugely interconnected network of web pages that refer to each other. This request-response organisation makes it trivially easy to create a web site by simply taking a bunch of documents and embedding inter-links within them at strategic points – a simple example is where index document contains a list of hyper- links to other pages on the site, and these pages contain links back to the index. An easy extension to this is that most web browsers can now display graphical content, and a web page can contain hyper-links to graphics files using the same request-response mechanism. In fact, a current web browser can cope with a large range of different types of content including audio, animations and video, all retrieved by the same request-response method. Static Pages, Server-Side Scripting and Client-Side Scripting

Using simply HTML text files and a smattering of other types of file containing graphics or other information, it is easy to build a ‘static’ website that will provide access to information about you, your hobby or your business. The down side of this is that as the details you wish to display change (obvious fundamental things like your age, which changes annually, or the products your company sells, which may change on a daily or weekly basis), so you need to maintain the files that make up the website to make the information up to date. The way around this is to create your website as a dynamic entity; one in which the information published can be updated automatically because the source material is kept up to date not by you altering the text that makes up the web pages, but by changes made to the source of the material. For example, if you were to display your age on a web page by simply putting a number in the HTML text, this will never change and so you will need to manually change the HTML text every year to keep it accurate. If however, you published your age by having it automatically worked out from your date of birth and the current date (something that is made available by just about every computer operating system), then it will always be correct and you will never need to update the page. If you published your company’s list of products not by simply listing them in a HTML file, but by extracting the product data from your company’s inventory database and sending this data back with some formatting to the browser, again the page will always be up to date (or, at least, as up to date as the source database). This type of publishing, known as server-side scripting, is done by embedding instructions into the web pages stored on the server to calculate or extract the necessary information and format it as necessary before sending it on to the client browser that issued the request. There is a growing variety of ways in which this can be done – programs can be written to generate HTML from data extracted by a database and connected to the web server, usually by placing them is a special directory on the server that is used to host these CGI (Command Gateway Interface) programs. Alternatively special ‘script’ statements can be embedded in web pages that are executed by the web server as it processes the request for the page. The generic name for the second method is Active Server Pages, and describes the general mechanism where the web server is configured to interpret scripted instructions embedded in web pages. Active Server Pages can be written in a variety of languages that can be ‘plugged-in’ to a web server; e.g. JavaScript, PHP, Python and VBScript. We will use the latter in the practical sessions, since this language is similar to the Macro language used in Microsoft Access, and is the standard scripting language for Microsoft web servers.

Active Server Page

The Internet Response

Database Request

Web Server

Figure 2: Active Server pages can generate a ‘live’ response to a web page request Script can also be created to execute in the client’s browser. This client-side script is an efficient way of doing some of the work, but has limitations that make it not particularly useful for our purposes. For a start, you can not publish data from a database that you host on the server by executing a script on the client’s computer; apart from it being an absurd idea (the database is at your end of an internet connection – not the client’s), the browser would not allow such a thing on the basis of security, your web server would need to have been set up to trust scripts run from an anonymous source (a security nightmare), and there would need to be software on either side of the connection capable of maintaining the direct access the client has to your database. For these and other reasons, client-side script is never used to do much more than alter the way that information is presented in the browser, ‘jazz-up’ interactions between the user and the page on the browser or validate information that the user is required to send to the server. Even then, we can never be sure that the browser accessing a web page is capable of allowing script to run, or that if the browser is capable of executing scripts, that the facility has not been disabled. All in all, client-side scripting is a non-starter for publishing data.

Generating a page from a web server

If we have a computer with a web-server running on it, for example Microsoft’s Internet Information Server (IIS), we can create a website by simply adding files that contains some HTML text to a directory that the web server is set up to ‘publish’. For example, the following simple file, placed in a folder that was configured to be published by the web server, would be enough to display a static message on a client’s browser: Static Web Publishing Test Page

Hello HTML

Listing 1: Hello.html – this is a static html file, which would simply be sent from the server unchanged. The text in listing 1 is HTML. Everything enclosed in angled brackets <> is treated by the web browser as ‘mark-up’, special code to indicate something to the browser. The only pieces of non-mark-up text in this listing are the page title (enclosed in ... tags), and some text to be displayed in a heading style (

). This would result in the following display on a web browser (Internet Explorer, or IE) running on any computer connected to the internet:

Figure 3: The Output from Hello.html Note that the web address (shown above the page in IE’s address bar) is given as http://paddington/DreamHome/Hello.html. The Web Server is hosted on a PC that I call Paddington (it is a laptop and I carry it around in a small suitcase – you figure it out), and I have set up a website in it called DreamHome (after the example database in the book). The file was saved to the folder that this website is hosted in with the name Hello.html. Of course, this is a static web page. To make a dynamic page, we need to change two things. First, the page needs to be named with an ASP file extension instead of HTML, so that IIS recognises it as a file containing script that is to be executed, and the page also need to have some script embedded in it.

<%@ LANGUAGE = VBScript %> Dynamic Web Publishing Test Page

Hello HTML: the time is <%=Time%>

Listing 2: Hello.asp – this page contains script code embedded in the html to generate ‘live’ results

Figure 4: The output from LIting 2 – note the display of the time. The significant difference between listings 1 and 2 is that the code in listing 1 will always display the same information, while the code in listing 2 will display information that changes as the time changes. The script ‘tag’, <%=Time%>, indicates a function that will be executed by the server when the page is sent to the client – in this case, the function returns the current time-of-day. Any text in an ASP file that appears within the ‘script tags’, <% and %>, will be directed to the script engine of the server. Provided this text is valid ASP code (i.e. provided it is syntactically correct for the language named at the top of the page – VBScript in this case), the script engine will execute it.

Pages, sessions and applications

A file with an ASP extension will generate a single page of a web site. For a web site to display multiple hyperlinked pages there will need to be a collection of HTML and/or ASP files on the server (it is normal to mix HTML pages and ASP pages on the same site to mix static and dynamically generated pages). The full set of ASP pages is referred to as an ASP Application; all of these pages are designed to operate together to fulfil some specific business purpose. Within an ASP application, there can be some specially named pages – typically Global.asa and index.htm, which have a specific purpose for a web application. With a normally configured installation of IIS, index.htm is the page that someone who points their web browser to the site without giving a specific page name (e.g. http://paddington/DreamHome) would get to. Typically, this page is the home page of a site and should be the ‘welcome’ page, providing links to key pages in the web and acting as a top-level menu. Global.asa performs a different function. This page contains a number of blocks of script (subroutines) that will execute automatically when a website is in use, providing code that initializes (sets-up) the site when it is first accessed, closes down database connections or other housekeeping if it has not been accessed for a while, and sets up and manages sessions – sequences of page accesses from a user of the site.

HomePage.htm LogIn.htm Login.asp CheckCredit.asp

Index.htm

Global.asa Catalogue.asp PlaceOrder.asp ViewOrders.asp

Figure 5: A small active web site, with a mixture of static (htm) pages, acti9ve (asp) pages and application pages (index.htm and Global.asa). The pages link (arrows) to each other to provide navigation through the site and to organize necessary services (e.g. login and credit checking). An ASP-based site typically interacts with many users, effectively doing so concurrently so that at any one time, there may be many different users all currently interacting with any page within the site. The sequence of pages accessed by each user is regarded as a session, and it is useful to be able to track any one user through all of the pages that they visit, either to gather statistics on the use of the site, or simply to save users from having to repeatedly send the same information to the site from page to page.

Session state

Tracking users through a site brings up one problem that is central to the way that Active Server Page websites are designed. Each request for an ASP page will execute some script. In sequence these ASP pages may, for example, allow a user to log-in to the site (to provide them with personalized information, or simply to prevent unauthorized access to restricted facilities), allow them to browse through several pages, perhaps selecting products to add to a shopping cart, and then to continue to a check-out page where the sale can be completed by the user entering credit card and delivery details (see figure 5). The problem is simply that the web application has no ‘memory’ that goes beyond a single page, so there is no simple way to know what stage in a sequence a client is on. Good website design demands this, because there is no compulsion for a user who has, say, added some items to a shopping cart to complete the process by going through the checkout page, or even to stay at the same website. You might think that a way around this would be to keep track of the user as they browse from page to page of the site, gathering information as they go and keeping this information ready for when the next page request arrives. However, as designers of a website, we have no knowledge of, or way of controlling the number of simultaneous users of the site. A site could at any time have zero, 100 or 1000000 current visitors, and if the web server was required to actively track each of these, it could take up a lot of time and memory (or none). For the site to remain efficient regardless of how many current visitors there are, it is necessary for the server to NOT be aware of the sequence of page requests for each and every visitor. However, for it to keep track of the current stage that each visitor to the site is at, the website must have some way of retaining their current status. Well designed web-sites are built to be ‘stateless’ – that is, there is no specific storage of data between sequential visits to active server pages. This makes is difficult to track where in a sequence a user of a site is – have they just logged in or are they proceeding to the checkout? ASP allows a number of techniques to be used to track a user through a site, from the deployment of special ‘Session’ objects which are embedded in each page returned to a client so that they can be retrieved on the next request, to the use of ‘Cookies’ – strings that can be stored in the client’s computer from page to page (or even session to session). We can also use a couple of web programmers’ tricks, such as storing session data in variables hidden in web forms to be passed back and forth between server and client. All of these techniques involve embedding session data in the response to a page request, with the page organised so that the same data will be returned if a link on that page is used.

The Response World- Wide- Web Next Request

Web Server Figure 6: Session state is maintained by sending data back and forth between the server and the browser embedded in the request-response data. The envelope here depicts this session data. All of the methods used to store data between ASP pages are there to save having to store the data at the server, where they could take up valuable space that would limit the number of simultaneous clients that could be serviced. The result is that well- designed web sites are inherently ‘scalable’, meaning that the software imposes no limit on the number of clients that the site can deal with at any one time. Of course there are limits imposed by the hardware the site is running on, the speed of the internet connection that the server has and other factors, but not the ASP website design.

Application state

ASP applications place demands on a web server, and it would be unwise to create a site that subsequently hogged space on the server whether it was servicing any clients or not. Managing session state goes a long way to reducing the load on a server, but a server could easily fill up with inactive ASP sites because each site must maintain a certain amount of information simply to function. A website typically keeps track of such things as the number of current users, page statistics (how many times each page has been visited) and database connections that can be used by a number of simultaneous sessions. Note that while session status multiplies up by the number of current users, application status is effectively one lot of stored data per application (or active website). i.e. the problem of maintaining application data is not anywhere near as bad. Even so, an application consumes some resources, and so it would be useful if we could cut-back on it (or even remove it completely) if there were no requests coming in for pages within it. Global.asa, one of the code files that are automatically associated with a web application, can contain code to perform application housekeeping. A realistic example of a suitable Global.asa file for a website is given later in listing 13.

Development Choices

When we decide to create a dynamic website, we have a number of choices to make – which web-server software, how the site will be hosted, what language to use, how we will write and test the code, how we will arrange the files stored on the server etc. The choice of web-server is one that should be a simple matter of preference – a number of web servers are available for free to install on most PC operating systems. If you are lucky (or wealthy) enough to have a permanent broadband connection to the Internet, or are creating a web-site for a business that has a permanent internet connection and a computer designated as a web-server, you can use whatever combination of operating system and web-server takes your fancy. This is easy for your Internet Service Provider to manage, because since you host all of the website and server facilities on your own computer, they need only provide a path to your PC from the Internet. Also, the risk of a badly designed site causing a server to crash, or worse, be open to malicious access from the community of Internet crazies, is yours to take and will not seriously affect the ISP or their other clients. If you have a dial-up internet connection, you will be restricted in how you create your active website (with some Internet Service Providers [ISPs] you may not be allowed to host an active website at all). ISPs often provide a restricted range of facilities for hosting dynamic websites, limiting your choice of database (if any), scripting language and configuration options. The reason for this is simply that with a dial-up connection, your entire website resides on the ISP’s own servers, and when a script is executed it runs on the ISP’s server, so you can only use those facilities the ISP has decided to install on their server machines. ISPs also have to restrict what your scripts can do on the server to ensure that they do not leave themselves open to malicious attack, and some find that the safest approach is simply to not host such business. Fortunately, you are free to choose among many ISPs, and so there ought to be a good range that provide the facilities you need to operate your site. In the practical sessions, we will be going down a decidedly Microsoft route. The server you will write script for is IIS (or PWS, which provides very similar facilities), the database you will write code to interact with will be Access, although you will find that the code you create will also work well with a SQL Server database, give or take a minor configuration change or two.

Tools

Once you have mastered the basics of writing ASP code, you will also be able to choose which tools you make use of to build the website. However, in these early practical sessions, we will use a very minimal toolset – a copy of Microsoft Access (for creating the database and checking the results of our ASP endeavours), and a simple text editor (Windows Notepad will do at a pinch). Microsoft FrontPage is a good application program for developing ASP websites (or static ones for that matter), providing good facilities for testing page behaviour, highlighting code syntax (by colouring the HTML/ASP text), different ways of viewing a page of a website or the structure of the whole site, and some tools that make it easy to insert some of the more complex HTML mark-up elements into a web page. FrontPage also allows databases tables to be inserted into a web page quickly, without the need for ASP script. However, the built-in database facility only allows simple data from a specific table or query to be inserted, and does not allow the creation of more complex data management pages. In these tutorials, we’ll use ASP to provide as much flexibility as we can.

IIS – Installation Issues

If you have a computer that runs either Windows 2000 or XP professional, you are likely to have Internet Information Server installed already. If it is not installed, you will need to run the Windows Setup program from the CD-ROM that your operating system was supplied on, and select the option to install IIS – currently this option appears on the Internet section of the Tools page of the setup program. Different versions of the Windows operating system do not include a copy of IIS. Windows XP home does not include a web server at all, although Windows 98 and Millennium (ME) come with a copy of Personal Web Server (PWS), which is effectively a cut-down version of IIS that has all of the capabilities that we need for developing websites. Consult the manuals or help files of the CD to find out how to locate and install the web server with these operating systems. Once you have a web server installed, you will need to create web sites on your computer to place your ASP code in. In IIS and PWS, creating a website is a simple matter. To create a new site in IIS on a Windows XP machine: 1. Select StartAdministrative ToolsInternet Information Services 2. In the tree view on the left of the IIS display, right-click on Default Web Site, and select New…Virtual Directory from the context menu that pops up 3. Follow the directions of the New Virtual Direction Wizard to set up a site within your web server. The steps are: a. Provide a name for the virtual directory – this will become the root name of the site your are creating (e.g. Dreamhome) b. Type or (more likely) browse to a folder that will house the files on the virtual directory. In a standard IIS installation, it is expected that you will place the files in a folder off C:\Inetpub\wwwroot. You can place the files in a different folder or on a different drive if you wish. c. Select the required settings for file access for your web page files from the Internet. The default is Read and Run Scripts, and this is a very sensible default. You are best to have a very good reason for choosing other settings for this, since you may be allowing hackers to gain access to your hard disk if your website is every published across a broadband connection d. Press the Finish button at the last stage of the wizard. You now have a root folder for a named website. 4. At this stage it is useful to test the website. Drop a very simple HTML file or ASP file into the root folder you created (e.g. in C:\Inetpub\wwwroot\MySite) – listing 1 or 2 (later) are ideal for this. You should now be able to access these files via the web server as follows: a. Run Internet Explorer b. Enter http://MyMachine/MySite/Hello.asp into the address bar and press enter. Of course, you should replace MyuMachine with your actual PC’s name, and MySite with the name you gave the virtual directory. Alternatively, you can use http://localhost/MySite/Hello.asp since the name localhost is reserved to refer to the web server that resides on the local computer (the one that you are running the browser on). Note that the localhost name will only work from the local computer, and browsing from any other machine will require the actual server name. The result (with Hello.asp from listing 2) should be a page that displays a message and the current time. This last part is important – if the time is not displayed, you have typed up the ASP file with an error in it, or your server is not executing the script properly. Fix this now, before you go on to try to create any other active web pages.

ADO

Before we move on to examine the ways we can move data between web pages and a database, a quick recap of ActiveX Data Objects, or ADO, will be useful. ADO is a database access layer developed by Microsoft using ActiveX. ActiveX is no more than a marketing term used by Microsoft to describe their component-based object technology COM, or Component Object Model. The term ActiveX has generally been unpopular with developers, and even Microsoft employees have been known to explain that the ‘X’ is silent in Active(X) Data Objects. ADO is a simple API (Application Programmers Interface) for accessing databases. It is essentially a software component library hosting the small number of components that are necessary to retrieve data from and update data in databases. There are three essential types of object you will need to learn to use to access data:  Connection objects: a connection is a software ‘object’ that provides an interconnection between a piece of software and a database. It has been designed so that it is easy to access data from almost any type of database, including Microsoft Access, Paradox, dBase, Oracle, SQL Server, and even structured text files and the data stores used by email servers. Typically a connection object is deployed in a script to create a connection to a particular database and send commands to it  Command objects: some of the commands that are sent to a database are more complex than a simple connection object (which has a job of its own to do maintaining a database connection) can handle easily. Typically, when a command contains a number of associated pieces of information (parameters), a command object is used to package and dispatch it via a connection. There is no real need to use command objects for most database operations, but it can make some of them easier to handle  Recordset objects: one thing we often want to do is to retrieve data from a database. Using ADO, this data is almost always returned in the form of a Recordset, which acts like a table of data held in computer memory. A Recordset can contain a whole table of data, but more typically, Recordsets are used to collect the results of a query – a single record from a table or joined tables, several selected columns from a defined set of rows in a table, in fact any data that can be the result of a SQL select statement. Recordsets give us access to the information that is in a database, and also allow us to add or change data in databases from an ASP script In addition, there are other types of ADO object that we do not normally deal with specifically – a Field (a single column of a single record of data) will give us access to actual data attributes, and an Error will provide us with information that indicates what went wrong when an ADO command can not be executed for some reason. Fields come to us as component parts of Recordsets and so we tend to work with them without explicitly referring to them (this will become clearer after a practical example). A collection of Errors is maintained by the Connection object, and can be examined by script code whenever some ADO operation is executed to determine whether it worked or not.

Object Model

ADO objects are packaged for deployment in a Dynamic Link Library (DLL). This is nothing to worry about – it simply means that we can access ADO objects from a running script. Each ‘object’ we wish to use must first be loaded into computer memory (a service provided for us by IIS) and then set up for use. The steps in doing this may at first seem complex, but they are a simple recipe we repeat any time we want to make use of an ADO object, and are hugely less complex than the underlying functions that the objects are performing for us. The ADO object model is organised as shown below: Connection Recordset

Errors Fields

Properties Properties

Command Properties

Parameters

Properties

Figure 7: The ADO Object model A Connection object potentially contains a collection of Error objects and a collection of Properties. Error objects only exist if, after executing some operation, something has gone wrong, and they are there to provide information as to the cause of the problem. Properties are ‘settings’ that apply to a connection – for example, the type of database it connects us to, the name of the database and an indication of whether it supports transactions (coherent sequences of commands). Similarly, a Recordset object contains a number of Fields (each field represents the name, type and value of an attribute in a database tuple), each of which can have Properties, and a set of Properties of its own (for example, the number of records in it, an indication of whether we are at the end of the set of records). A Command object has a set of Parameters (each indicating a piece of information that can be sent to or retrieved from a query) and some Properties (the type of command, its name and whether it will return a Recordset or not) This small set of objects is enough to enable us to do whatever we wish to an existing database. The objects contained in ADO are interrelated so that they collaborate on performing data access tasks for us. A typical sequence of operations we might perform to retrieve some data for display from a database might be something like: 1. Connect to a database 2. Open the database (making the data in it accessible) 3. Send a SQL query to the database connection defining the set of information we want 4. Using the Recordset that is returned from the connection as the result of the query, step through the current record in it, displaying the contents of each field in the record 5. Try to move to the next row in the Recordset 6. If the next row is not empty, return to step 4 7. Close the Recordset 8. Close the database connection This sequence of steps indicates something about the structure that relates the objects in ADO. A connection is capable of creating a Recordset, and a Recordset contains a sequence of records (rows), each of which may have a number of individual Fields (attributes). The relationships between these objects is structural, and is sometimes referred to as an Object Model – the way in which objects are interconnected to form a coherent and useful assembly. The way we step through the operations is typical of the flow of instructions in an ASP script - a step by step sequence of small tasks that incrementally perform a larger overall task. As we step through such a sequence, the various ‘objects’ in ASP are made to interact so that they collaborate on some overall task (for example, in steps 3 and 4, we send a SQL query to a connection, which responds by giving us back a Recordset full of data). In this way, the object model, rather than any individual object, is responsible for performing some task.

Database Neutrality

One important feature of ADO is that it tries not to make distinctions between different types of database. The ADO code to retrieve data from an Oracle server is exactly the same as the code we would use to retrieve the data from an Access database with a similar data structure. It is impossible for ADO to be 100% neutral in this respect (some database systems provide advanced features that not all of them do), but as much as possible, ADO hides the idiosyncrasies of the underlying databases, which is a very good reason to use it. By providing for transparent interaction with any of a range of database types, ADO makes it possible to change the underlying database without ADO code needing to be radically re-written. For example, I may start with a small website that caters for a small number of visitors and use an Access database as the underlying database. If my website became very popular over time, it might be sensible to transfer the data to a SQL Server database, since this provides for much higher data throughput. Using ADO, only minimal changes would be needed to make the transition from Access to ADO (provided I did not immediately need to make use of some of the more industrial-strength features of SQL server, since for these, it would almost certainly be necessary to change the ADO code significantly).

IIS Server Objects

IIS (and Personal Web Server) make a number of standard objects available to ASP code. Typically these objects perform complex functions such as extracting useful information from web requests, packaging up web responses to send back to the clients’ browsers, and maintaining the state of clients’ sessions and the application itself. It also provides a simple mechanism for deploying other objects that are not part of IIS, such as ADO connections and commands, on request. IIS separates out ASP code from html code as it sends a response back to a request. While plain HTML is passed directly into the response, ASP code is executed by one of the available script engines attached to IIS. The script engine interprets the ASP code (e.g. VBScript), and returns a result to IIS, which then passes this on into the response. ASP script is lines of script code within any script tags <% and %> in an ASP file. A typical script statement might evaluate an expression (e.g. 2+2) and calculate its result (e.g. 4). An ASP file may contain any number of blocks of script interspersed between blocks of HTML, and in each case, IIS will direct HTML straight back into the response but will have ASP code executed by the script engine. Within the ASP statements, there will usually be references to a number of objects that IIS is aware of. These objects perform standard functions that would be too complex or too mundane to write script code for. Objects in IIS are responsible for representing information about the page request (the Request object), sending and controlling the sending of results back into the response (the Response object), managing various aspects of the server engine itself (the Server object) and keeping track of information that is used by the entire ASP application (the Application object) and by individual sessions (the Session object). Other objects collect data from a client’s browser (Form), store data on a client’s PC (Cookies) and allow script to access information specific to the server (ServerVariables).

Server

The Server object is used mostly to create other, non-native (to ASP) ob jects. For example, to create an ADO Connection object, we would use a statement like: Set conn = Server.CreateObject(“ADODB.Connection”) where “ADODB.Connection” is the name used to identify database connection objects to the Windows registry. We can also get the server to do other things that are not specific to any one website on the server, such as: Server.ScriptTimeOut = 90 to set the maximum amount of time (90 seconds) the server will allow any one ASP application to spend on responding to a single ASP request, or DatabaseName = Server.MapPath(“Dreamhome.mdb”) to work out the actual location of a file (in this case a database file) on the computer running the server.

Global.asa

Global.asa is the name we should give to a file of ASP code in the root folder of a website that defines routines that will be run automatically when certain things occur – the first page request for the site is received, the site has been inactive for a preset period of time, a new user sends a request in for a page, or a user completes a session.

Application

This object allows us to define variables that will be available throughout an ASP website. For example, if we wanted to create an ADO database connection object that could be accessed from anywhere on the site, we could use this code: Set conn = Server.CreateObject(“ADODB.Connection”) conn.open DBCONNECTSTRING Set Application(“Conn”) = conn

Now, wherever we were on the website, we could access the database, for example to execute a SQL Select statement, in code like this… Set RS = Application(“Conn”).Execute(“SELECT * FROM Client”) ‘ Can now go on to use the Recordset RS… The sequence Application(“Conn”) is used here to set or retrieve a variable that is accessible to the whole application – Conn is the name given to the variable – in this case a Connection object. The Application object is also used within Global.asa to define things to do when an application starts (when its very first request is received). For example, we might place the code listed above to open a database connection in Global.asa so that a connection is automatically opened as soon as the first visitor arrives (like opening the first bottle of wine as soon as the first guest arrives at a party – the wine will be open for subsequent guests to arrive):

‘ Code in Global.asa

Sub Application_OnStart() Set conn = Server.CreateObject(“ADODB.Connection”) conn.open DBCONNECTSTRING Set Application(“Conn”) = conn End Sub Listing 3: The Sub in Global.asa that initializes an active website. The code Sub Application_OnStart() defines the entry point to a subroutine (a block of code that is executed as a sequence of instructions) that will execute automatically when a site starts up.

Session

A session object can be maintained for each and every current user of the site. This allows us to store a small amount of information for each user between pages – for example, we can establish who a user is when they first log in to the site by making them visit a log-in page, which would allow us to authenticate users of a restricted site, or provide us with an identity that we can use to record purchases in a shopping cart style website. Once someone has logged in for the first time and we have collected some data on their identity (typically in a database Recordset), we would not want to ask them to log in again for each page they visit, so we could store the user’s login-identity in a session variable: Session(“UserID”) = RS(“UserID”)

In the above statement, RS is the database Recordset containing user data, and UserID is the name of the field in the current record that stores the user’s identification (typically a customer number, or possibly a nickname or email address). Now, in each subsequent page-visit, the user’s ID will be accessible as: Session(“UserID”)

Since we can create and use as many session variables as we like, we could continue to define more variables to store, for example, user’s name and other details, details of current purchases in a shopping cart, and so on. However, since each session variable will require a block of information to be passed back and forth between the web server and the browser each time an ASP page is accessed, the result of too many session variables can be to slow down the web accesses and make the site appear more sluggish. For good website design, it is better to minimize the amount of data being passed back and forth between browser and server – typically we would store the bulk of the data in a database and just use session variables to pass key values back and forth, so that we could always identify the database entries that stored the information we needed.

Request

The Request object is used in ASP script to gain access to information that comes from the browser. It has four properties that give this access:  QueryString: simple interactions with an ASP page (GET operations) can contain further information in the (modified) URL in the form of Name=Value pairs. The QueryString property allows these to be accessed.  Form: this property allows you to retrieve values entered into and POSTed from a form on the requesting web page. Each control on a HTML form is represented in the form object, and the collection of Form values can amount to a significant quantity of information sent from a browser to a website  ServerVariables: Using this property, you can determine the type of browser that sent the request (e.g. Internet Explorer 5.0, Netscape) and other information (e.g. the visitor’s IP address)  Cookies: this property allows you to access data that you previously stored in the user’s computer; these are typically small configuration files that allow you to recognise a browser that had previously visited the site, and are typically used to allow you to ‘personalize’ the pages you send back. QueryString There are two types of request that can be sent from a user’s browser. A GET operation (the simplest one) can contain up to 255 characters worth of data appended to the URL used to access your site. For example, a HTML file might contain a number of different hyperlinks which all lead to the same ASP page. To identify which link was used, the hyperlinks could include a different Name/Value pair in each link. For example,

Figure 8: A hyperlink with a query string (link is displayed in the status bar). Note the four links at the bottom of the page (First, Previous, Next and Last), and the URL shown in the status bar, which is the URL that will be used if the mouse is clicked when the pointer is over the ‘previous’ link, as shown. This would be coded into the html page as a set of page-links as shown in bold below:

DreamHome Estate Agents

Information: Select a page...

First Previous Next Last Listing 4: HTML code with hrefs defining links with query strings. The file getInfo.asp will be able to determine which link was clicked on by retrieving the value QueryString(“info”) (which will be ‘prevpage’ if the ‘Previous’ link was pressed). Form GET operations are ideal for sending a small amount of information to the server. Several values can be passed to the server, provided the length of the entire set of name and value pairs passed does not exceed 255 characters (this limit must include the delimiters ‘?’ at the start of the list of QueryStrings, ‘=’ between each name and value pair, and ‘&’ between successive name/value pairs). If it is necessary to send more data from the browser to the website, a POST operation can be used. The POST method can deal with much larger amounts of information. It is also a more convenient way of sending data from a Web Form – an area embedded in a web page that contains controls that the user can enter data in to. In a POST operation, data is again sent in Name/Value pairs, but now these are sent as a separate stream of binary information, retrievable from the Form property of the Request object. For example, a web form can be used to pass registration details to the website:

Figure 9: A HTML form – each control on this will provide data that can be collected from the Request.Form object All of the values entered into this page on the browser by the user will be sent as name/value pairs by the POST method. The html for the form is:

Join our Mailing List

Please enter the details below (do not omit any items marked *):

* First Name:

* Last Name:

Telephone:

* Street Address:

* City :

* PostCode:

Email:

Where do you want to find a house:

Preferred Rental Type: House Flat

Maximum Monthly Rent: £

 

Listing 5: HTML code to produce the form shown in figure 9 All of the controls on the above form are encoded in the web form as , or " Dim D D = StartDate Do While D <= EndDate HTML = HTML & "" D = DateAdd("d", 1, D) Loop HTML = HTML & "" GenerateDateOptions = HTML End Function '************************************************** '*** GenerateHourOptions function '************************************************** '*** Written 13/6/2004 '*** Author: A.McMonnies '*** Revision 1.0 '*** Purpose - Function returns a complete HTML '*** tag set for an option button with a range of '*** hour-intervals pre-loaded. This HTML should '*** be embedded in a form for user-input. '======'*** Input parameters '*** 1. startHour As String - hour at start end of range. '*** 2. endHour As String - end at end of range. '*** Result - HTML Text As String '*************************************************** Function GenerateHourOptions(startHour, endHour) Dim h, options Dim Q Q = Chr(34) options = "" GenerateHourOptions = options End Function %> Listing 14: The DHIncludes.inc file – functions and subs for general use by ASP files. DHIncludes.inc is an include file that we refer to at the top of any ASP file we wish to incorporate its functions into. To make the functions in the file available, we use the following statement in an ASP file (note – DHFunctions must be in the same folder):

Now we can call any of the functions within this file from our ASP file. The utility functions in here are:

Function GetClientName(id) – this function retrieves the full client name from the database given the ClientID. We can incorporate a call to it within ASP code, like: Response.Write GetClientName(3) which would display the name of the client with ID = 3 in the Client table of the database, or can even incorporate it directly into a HTML statement:

Hello <%=GetClientName(Session("ClientID"))%>. Nice to see you back.

Function RSToHTMLTable(RS, borderwidth, link) – this very useful function will display the entire contents of an ADO Recordset within a HTML table. On the potentially many times you wish to display the information retrieved from a database in a Recordset, simple call this function passing the Recordset into the function as the first parameter, a number (0, 1 or 2 is normal) for the second parameter, and, if you wish each record in the table to display a link to a page to show the data in more detail, the name of the ASP file to do the detail display in the third. The function displays the table with headings taken from the Field names in the Recordset, so for example, a Recordset that was created with the SQL statement “select Name, email from Client” would be displayed as a two column table with headings “Name” and “email”. You can take advantage of the SQL ‘as’ clause to define the headings you wish to be displayed. For example, given the Client table in the DreamHome database, the SQL statement: select FName + ‘ ‘ + LName as Name, telNo as Telephone, email from Client; could be incorporated into an ASP file with a statement like: Response.Write RSToHTMLTable(RS, 1, "") This would display the data selected with the headings, Name, Telephone and email as follows:

Name Telephone email Fred Flintstone 555 1234 Wilma Flintstone 555 1234 Albert Johnstone 555 6677 Clark Kent 555 9999 Joe Bloggs 123 4567 Edward Scissorhands 123 4567 Albert Enistein 555 6789 Snorrie Sturrluson 333 4567 Ferdinand Oblogiotta 123 5555 Joe Schmoe 123 45678 Bill Gates 123 5555 Ermentrude Llama 000 2222 Table 1: Results from the RSTOHTMLTable function in DHIncludes.inc If the third parameter is included, it should be the name of an ASP file in the same folder as the one that uses the RSToHTMLTable function. This page should expect a single GET value – Request.QueryString(“ID”) – where ID is the ID column of a database table. The ASP page can then display more information about this particular record.

Function GenerateDateOptions(StartDate, EndDate) – this function will display a drop-down box (sometimes called a ComboBox) containing the specified range of dates. You should call this function within HTML form code to provide the client with a range of dates to select. Date entry is always a problem in software if the user has to type a date, particularly in web pages where an invalid date that is entered may be sent back to the server before it is recognised as an error. Users can enter an invalid date (such as 30th February), a date the past or even text that is nothing like a date, and if this is sent to the server, the result can only waste time and processing. Using the GenerateDateOptions function, you can ensure that the user is only able to enter a valid date from a selected range. The resulting date form a form can be picked up as Request.Form(“optDate”).

Function GenerateHourOptions(startHour, endHour) – this function will display a drop-down box containing a list of 1-hour ranges (e.g. 11:00 – 12:00) to allow a user of the site to select a time for an appointment. The resulting hour is a single number (the starting hour of the range) that can be picked up from Request.Form(“optHour”).

Now that we have set up the basic housekeeping for our active web site, we can think about what pages we will need to fulfil the functions listed earlier. Page name Purpose Links to Index.asp Display company information, and JoinMailingList.htm, list the available options. Note Rentals.htm, that these will be different for ReviewViewings.asp visitors depending on whether they are on the mailing list or not. This page can also display contact details. Rentals.htm This page allows a visitor (whether Rentals.asp on the mailing list or not)to view Index.asp properties that meet some selected criteria (size, location, price etc.). This page does not need to be active, since forms are supported in standard HTML Rentals.asp This page displays the list of Index.asp rentals that matches the criteria ViewProp.asp entered into Rentals.htm. ViewProp.asp Returns details of a property Index.asp selected on the Rentals.asp page BookViewing.asp Login.htm Provides a form for entering log-in information. Again, this page does not need to be active. JoinMailingList.htm Provides a form for a new client to AddToMailingList.asp add their contact and other details Index.asp to. Again, this pages can be plain HTML AddToMailingList.asp Takes the information from the Index.Asp JoinMailingList form and enters it into the Client table of the database BookViewing.asp This will have a form for booking Index.asp a property viewing, but since it CreateBooking.asp will be accessed via the Rentals.asp page, it will need to be active so that it can identify the Client and the Property CreateBooking.asp This page will do the job of adding Index.asp a booking record (details entered at BookViewing.asp). ReviewViewings.asp This page will allow a registered ViewingComments.asp client (on the mailing list) to Index.asp examine the records of any viewings they have made, either to cancel the viewing or to make comments and/or rent the property. ViewingComments.asp This page will accept any Index.asp comments or a reservation to rent a property Table 2: The files in the Dreamhome website

Exercise 1: Index.asp - the Home page

In this page, we should be able to identify a client who has already registered with the site provided their browser supports Cookies. For requests from browsers that do not support Cookies, we will need to make it possible for a client to log-in to the site. When a Session commences here, we can set up a session variable, ClientID, to indicate whether we know the client or not, having first checked for a Cookie. Of course, we may have the client on the system but their browser does not support Cookies, in which case we need to treat the client as a newcomer anyway. The logic of the page is straightforward: If the ClientID session variable has a value Greet the user Display registered user site options Else Display standard (non-client) site options End If What is displayed depends on the value in Session(“ClientID”) (which will have been set up in the Session_OnStart() routine in Global.asa. If this is nothing, we will display only the standard options available to non clients. If there is a ClientID value, we can retrieve and display that client’s name so that the page can greet them, and then display the options available to registered clients: view properties for rent or display details of any property viewings the client has had in the past. If there is not a ClientID value, we will display the standard options: view properties for rent, join the mailing list and log-in as a client. This last option is necessary is case the person visiting the site is a client, but does not allow Cookies in their browser. Joining the mailing list will of course create a ClientID for a visitor so that their next visit to this page will display the client-only options. A small amount of ASP code performs this functionality… <%@ LANGUAGE = VBScript %> DreamHome Estate Agents

DreamHome Estate Agents

<% ' Do we know this client... If Session(“ClientID”) <> "" Then Name = GetClientName(Session(“ClientID”)) Response.Write "

Hello " & Name & "

" Response.Write _ "

Welcome back to the Dreamhome website.

" Response.Write _ "

Properties for Rent.

" Response.Write "

” & _ “Check your viewing appointments.

" Else Response.Write _ "

Properties for Rent.

" Response.Write "

” & _ “Join our Mailing List

" End If %> Listing 15: The Index.asp file – recognising a client (or not). Given what we have already covered, the only notable features of this page are the statements that display hyper-links. For example: Response.Write _ "

Properties for Rent.

"

Note how the address of the linked page is embedded in single quotes (‘) as the href attribute of the (anchor) HTML tag. Testing the Index page is a bit more complex than simply entering the URL into a browser and checking whether the correct result appears, since we are aiming to support both systems that allow cookies and systems that do not. For this purpose, I’ve found it useful to place an extra page in the website – SetClient.asp. This simple ASP lets you set up a client cookie with a specific client value, clear the current setting and find out what the current cookie setting is: <%@ LANGUAGE = VBScript %> SetClient.ASP <% If Request.QueryString("ID") = "none" Then Response.Cookies("ClientID") = "" Response.Cookies("ClientID").Expires = Date Session.Abandon Response.Write "Client reset" ElseIf Request.QueryString("ID") = "who" Then Response.Write "'ClientID' Cookie now set to : " & _ Request.Cookies("ClientID") ElseIf Request.QueryString("ID") = "" Or _ Request.QueryString("TimeOut")= "" Then Response.Write _ "Usage: SetClient.asp?ID=[id_value_to_set]&TimeOut=[number_of_days]" Else Response.Cookies("ClientID") = Request.QueryString("ID") Response.Cookies("ClientID").Expires = DateAdd("d", _ Request.QueryString("TimeOut"), Date) Response.Write "'ClientID' Cookie now set to : " & _ Request.QueryString("ID") & "
" Response.Write "Cookie will time out on " & DateAdd("d", _ Request.QueryString("TimeOut"), Date) End If %> Test Listing 1: An ASP page for setting up, changing and clearing a client cookie. Using the ASP in Test Listing 1 we can set up the test browser to have a particular customer ID by entering the following into the address bar: http:///Dreamhome/SetClient.asp?ID=25&TimeOut=30 This setting would make the client ID 25, and would set the cookie to persist for 30 days, after which the browser would discard it. If you forget what the current client ID setting is: http:// /Dreamhome/SetClient.asp?who remembering to supply the correct server name (or localhost) for your own machine. Removing the cookie is as simple as: http:// /Dreamhome/SetClient.asp?none Finally, if you were to forget any of this, the following would display the various ways of setting up the cookie in the browser: http:// /Dreamhome/SetClient.asp

Using this utility, we can now test the Index.asp page by setting various client ID’s and checking that the client’s name is displayed in the browser. Clearing the client ID, we can then test that Index.asp displays appropriate options for a new client.

Exercise 2: Rentals.htm – The form for indicating rental preferences

This file does not include any ASP code (as an HTML file, any code that it contained would be ignored by the server’s script engine). However, it does serve a very important purpose for an active website, since it defines a form that will collect user- input and send it back to the browser. The form code is as follows: Rentals.htm

House Rentals

Select the criteria for your ideal home...

Area

House Flat

Number of Rooms

Maximum rental (per month) £

Home

Listing 16: rentals.htm – This defines the form shown in Figure 12 The code in listing 16 defines a HTML form. In the form (shown in figure 12), there are two drop-down boxes for the user to select from, plus a pair of option buttons, a text box and a pair of buttons. A HTML form is created in HTML code using the
tags. Since a form is usually required to have an action (in this case, to call up a specific ASP page), this is defined in the opening
tag as the ‘action’ property. When the form is submitted, this page will be executed at the server. The HTML code applies names and values to a range of form-based controls – text boxes, option buttons, lists etc. The values entered into these control can be retrieved in ASP code by referring to the specific control; for example Request.Form(“RentalMaxPrice”) will provide the value that the user entered into the box labelled “Maximum rental (per month)”. In some cases (e.g. select controls), a set of options is grouped within an overall tag, and the chosen option is referred to by the name of the outer tag; e.g. Request.Form(“RentalArea”) will retrieve whichever value was selected from the drop-down box. The end result is a file that is defined to inter-operate with a related ASP file. Rentals.htm sends its data to rentals.asp courtesy of the form’s action property (set to “rentals.asp”).

Request.Form(“RentalArea”)

Request.Form(“RentalType”)

Request.Form(“RentalSize”)

Request.Form(“RentalMaxPrice”)

Figure 12: The rentals.htm page. Given this form, generating a list of rentals from the database that match the user’s input is a remarkably simple task, and is done by rentals.asp which provides the response to Rentals.htm.

Exercise 3: Rentals.asp

<%@ LANGUAGE = VBScript %> Rentals View Page

DreamHome Estate Agents

Rentals that match your criteria...

<% Set Conn = Application("Conn") ' Formulate a SQL Select query, uising # to mark values... SQL = "SELECT propertyNo As ID, street, city, " & _ "postcode, fname+' '+lname " & _ "As contact FROM PropertyForRent INNER JOIN staff " & _ "ON PropertyForRent.staffNo=staff.staffNo " If Request.Form("RentalArea") = "ANY" Then SQL = SQL & "WHERE type = '#2' AND rooms >= #3 & rent <= #4" Else SQL = SQL & "WHERE PropertyForRent.branchNo = '#1' AND “ & _ "type = '#2' AND rooms >= #3 AND rent <= #4" End If ' Now replace the values... SQL = Replace(SQL, "#1", Request.Form("RentalArea")) SQL = Replace(SQL, "#2", Request.Form("RentalType")) SQL = Replace(SQL, "#3", Request.Form("RentalSize")) SQL = Replace(SQL, "#4", Request.Form("RentalMaxPrice")) Set RS = Conn.Execute(SQL) If Not RS.EOF Then Response.Write RSToHTMLTable(RS, 1, "viewProp.asp") Else Response.Write("No matches found for your criteria.") End If RS.Close %> Listing 17: Rentals.asp Rentals.asp performs a task that will be familiar to any database developer – given a number of criteria, such as the area that a property is in, the number of rooms needed and the maximum price per month a client will pay, it will form a SQL query that sets these criteria and execute the SQL on the database. The data that is returned will be in the form of an ADO Recordset, but we already have a facility for displaying that in a browser (RSToHTMLTable). Forming the SQL query is interesting. The general format of the query will be: select from PropertyForRent where

Our problem is that the criteria will come from form controls sent from Rentals.htm, so we need to embed these into the SQL. This can be messy, since the overall SQL statement will be a sequence of database column names interspersed with values extracted from the form. However, VBScript has a neat feature – a string function called Replace(), that we can use to form the overall statement in a sequence of logical and orderly steps. We start by storing the basic SQL statement in a string variable, ignoring any criteria (‘where’ clauses): SQL = "SELECT propertyNo As ID, street, city, postcode, “ & _ "fname+' '+lname " & _ "As contact FROM PropertyForRent INNER JOIN staff “ & _ "ON PropertyForRent.staffNo=staff.staffNo "

Note that we’re incorporating contact details into the result by joining the PropertyForRent table with the Staff table, and concatenating the fName and lName files in the Staff table to simplify the result. Now we need to limit this overall query, by selecting only those properties that match the requirements set out on the form. The criteria specified can be branchNo (the location), type (house or flat), rooms (minimum number) and rent (maximum), or simply type, rooms and rent, if the user accepted the “Don’t Care” (ANY) option for area. We can determine which version of the criteria is needed by checking the Request.Form(“RentalArea”) value, and then form the ‘where’ clause of the SQL, and adding it to the existing SQL statement: SQL = SQL & "WHERE type = '#2' AND rooms >= #3 & rent <= #4" or SQL = SQL & "WHERE PropertyForRent.branchNo = '#1' AND " & _ "type = '#2' AND rooms >= #3 AND rent <= #4"

Note however that instead of specifying each criterion in this clause, we simply have place markers #1, #2, #3 and #4. These are distinctive values that we know will not appear in a normal SQL statement. We can now go on to replace each marker with the actual value taken from the form: SQL = Replace(SQL, "#1", Request.Form("RentalArea")) SQL = Replace(SQL, "#2", Request.Form("RentalType")) SQL = Replace(SQL, "#3", Request.Form("RentalSize")) SQL = Replace(SQL, "#4", Request.Form("RentalMaxPrice"))

The end result is a complex SQL string that specifies all of the criteria stated on the form, without what would be a mess of partial statements joined up with bits of form variables. It is now a comparatively trivial matter to execute the SQL on the database, and display the returned result using our RSTOHTMLTable function (from DHIncludes.inc), not forgetting to close the Recordset once it has been formatted for display. Note that “viewProp.asp” is given as the third parameter in the call to RSToHTMLTable(); this will have the purpose of adding a HTML tag – a hyperlink, to every ID tag in the table (we have engineered one of these in every row by specifying “select propertyNo As ID…” in the SQL). The result is that each entry in the table will link to a page that provides details of the property. The end result is shown in figure 13. Note that the ‘View Detail’ link in the last column is a hyperlink (the target for the first on is shown in the status bar because the mouse pointer is hovering oven the link):

Figure 13: The result of executing Rentals.asp with the form values shown in figure 12 Note that the hyperlink in each row is to a file called viewProp.asp. We should move on to develop this file now.

Exercise 4: ViewProp.asp

A user will only get to this page by selecting a property from the list of matches generated by Rentals.asp (the client could bookmark a specific property having navigated to it, but the bookmark would still include the specification of the property due to the way that the GET method works, incorporating data after the ? in the page URL). Look closely at the status bar in figure 13, and you see that the URL that links to the viewProp page includes a QueryString setting (in this case, ID=PA14). The viewProp ASP file will simply need to retrieve the property record that matches this ID and display its details. <%@ LANGUAGE = VBScript %> View Property Page

DreamHome Estate Agents

Your selected rental...

<% Dim propID propID = Request.QueryString("ID") Dim SQL SQL = "SELECT * FROM PropertyForRent WHERE propertyNo = '" & propID & "';" Set RS = Application("Conn").Execute(SQL) If RS.RecordCount <> 0 Then ' Display the property details... Response.Write "Property Code: " & RS("propertyNo") & "
" Response.Write "Street Address: " & RS("street") & "
" Response.Write "City: " & RS("city") & "
" Response.Write "Property Type: " & RS("type") & "
" Response.Write "Number of Rooms: " & RS("rooms") & "
" Response.Write "Monthly Rental: " & RS("rent") & "
" Response.Write "Staff Cotntact: " & RS("staffNo") & "
" Response.Write "Branch Code: " & RS("branchNo") & "
" Response.Write "
" ' Display picture... If Not IsNull(RS("picture")) Then Response.Write "" End If ' and plan... If Not IsNull(RS("floorPlan")) Then Response.Write "" End If Response.Write "
" Response.Write "
Arrange a Viewing
" Response.Write "Home
" Else Response.Write("No matches found.") End If RS.Close %>
Listing 18: viewProp.asp – a script to display details of a selected rental property. This page also displays up to two pictures associated with a given database entry. The data table, PropertyForRent, includes two fields that refer to picture files. Note the two attributes – picture and floorPlan. Both are text attributes that will hold the path and filename of an image file. The first is for a photograph of the property, the second for a floor plan drawing. Inserting a picture into a HTML document is a simple matter of creating an tag, which contains a ‘src’ attribute that can reference a picture file in GIF (line-art) or JPG (photograph) format. For example, the tag will refer to a file named ‘imageFile.jpg’ in a folder named ‘images’ contained in the folder that the HTML file is in. If this file exists, it will be displayed in the browser. In listing 18, two If..Then statements control whether an image tag is inserted into the web page. The IsNull() function returns True if the specified attribute has a null value (i.e. it is empty). Provided the attribute is not empty, the controlled statements: Response.Write "" write out a HTML tag that inserts these pictures. The result is that if photographs and line art further describing the propertyForRent are available and have been referenced properly, these will be displayed in the web page: Figure 14: The viewProp.asp page, showing a photo and a floorplan image of the property.

Exercise 5: Booking a viewing

If the user were to select the link “Arrange a Viewing” in the viewProp page, the action of arranging a viewing would rely on there being a data record for that user in the Client table. Recall that when the session started we attempted to identify the client by accessing the ClientID Cookie (using the Session_OnStart() sub in globals.asa). There were three possible outcomes to this: 1. The ClientID cookie existed, and so we will have set the ClientID session variable to this value, and we now know exactly who we need to arrange a viewing for 2. The ClientID cookie did not exist because this was a new client who had never registered with the site, so currently the ClientID session variable is empty 3. The ClientID cookie did not exist because although the client was already registered, the client’s browser does not accept cookies – again Session(“ClientID”) would be empty. Because of this, if a client is to arrange to view a property, we must start by trying to retrieve the client’s ID from a session variable. If the session variable is empty, we need to re-direct the client’s browser to a log-in page. The logic to do this is easy enough, but does require that a page we are using for input will also need to contain logic to test the client’s ID and perform the re-direction. <%@ LANGUAGE = VBScript %> Book A Viewing <% ' First we need to establish who the booking is for... If Session("ClientID") = "" Then ' Don't know who - the client will need to log-in. ' Start by storing the url used to access this page so we can easily ' return to it... Session("ReturnTo") = Request.ServerVariables("URL") & "?" & _ Request.ServerVariables("QUERY_STRING") Request.ServerVariables("QUERY_STRING") Response.Redirect "login.htm" Else ' We know this client, so can continue with the booking... Dim propID, SQL, RS Session("ReturnTo") = "" propID = Request.QueryString("propID") ‘ Storing the propID in a session variable will simplify things… Session("propID") = propID SQL = "select * from PropertyForRent inner join Staff " & _ "on PropertyForRent.StaffNo=Staff.StaffNo " & _ "where PropertyForRent.PropertyNo='" & propID & "';" Set RS = Application("Conn").Execute(SQL) Response.Write "

Book a viewing

" Response.Write "" Response.Write "

Property: " & RS("street") & ", " & _ RS("city") & ", " & RS("PostCode") & "

" Response.Write "

Client Name: " & _ GetClientName(Session("ClientID")) & "

" Response.Write "

Agent Name: " & _ GetStaffName(RS("Staff.StaffNo")) & "

" Response.Write "

Viewing Date: " & _ GenerateDateOptions(Date+1, Date+8) & "

" Response.Write "

Preferred Hour: " & _ GenerateHourOptions(9, 5) & "

" Response.Write "
” & _ "" End If %> Listing 19: bookViewing.asp – note the test for a ClientID cookie at the start In bookViewing.asp, we first check whether we know the client. Depending on the outcome, we need to arrange the page to perform one of two possible functions – it will either send the client’s browser off to the login page, or it will act as a form, providing the user with input controls on the browser. If there is no Session(“ClientID”) value, we send the client’s browser to the login page. However, before we do this, it is a good idea to keep track of where we currently are. The Session(“ReturnTo”) variable can be used to store a URL for a ‘return address’. We can also include the ID of the property the client is arranging a viewing for as a QueryString parameter, by simply appending it to the end of the URL. The formatting for this is simple – Request.ServerVariables(“URL”) gives the address we want to return to (the address of this ASP page), while Request.ServerVariables(“QUERY_STRING”) is the name and value of the query string we sent to this page to identify the property to be viewed (the Property ID). The advantage of using a query string instead of a session variable here is that the user can bookmark specific properties in his/her browser since the property ID is contained in the URL. Having set up the address to return to after the log-in process, we can now send the client’s browser to the log-in form (we will deal with this in listings 21 and 22). Response.Redirect() simply re-orients the client’s browser at the specified URL. If we already know who the client is, the Else case in listing 19 takes over. In this, we build a SQL statement to retrieve more details about the viewing (more as a way of providing the client with better information than because we need to – the SQL statement simply returns more information about the property and the agent who looks after it), collect the information and then set about building a form to allow the user to say when the viewing is requested for. Figure 15 shows the form: Figure 15: the form for arranging a viewing – note this form is generated in ASP code. There are two statements in particular that make the creation of this form stand out from other HTML forms: Response.Write "

Viewing Date: " & _ GenerateDateOptions(Date+1, Date+8) & "

" Response.Write "

Preferred Hour: " & _ GenerateHourOptions(9, 5) & "

"

In the first of these statements, the GenerateDateOptions() function is used to create the drop-down box of dates you can see in Figure 15. Given two dates (in this case, tomorrow’s date and a date 8 days from now), the function will generate HTML code to provide the user with a box from which to select a date in this range. If we were to ask the user to type a date into a text box, we would be asking for trouble, since the user could enter a date in the past, one on a day so far in the future that it might affect office planning, an invalid date (such as the 30th February) or any of a range of other circumstances we could not cope with. By providing the client with a fixed list of dates to choose from, we have simplified the whole procedure. The second statement calls on GenerateHourOptions() to provide the same sort of facility for selecting a suitable time for a viewing. Of course, the combination of date and time selected by the user might cause another problem, since the required agent could be busy with some other job, but once a provisional viewing date and time is booked, the agent would be able to contact the customer and negotiate a more suitable appointment. Once a client has filled in this form and pressed the Submit button, an ASP page will have to deal with recording the viewing data. This is a simple enough process: <%@ LANGUAGE = VBScript %> Create a new booking <% Dim SQL If Session("propID") <> "" Then SQL = "insert into Viewing(clientID, propertyNo, " & _ "viewDate, viewHour) values(#c, '#p', '#d', #h);" SQL = Replace(SQL, "#c", Session("ClientID")) SQL = Replace(SQL, "#p", Session("propID")) SQL = Replace(SQL, "#d", Request.Form("optDate")) SQL = Replace(SQL, "#h", Request.Form("optHour")) Application("Conn").Execute SQL Response.Write "

Booking created

" Response.Write "

Property: " & Session("propID") & "

" Response.Write "

Date: " & Request.Form("optDate") & "

" Response.Write "

Hour: " & Request.Form("optHour") & "

" Response.Write "Home" Else Response.Write "No property has been selected." Response.Write "Home" End If %> Listing 20: createBooking.asp – ASP code to insert data for booking a viewing into a database table The ASP code in createBooking.asp starts by checking whether a property has been specified in a session variable. If it has not, the user has probably got here by having bookmarked it in their browser – we should avoid trying to deal with it in this case as there is too much other information that will be needed. The database insertion is done simply by creating the SQL statement needed to do it, and then passing this to the database connection’s Execute command. Note we have again made use of the Replace() function to make adding the parameters to the SQL Insert statement easier. Once the data has been inserted, all that remains is to confirm the appointment to the client (by writing back the property, date and time to their browser) and provide a link for the client to go back to the home page.

Exercise 6: Logging-in

If a new or unknown client attempts to create an appointment to book a viewing, we need to get them to log-in to the site. If he/she is already registered on the site, we simply need to ask for a username and password. If, not, we need to go through the entire registration process. The problem is, we don’t know which. The usual strategy is to provide a page for existing registered users to log-in, but to provide a link to a registration page for new users, and hope that they will realize they need to follow this link (we can always spell it out on the page). Providing this page is easy since it will contain only HTML Log-in

Registered users

If you have previously registered with Dreamhome, please enter your email address and password

Email

PostCode


New users

If you have not registered with Dreamhome, please follow this link Register with Dreamhome

Listing 21: login.htm – a simple HTML page to allow a user to log in. Note, a link is provided to allow a new user to go to a registration page. To get to this page (login.htm), a user should have been redirected from the bookViewing.asp page. An existing client will log in to the site using their email address and PostCode. Using the client’s email address and PostCode in combination provides some minimal security here (a stranger is unlikely to guess both) – probably enough given the nature of the operation. However, you ought to consult the most up to date data-protection laws before you consider using this strategy for allowing people to log in to a site which contains sensitive information. The form appears in a browser as shown in figure 16: Figure 16: The login form. Note that the form on this page invokes login.asp, which contains code to retrieve the client’s ID if the correct combination of email and PostCode are used. Users of the site who are not registered clients will need to select the link to AddToMailList.htm, which provides a form for registering a client. Login.asp uses a SQL query to try to retrieve an ID from the client table, given an email address and a postcode: <%@ LANGUAGE = VBScript %> login.ASP <% Dim SQL, PostCode, Email Email = Request.Form("txtUserName") PostCode = Request.Form("txtPostCode") SQL = "select ID, FName + ' ' + LName as Name from Client" SQL = SQL & " where email = '" & email & _ "' AND PostCode = '" & PostCode & "';" Set RS = Application("Conn").Execute(SQL) If Not RS.EOF Then Session("ClientID") = RS("ID") Response.Cookies("ClientID") = RS("ID") Response.Cookies("ClientID").Expires = Date+30 Response.Write "

Welcome back " & RS("Name") & "

" Response.Write "

Return to arrange a viewing." Else Response.Write "

Log-in failed

" Response.Write "

Press the Back button on the " &_ "browser to try again, " & _ "or follow this link: " & _ "Register

" End If RS.Close Set RS = Nothing %> Listing 22: Login.asp. Retrieving the client’s ID Having issues a SQL statement to try to retrieve the client’s ID, we can determine whether the client record was found by testing whether the Recordset returned is empty – the EOF function does this test. Note that having retrieved a client’s ID in Login.asp, we can set the ClientID Session Variable so that other pages on the site know who the client is, and attempt to set a Cookie on the client’s computer to save them having to log in in future. The Cookie is set to expire in 30 days, which is an ample window of time for the client to return in. If a cookie already exists, refreshing it will re-set the expiry date to 30 days in the future.

Exercise 7: Registering

A client who can not log-in must register before he/she can arrange a viewing, and can get to the page to do this by selecting the ‘Register’ link set up at the end of the Else clause in listing 22. Registration is another user-input arrangement where the user’s data is entered in to an HTML form, and then sent by the form to an ASP page which updates the database. The HTML form is shown in figure 16, with the HTML code to generate it shown in listing 23. Figure 16: AddToMailList.htm – the HTML form for collecting client data New Page 1

Join our Mailing List

Please enter the details below (do not omit any items marked *):

* First Name: * Last Name:

Telephone:

* Street Address:

* City :

* PostCode:

* Email:

Where do you want to find a house:

Preferred Rental Type: House Flat

Maximum Monthly Rent: £

Home Listing 23: AddToMailList,.htm - the HTML code for the form As you can see from the Form tag in listing 23, when the user presses the Submit button, the form information is sent to AddToMailList.asp, an active server page for creating a new client record. Because adding a client record is a bigger operation than adding a record for a viewing (the Client table has more fields), the ASP page to do this is a bit longer than we have seen so far. However, the operation is no more difficult than that of adding a viewing record. The method for adding to the Client table is different however, since instead of constructing a SQL INSERT statement, it uses the AddNew operation of a Recordset. This method has the advantage that we can add a record a field at a time, and since the Recordset provides a more direct link between ASP code and the database, we can also retrieve the Client’s ID field value, which, as an autoincrement field, we do not set explicitly. Since we need this to set up the ClientID session variable and Cookie, the facility is helpful. Since the code listing is longer, we’ll look at it in two chunks: Add to Mailing List

DreamHome Estate Agents

Mailing List

<% ' Need to insert a record to Clients table of the database. ' We need to add a clientNo, so best approach is to open a writable recordset... Dim RS, conn Set conn = Application("Conn") Const adOpenDynamic = 2 Const adLockOptimistic = 3 Const adCmdTable = 2 Set RS = Server.CreateObject("ADODB.Recordset") RS.Open "Client", Conn, adOpenDynamic, adLockOptimistic, _ adCmdTable ' The client table is now open. Add a new record... RS.AddNew RS("fName") = Request.Form("txtFName") RS("lName") = Request.Form("txtLName") RS("TelNo") = Request.Form("txtTel") RS("Street") = Request.Form("txtStreet") RS("City") = Request.Form("txtCity") RS("PostCode") = Request.Form("txtPostCode") RS("email") = Request.Form("txtEmail") RS("JoinedOn") = Date RS("Region") = Request.Form("cboRegion") RS("preType") = Request.Form("optPreType") RS("maxRent") = Request.Form("txtMaxRent") RS.Update ' Now set the clientNo up in the user's browser... clientNo = RS("ID") Response.Cookies("ClientID") = clientNo Response.Cookies("ClientID").Expires = DateAdd("m", 3, Date) Session("ClientID") = clientNo ‘.... ‘ Continues… Listing 24: AddToMailList.asp part 1 – this code creates a new data record, retrieves the ID field for it and sets the Session variable and Cookie to suit When we retrieve a Recordset from a SELECT statement sent to a connection, ADO sends back the simplest form of Recordset available. This type of Recordset is capable of allowing the data to be read but not added to or changed, and allows us to look at records only in the order in which they appear in the Recordset – we can not scroll backwards to examine a record we’ve visited already. Technically, the Recordset is set as a ForwardOnly Recordset. How we create the Recordset influences what it can do, and to make a Recordset that we can write new data into, we need to open it in a more capable mode. The statements: Set RS = Server.CreateObject("ADODB.Recordset") RS.Open "Client", Conn, adOpenDynamic, adLockOptimistic, adCmdTable first create a new Recordset (in much the same way that we create a database connection), and then opens it for dynamic access (we can move to and update any record in the database or add new ones), with optimistic locking (updates to the database will be guarded against conflicting updates from another user of the database happening concurrently) and whole table access (the Recordset that is opened is the whole Client table, rather than a subset of it or a join with another table). This type of Recordset allows us to do what is needed to add new data. Having opened the correct form of Recordset, we simply use its AddNew method to create a new (initially blank) record, and then go through each field in the table assigning values to them. The values come from the Form fields defined in AddToMailLIst.htm. Note that we assign values to every field except the ID field – this is an Access auto-increment field, and so it will take on a number automatically. Having assigned values, a call to the Update operation in the Recordset sends this data back to a new record in the database table, and refreshes the Recordset so that it is completely in sync with the database table. This then allows us to read the newly assigned ID field into the ClientNo variable, and from there we can set up the Session variable and the Cookie for ClientID. At this stage the data is safely in the database, and we now have a way of identifying the client within the remainder of this session (using Session(“ClientID”) or in some other session (using Request.Cookies(“ClientID”), provided cookies are allowed on the client’s PC). We could stop at this point, the client’s data having been sent to the database, but since this type of operation requires a lot of things to happen correctly, it is good practice to first check that it all went well, and then report back to the client: ‘Continued… ‘... If Err.Number > 0 Then Response.Write "

An error has occurred. Please try " & _ "to join our list later.

" Else Response.Write "

Details stored in your mailing list " & _ "entry are:

" Response.Write "

Customer ID: " & RS("ID") Response.Write "Name : " & RS("fName") & _ " " & RS("lName") & "
" If RS("telNo") <> "" Then Response.Write "Telephone no.:" & _ RS("telNo") & "
" End If Response.Write "Address : " & _ RS("Street") & "
" Response.Write " " & RS("City") & "
" Response.Write " " & RS("PostCode") & "
" Response.Write " " & RS("City") & "
" If RS("email") <> "" Then Response.Write "Email address : " & _ RS("email") & "
" End If If RS("Region") <> "(N/A)" Then Response.Write "Preferred area : " & _ RS("Region") & "
" End If If RS("preType") <> "" Then Response.Write "Preferred rental type : " & _ RS("preType") & "
" End If If RS("maxRent") > 0 Then Response.Write "Maximum monthly rent : " & _ RS("maxRent") & "

" End If Response.Write "This information will be stored securely." End If RS.Close Set RS = Nothing If Session(“ReturnTo”) <> “” Then Response.Write “
Arrange a viewing End If %>
Home Listing 25: AddToMailList.asp part 2 – checking for an error and reporting back. This half of the ASP page is simpler. When the Recordset’s Update operation is called, one of the outcomes is to check for an error report from the database. If anything bad happened, an Error object, Err is created. Err has a number – 0 for no error, some other value to indicate a problem. If there has been an error, all we can do is let the user know something bad happened. However, an error number of 0 tells us all has gone well, and we can read back the values from the Recordset and report them back to the client as confirmation that their data is now stored in the database, The only remaining task is to guide the user back to where they came from. If Session(“ReturnTo”) is not empty, we have come from the Arrange a Viewing page, and need a link to return there. The last If..Then block in the script does this. Beyond the closing script tag (%>), we can provide a plain link back to the home page. When the user returns to the index page, it should now be able to welcome them by name.

Exercise 8: Revising viewing records

A registered client has the option of examining their past and future viewing appointments. This will make it possible to allow them to select a viewing and make a comment on it, or even indicate that they are interested in renting the property. Given the groundwork code for creating an HTML table from a Recordset, retrieving the client’s name etc, it takes only a small amount of code to provide this facility: <%@ LANGUAGE = VBScript %> Review Property Viewings

DreamHome Estate Agents

Review Property Viewings


<% Response.Write "

Client : " & _ GetClientName(Session("ClientID")) & "

" Dim RS Dim SQL ' Set up a SQL statement to retrieve the current client's ' viewing records... SQL = "select ID, propertyNo, viewDate, viewHour, " & _ "Comment, WishToRent from Viewing where clientID=" & _ Session("ClientID") Set RS = Application("Conn").Execute(SQL) ' Write out the result as a HTML table... Response.Write RSToHTMLTable(RS, 1, "viewViewing.asp") If RS.EOF Then Response.Write "
You have not viewed any properties.
" End If %> Home Listing 26: ReviewViewings.asp – ASP code to create a list of the current client’s viewing records. Note that things are a lot easier now because we don’t have to worry about whether the client is identifiable or not. Quite simply, we could not get to this page unless the client’s ID was in a Session variable (see the condition code in Index.asp). The list of viewings appears as a simple HTML table: Figure 17: ReviewViewings.asp – Viewing records for a client

Exercise 9: Amending a viewing record

In this final exercise, we will allow the client to update a viewing record, adding a comment and/or indicating an interest in the property. We need two items for this – an HTML form that displays a specific viewing (and so will need to be generated in ASP code), and an ASP page that accepts updates to this viewing entered into the form. First we’ll consider the code to generate the HTML form. This form will allow the client to enter comments about the property viewed and also to indicate whether they are interested in renting it. <%@ LANGUAGE = VBScript %> Comments on viewing

DreamHome Estate Agents

<% ' The viewing record ID is passed in the URL.. viewID = Request.QueryString("ID") Dim RS, SQL SQL = "select PropertyForRent.propertyNo, street, city, " & _ "viewDate, viewHour, Comment, WishToRent " & _ "from Viewing inner join PropertyForRent " & _ "on Viewing.propertyNo = PropertyForRent.propertyNo " & _ "where Viewing.ID = " & viewID Set RS = Application("Conn").Execute(SQL) Response.Write "

Viewing record

" Response.Write "

Property No.:" & RS("propertyNo") & _ "

" Response.Write "

Property: " & RS("Street") & ", " & _ RS("city") & "

" Response.Write "

Viewed on: " & RS("viewDate") & " at " & _ RS("viewHour") & ":00

" Response.Write "
" Response.Write "" Response.Write "

My comments:

" Response.Write "

I wish to rent this propertry: " & _ "

" Response.Write "” Response.Write "" Response.Write "
" RS.Close %> Home Listing 27: ViewingComments.asp – ASP code to generate a form for updating a viewing record. Listing 27 starts with the construction of a SQL statement. This selects, from a join of the PropertyForRent and Viewing tables, the required fields and incorporates the ID of a row from the Viewing table, which was passed as a QueryString in the page request. Once the SQL is executed on the database, we can write out the fields returned. The twist here is that the two fields that the user is able to update (the Comment and the WishToRent fields) are enclosed as form elements in a
tag. Since the WishToRent field is an access Yes/No field, is makes sense to display it as a checkbox, although this is quite awkward to do. HTML code for a checkbox is organised as follows: In this, the word ‘checked’ is only applied if the checkbox is to appear selected. The value property is what will be returned if the checkbox is checked when the user submits the form; if it is not checked, the value will be returned as an empty field. The first named field in the form will not appear in it. It is a ‘hidden’ input field, which means that the user will not be able to use it for input. It is instead, another way that we can pass data between pages within a session. The value of the hidden field is set to be the viewID of the current viewing record, since this is the record we will want to update. The statement: Response.Write "" embeds the current value of viewID as the value of the hidden field. This allows us to identify the record to update in the ASP page that responds to this form.

The other significant form field is a TextArea. This can display and accept multiple lines of text typed into the user’s browser. The form generated by this ASP code appears as follows:

Figure 18: The ASP generated form for viewing and updating a viewing record. When the client updates this form by pressing the ‘Update Response’ button, it will execute an ASP called UpdateViewRecord.asp. This ASP applies any changes made in the above form to the current viewing record in the database. <%@ LANGUAGE = VBScript %> Update Viewing Response

DreamHome Estate Agents

Update Viewing Response

<% Dim comments, wishToRent, SQL, RS comments = Request.Form("comment") wishToRent = Request.Form("chkRent") SQL = "update Viewing set comment='#1', WishToRent=#2 where ID=" _ & Request.Form("viewID") & ";" SQL = Replace(SQL, "#1", comments) If wishToRent = "True" Then SQL = Replace(SQL, "#2", "Yes") Else SQL = Replace(SQL, "#2", "No") End If Response.Write SQL Application("Conn").Execute(SQL) Response.Write "

Comments updated.

" %> Return to list of viewings Home Listing 28: UpdateViewRecord – this page writes the updates entered into the ViewingComments.asp form to the database. UpdateViewRecord.asp makes the updates to the database and sends a simple message back to the client’s browser to acknowledge this. It contains links to return to ReviewViewings.asp and the home page. Its most significant feature is the formation of the SQL statement to perform the update. This has the format: update Viewing set comment=’some comment’, WishToView=Yes where ID=some_ID To make the SQL parameters easy to insert into the statement, we again use the Replace() function to replace easily identifiable markers (#1, #2) in the SQL. You should note the placement of quote marks (‘) around the text parameter, but none around the Yes/No parameter, since the values Yes and No are valid for this type of field in Access and SQL server databases.

Summary

This completes the code for the Dreamhome active website. Of course, a real website would be more attractive, having better text styles, more graphics and some more carefully considered wording to provide the client with more explanations. However, the main point of this code is to demonstrate the various methods used to pass data from web browsers to a database and vice-versa. The HTML code in more elaborate design would be more likely to obscure the ASP code that does the work. Appendix: File Permissions for Internet Information Server

On a home PC that is not connected to the internet, it would be reasonable to trust the user or users not to do anything malicious to the computer or its files. Unfortunately, it is not possible to extend this level of trust to all of the users that could access the files on a PC that is connected to the Internet. Even if you are not running a website, if you are connected to the Internet there are various ways in which the creeps who write computer viruses can get access to files on your system and corrupt or subvert them for their own sleazy ends. As a result of this, operating systems need to provide various means of securing your system and its files against attack, especially where the computer is connected to a network that could allow other people to gain direct or indirect access to the file system. One level of security that is applied to the files on all types of modern operating system is that users need to be granted permission to do specific things with a file – read it, change its contents or, in the case of scripts and executable files, execute it. In a computer that has been installed with a NT-class operating system (Windows NT, 2000 or XP), file permissions are set so that a given file has an ‘owner’ (usually the person who created it) who is able to do anything with a file – delete it, change it, execute it etc. Other users are granted permission to do various things depending on the policies set up by system administrators. In a home PC, usually the person who owns the computer also owns the filing system and has full permission to do as he or she wishes. The owner is the person who can access the PC with ‘administrator permissions’. All other users of the PC are usually granted more restrictive permissions by dint of the administrator giving them a user account and their own password. When you create a website on a PC that has a broadband connection, you are giving other people permission to have access to some of your files. This needs to be very limited access to prevent your website being corrupted by strangers, but you still need to allow internet users to read html files and, if you are running an active website as described in the rest of this document, to execute script files. You don’t know who these users are, and you certainly can not trust them not to make unsafe changes to the files, so usually files on a website are set to give read and execute permission to all internet users.

Establishing Permissions for WWW ‘Guests’

When IIS (Internet Information Server) is installed on a PC running Windows 2000 or XP, a folder is created to host all of the web sites that it is expected to host. This folder is called ‘wwwroot’, and can be found at the location ‘c:\Inetpub\’ on a normal IIS installation. If you locate this folder on an XP system, right-click on it and select Properties from the pop-up menu, you will get the following dialog box:

The wwwroot Properties dialog on the Web Sharing page With the settings for wwwroot shown above, IIS has been given access to the files in this folder. This allows IIS to access any files created in this folder, and confers the same access rights to any folders created within it. However, if you were to create a folder at some other location and then move or copy it into this folder, it would retain its original access rights (which in normal circumstances would prevent IIS from gaining access to files in it. If that was the case, you can set the folder to enable IIS access by clicking on the Share this folder option, and selecting appropriate access rights from the following dialog box: Setting access rights to a folder Note that you have the ability to apply tight control over how access rights are applied – IIS can be given permission to read, write, execute scripts or execute any file (including native executables), and to browse the folders within it. For ASP applications, the only permissions normally required are to Read files and execute Scripts. However, if the folder contains a database (e.g. an Access .mdb file), then Write access would also be required if you intended to allow web users to send information to it, although for this reason it is better to place database files in a separate folder to which Read and Write permissions (but not Execute permission) has been applied.

Summary

Special permission has to be given to files that make up a website so that Internet Information Server is able to read them (for HTML files) and execute them (for ASP files). Specific permissions are set for files in the c:\Inetpub\wwwroot folder (in a normal IIS installation) as follows:  Files that are created in this folder can by default be accessed by IIS

 Folders that are created in wwwroot provide access permissions to files in them in the same way that it does (and the same for folders created within these folders etc.)

 Files in folders that are created elsewhere and then moved or copied to wwwroot can not by default be accessed by IIS. In this case, right-click on the folder, go to the Web Sharing page of the dialog and click on Share this folder to set permissions

 Database files (such as Access MDB files) need to reside in a folder that has been given web sharing permissions for Read and Write access. Note that client-server databases (such as Oracle or SQL Server) manage their own permissions and so there is no need to do anything to provide the correct level of access to them.

Recommended publications