Creating an XML.NET Guestbook
Your first case study is a simple online guestbook application, completely coded in ASP.NET. You are going to need to provide the basic functions through this guestbook, namely the ability to do the following:
The flowchart in Figure 11.1 shows the user interaction process that you want to achieve.
In essence, the user will come to the site and decide if he or she wants to view previous messages or add new messages. The user will be redirected to the view comments page after filling out a new message, or the user viewing the messages has the option to fill out a message.
The Name, E-mail, Subject Line, and Actual Comment need to be required fields and you need to provide validation for the e-mail field. Also, you need to provide the user with an easy-to-use interface. A basic interface would consist of the user being able to do the following:
Several guestbooks are already available online for download, but most require either a Microsoft Access database or an SQL Server database for storing the guestbook entries and other information pertinent to that guestbook. While both of these tools provide their own strengths and weaknesses, you want to provide an application that is small, quick, and able to stand alone without requiring a separate application to make it work. This type of thought also implies that the application will be small and easy to transfer, if needed. You also need to keep an eye on the code and keep it as small as possible. You need to be able to write directly to the database and read from the database with as little code as possible. Just because you are trying to make the code portable doesn’t mean you need to make the code bloat!
So, if you are not going to use a traditional database (such as Microsoft Access or SQL Server), then what can you use that won’t kill the application requirements? Back in Chapter 8 we talked about a technology that is turning into a strong database alternative, called XML. XML will enable you to use a text-based approach to your database that does not rely on any ODBC connections or even any server (although your code will pretty much lock you into a server that uses ASP.NET). Also, through an XML schema you can define how our XML “row” will look and what each value must contain.
With your backend solution set at XML you need to determine how you are going to work with the XML file. The logical choice is the System.XML namespace, but you can actually find a faster method by using the XML tools that accompany the System.Data namespace. Even though System.XML is more powerful than System.Data when it comes to XML, you simply don’t need to rely on so much coding to see your results.
Even though System.Data is viewed more or less as a method of working with traditional database connections, such as a SQL database or an Access database, it can also work with XML data, provided the XML has an inline schema that it can match the data against; almost like looking at the table structure first and then the data within it.
The file gbook.xml (shown in Figure 11.2, and in the Basic directory on the CD that accompanies this book) displays the XML code that we will be working with.
Lines 1 and 26 have the root tags for the XML file. In this example, we are using “gbook” but you can use anything. Lines 2 through 6 are one line that we used whitespace to organize the attributes in order for the tag to be more readable. The targetNamespace and xmlns attributes in the <xsd:schema> tag are left blank since both the targetNamespace and xmlns are inline. The xsd attribute is pointing to the current schema, and the special Microsoft attribute msdata points to a Microsoft data compatibility namespace.
Lines 8 through 24 construct the element that will store the data. When the data is entered into the corresponding .aspx file, it will format the data within the XML per the data outline within the schema. In this case, a sample entry in our guestbook will appear as the following:
This information will be created by your application through the System.Data namespace. In order to be able to do it, System.Data matches the information input to the inline schema and creates the appropriate record. Now that you have set up the “template,” you can get started with the code that adds records. Refer to Figure 11.3 for the logic behind the XML file.
Any veteran ASP developers are going to notice in this section a distinct change. Remember in desktop applications that you formed your GUIs using a Form? Well, in ASP.NET, the Form has been brought to Web development and is referred to as a Panel. You are going to work with your code inline for just this chapter so that you can get a good grasp of what a Panel looks like and how it works within ASP.NET.
There are no real differences between using a Form for desktop applications and a Panel for online applications. Many of the same subs are intact, such as OnLoad, and Panel can reference any item within the Panel, just like in desktops. A great place to view the Panel in ASP.NET is within the UI for adding guestbook records. Your file will be called add.aspx, and is the code is displayed in Figure 11.4 (note that some lines wrap), and in the Basic directory on the CD that accompanies this book.
It may look daunting at first, but it really is quite simple. Remember that in ASP.NET you first should declare the language the page is going to be using. While it is redundant, since the language declaration on the <script> tag determines the actual language use, it is still a good coding practice to get into. Lines 2 through 4 declare the namespaces that you are going to use—System, System.IO, and System.Data. Lines 5 through 8 just display the HTML code that needs to be in every single HTML page.
You then hit the script tag that controls the Submit button event (lines 9 through 10). For now it’s just a placeholder for the code you’ll be adding in later. Notice that the code is placed at the head of the html file, which means that it will be processed before anything else. You’ll look at the Submit button event after you dissect this portion of the ASP.NET page.
On line 19 of Figure 11.4, pnlAdd is declared; it is the name of the panel that contains the programming code displaying the messages and text boxes that the user will be viewing on the page, in order to enter the guestbook entry data; e.g., the name area, the name entry textbox, the e-mail area, the e-mail entry textbox, the comment area, the comment entry textbox, and the Submit button. In other words, it is your run-of-the-mill HTML form but with ASPX. In reality there are only two “normal” form objects; the name textbox is your standard text object, and the comment area is your standard multilane textbox.
Starting from the top, you find your standard ASPcontrol declaration as a textbox with its default text set to empty and an ID of “E-mail.” Right after it comes the ASP control declaration for RequiredFieldValidator set to validate the control labeled “E-mail” and with a static display. You then implement two types of validation to the field. The first validation is through the RegularFieldValidator control:
All you are doing here is a quick check to see if the field is empty or not. If the user skips the field and leaves it empty, then a little message in red shows up saying that “This is required.” You don’t have to use that text but it works for this example. Our second round of validation begins right after that line with the more intense RegularExpressionValidator object:
You first set the object to bind itself to the E-mail control. It will be analyzing the contents within the E-mail object to see if it falls under the Validation Expression that it has been given; in this case, it checks to see that an “@” symbol as well as a “.” is present within the string. You may want to read up on RegEx to fully understand what variables can be used with Regular Expressions.
All you are doing here is declaring a panel that will show up after a successful guestbook entry has been added to the XML file. The link in order to view the guestbook is declared and set. Very simple and very quick, to the point, starting on line 48 (Figure 11.4):
Now that you have established your design and layout, you can take a look at the code that actually handles the addition of new entries into the guestbook. The basic functionality of this code is to react to the Submit button when pressed, and write the necessary items to the XML file. Figure 11.5 walks you through an overview of the Submit button code.
Line 1 starts you off with your VB code, declaring itself a code segment that is run on the server-side and written using VB. Line 1 uses an ASP.NET form subnamed “AddClick”; this code segment will be providing all of the functionality of the Submit button.
On line 3, you start taking advantage of one of VB’s newest and very useful feature, error trapping. Your try/catch segment starts out by declaring a variable to store the location of your XML file, which can be any directory. You can just assume that for this example it’s in the gb directory on the root folder of the site. With the location of the file stored, you can open up a FileStream object to open and process the XML file for you. FileStream needs to know the actual location of the file (not the virtual location) of the file, so you use Server.MapPath() to return the actual location of the file to your FileStream object, which you can then open (FileMode.Open) and start reading (FileAccess.Read). You can also tell FileStream how to handle other events, such as sharing; by telling FileStream to allow read/write sharing of the file (FileShare.ReadWrite), you don’t have to worry about your XML file suffering from any file locking, which would prevent any other user from editing the file and getting them a nasty error.
With your XML file stored within the fout object (line 10 in Figure 10.5) you can start to create the object that will handle parsing the data, DataType, and properly formatting it and writing to the XML file, DataRow. Specifically, DataType will handle reading the information and transforming it to a table format. DataRow will then use the information stored within your DataType object to create a new row with the columns that it finds within the DataType object. In other words, when DataType reads your XML file, it will see the root element “gbook” as your table, “gbooky” as your rows, and all the information within “gbooky” as columns. It will write the information out accordingly to the XML file. It will know what it’s writing since it’s using the inline schema (Figure 10.2) to write to the file per the schema, using the WriteXML class of the DataType object and having it write the stream matching the XMLSchema (XMLWriteMode. WriteSchema). You then hide the panel that contains the text boxes and Submit button, and make the panel that contains the “Thank You” message. Figures 10.6 and 10.7 show the basic add.aspx file before and after filling out a new entry.
One line of actual ASPX code—that’s about as simple as it gets, and done just by using the built-in XML server control. You may remember in Chapter 3 that ASP.NET has several controls built in to facilitate many different HTML functions, such as displaying radio buttons and handling forms, which allows ASP.NET to generate items fairly on-the-fly. XML is no exception to this rule.
Here is our one-line masterpiece, as shown in Figure 11.8. In essence, all we did to get the sample output shown in Figure 11.8 was just to tell the ASP.NET XML control to read the data in gbook.xml, and to transform it according to the XSL information in gbook.xsl. It is displayed in Figure 11.9 and can be found in the gb folder in the Basic directory on the CD that accompanies this book. Figure 11.10 shows us the output.
because you are working with ASP.NET does not mean that you cannot use its new tricks to come up with some really jazzy items and tweak your XML a bit. Let’s start by looking at your guestbook entry page.
Clearly this is a design point and not a very strong showing of ASP.NET. However, how you design your page is just as vital as how you design a graphical user interface. In this example, I made the design pleasing to the eye, and I try to use a couple of design techniques to lure the user’s eye to the proper areas on the add screen. While these are basic points, it’s a good idea to keep the following in mind:
One of the nice things about ASP.NET controls is that you can still use tags with them. In fact, this second version of my add entry page looks so nice because I’m using a Cascading Style Sheet (CSS) script with it (in the CD that accompanies this book as gbook.css in the Advanced directory). Another part of this new design that you haven’t seen before are the emoticons. Emoticons add a little bit of interactivity to the guestbook by enabling users to pick an image that reflects their “feelings” at the time of posting. You will have to add a couple of changes to the XML file and to the add.aspx file as well as to the view.aspx file in order to display the images. Figure 11.11 will show you how the new add.aspx page will look before and Figure 11.12 after entering a message.
Line 16 in Figure 11.13 reflects the change from the previous XML code; all that happened was just to create a new element of “img” to under complex type “gbook.” Your code will read this value and assign the correct image for it. For right now all you are doing is just preparing the inline schema to support the value so that when you store the data it will know where to put it.
Now for your code; first, you have to add the new row to your Submit button handler at the top in order to include the new Emoticon element within the XML (Figure 11.14).
You don’t really want to display the same boring, old structured output, so try using some tables to break things up a bit. You are going to take a look at this code a bit differently by starting with the page load code (Figure 11.15).
You are telling the server that when the page loads (before ANYTHING else is processed, including HTML) create a dataset (ds) and a filestream (fs) to the XML file. Then you tell the dataset (ds) to read the XML file and bind the information to the “gbook” object with the information contained in the dataset. You close the filestream and finish your initialization code. Your display code has undergone some major changes as well (see Figure 11.16, note that some lines wrap).
Instead of using the asp:xml server control, you are using the Repeater control and a DataSource. Lines 2 and3 have the two namespaces that you are going to need for your script tag. System.IO handles the Filestream object and System.Data handles the DataSource object. The information acquired from the Page_Load sub will generate the information that is bound to the Repeater object. The Repeater object (id=“gbook”) will read the information bound to it, write the header, and then repeat the sequence within the item template until it finishes; then the footer will be written and the asp:repeater object will close. Line 17 shows your only change to the Repeater by adding the link to the image stored by the image tag. The code above plus the graphical add-ons gives you the happy result as seen in Figure 11.17.
Well, we started off with basically nothing and finished up with something that is not only useful but can be pleasing to the eye as well. Hopefully this chapter has introduced some concepts that are useful, not only to your hobby programming but also in your work.
XML and ASP.NET can work well together in a variety of ways: from simple reading and writing to proper design and look. Using a combination of either the System.Data namespace and the ASP server objects, you can create a single-line parsing .aspx page or a more robust page with tables, rows, columns, and different colors and graphics. In order to achieve the best performance available, the System.Data namespace requires an inline schema within the XML file, which the System.Data namespace can reference against when reading or writing XML.
ASP server objects themselves are very flexible in that they can be stand-alone and provide an area to insert inline ASPX code. In the Advanced guestbook, you made heavy use of the inline functions, wrapping table rows and columns around them to provide a view that was readable. Also, by using an inline function you were able to receive the correct image file associated for an emoticon, by placing it within the image html tag. Combined with Cascading Style Sheets (CSS), this method proved capable and provided ample room to grow with.
Even though you can use the XML schema to help determine certain validation points, it is better to have the ASP.NET provide the validation of certain entries, such as e-mail, due to the powerful use of Regular Expressions.
Using System.Data can provide a fast, efficient forward-only read and write solution that is perfect for reading and writing to XML files that are not dependant on heavy node interaction, and that just need information added to them.
The ASP.NET controls are very versatile and efficient. Keep in mind that by combining them with Cascading Style Sheets, their obvious lack of visual aids are easily bypassed for a true eye-candy feel.
Frequently Asked Questions
The following Frequently Asked Questions, answered by the authors of this book, are designed to both measure your understanding of the concepts presented in this chapter and to assist you with real-life implementation of these concepts. To have your questions about this chapter answered by the author, browse to www.syngress.com/solutions and click on the “Ask the Author” form.
A: Add.aspx uses the schema to retrieve the way it needs to write the data to the XML file in the proper order. Say that instead of name before e-mail, you had e-mail before name; add.aspx would write the row with the e-mail field first instead of the name field.
A: .NET expects www.w3.org/1999/XSL/Transform as the XSLT namespace. This does limit you a bit, since the Working Draft version is extremely better than the 1999 version.
A: Unfortunately, some of the error handling for ASP.NET still needs tweaking; this is a perfect example. When running the aspx page, it will spit out errors when it finds them within the asp objects, but is not very good at reporting errors within the subs located within the <head> tag. When you see these errors, check the code and try again.