Click here to Skip to main content
13,861,515 members
Click here to Skip to main content
Add your own
alternative version


138 bookmarked
Posted 19 Jun 2002

Guestbook for ASP.NET

, 19 Jun 2002
Rate this:
Please Sign up or sign in to vote.
An ASP.NET application written from the ground up, that presents a guestbook.

Sample Image - Guestbook.gif



It is a project permitting people to sign a guestbook on a website. The project is built in two parts:

  • Signing the guestbook.
  • Viewing the guestbook.


The guestbook will be stored in an XML file on the server, named guestbook.xml. The encoding of the XML file is changed to ISO-8859-1 to be able to handle special characters. Here is the structure of the XML file:

<?xml version="1.0" encoding="ISO-8859-1" ?>
    <guest private="yes">
        <name>Laurent Kemp?t;/name>

You will be prompted to enter the following information:

  • Name
  • E-Mail
  • Homepage title
  • Homepage URL
  • Location
  • Comments
  • PRIVATE - I only want the web site owner to see my email


To be free to change the way the guestbook is displayed, it is needed to separate the coding from the data. To achieve this requirement, I chose to use XSLT to transform the XML file to an HTML file returned to the client.


The page that will permit people to sign the guestbook is the Web Form called 'Sign.aspx'. This page will require that the user fill some textboxes with information to be displayed on the guestbook. To be able to validate the information, we use RequiredFieldValidator. We also use a RegularExpressionValidator to validate the email address.

When the guest has filled all his information, he presses the Continue button and the page gets back the event in the method ButtonContinue_Click. The method loads the XML database, retrieves the information entered by the guest and adds them at the beginning of the XML file. Then the new database is saved on the server disk and the guest is redirected to the view page.

private void ButtonContinue_Click(object sender, System.EventArgs e)
    //Load guestbook database
    XmlDocument xmldoc = new XmlDocument();
    xmldoc.Load( Server.MapPath("guestbook.xml") );

    //Get private status
    string strPrivate;
    if ( CheckBoxPrivate.Checked )
        strPrivate = "yes";
        strPrivate = "no";

    //Create a new element
    XmlElement elem = xmldoc.CreateElement("guest");
    elem.SetAttribute("private", strPrivate);

    //Add the new guest as the first node

    addTextElement( xmldoc, elem, "name", TextBoxName.Text );
    addTextElement( xmldoc, elem, "email", TextBoxEMail.Text );
    addTextElement( xmldoc, elem, "homepage", TextBoxHomepageTitle.Text );

    XmlAttribute newAttr = xmldoc.CreateAttribute("url");
    newAttr.Value = TextBoxHomepageURL.Text;

    elem.LastChild.Attributes.Append( newAttr );
    addTextElement( xmldoc, elem, "location", TextBoxLocation.Text );
    addTextElement( xmldoc, elem, "comment", TextBoxComments.Text );

    //Write date
    string strDate = DateTime.Now.ToLongDateString() + 
                     " - " + 

    addTextElement( xmldoc, elem, "date", strDate );

    xmldoc.Save( Server.MapPath("guestbook.xml") );


We use the method addTextElement to build the new guest entry into the database:

private void addTextElement( XmlDocument doc, XmlElement nodeParent, 
                             string strTag, string strValue )
    XmlElement nodeElem = doc.CreateElement( strTag );
    XmlText nodeText = doc.CreateTextNode( strValue );
    nodeParent.AppendChild( nodeElem );
    nodeElem.AppendChild( nodeText );


To view all guestbook entries, we add another Web Form called 'View.aspx' to the project. In the Page_Load method of the page, we load the XML database and the XSLT file. We do the transformation and output the result in a Literal Web Form control.

private void Page_Load(object sender, System.EventArgs e)
    //Load guestbook database from the xml file
    XmlDocument doc = new XmlDocument( );
    doc.Load( Server.MapPath("guestbook.xml") );

    // Get the page number asked
    string strPageAsked = Request.QueryString["page"];

    // If the page is not defined then set it to first one
    if ( strPageAsked == null )
        strPageAsked = "1";

    int nGuestPerPage = 5;
    int nGuests = doc.ChildNodes[1].ChildNodes.Count;

    int nPageAsked = System.Convert.ToInt32(strPageAsked);

    int lowerbound = 1 + ( nPageAsked - 1 ) * nGuestPerPage;
    int upperbound = lowerbound + nGuestPerPage - 1;

    //Do XSLT transformation
    XslTransform xslt = new XslTransform();
    xslt.Load( Server.MapPath("guestbook.xslt") );

    //Build XLST Param list
    XsltArgumentList xsltArgs = new XsltArgumentList();
    xsltArgs.AddParam("lowerbound", "", lowerbound.ToString());
    xsltArgs.AddParam("upperbound", "", upperbound.ToString());

    //Transform XML to HTML
    MemoryStream ms = new MemoryStream();
    xslt.Transform( doc, xsltArgs, ms );
    ms.Seek( 0, SeekOrigin.Begin );

    StreamReader sr = new StreamReader(ms);

    //Insert result in the View.aspx page
    LiteralGuests.Text = sr.ReadToEnd();

    //Insert the pages navigator at the bottom of the page
    int nPages = 0;
    if (( nGuests % nGuestPerPage) != 0 )
        nPages = 1 + (nGuests / nGuestPerPage);
        nPages = (nGuests / nGuestPerPage);

    LiteralGuests.Text += "Page(s) ";

    for (int n = 1; n <= nPages; n++)
        LiteralGuests.Text += "<font face='verdana' size='2'>"
        LiteralGuests.Text += "<a href='/Guestbook/View.aspx?page=";
        LiteralGuests.Text += n.ToString();
        LiteralGuests.Text += "'>";
        LiteralGuests.Text += n.ToString();
        LiteralGuests.Text += "</a></font> ";


All transformation from XML to HTML is done in the guestbook.xslt file. This transformation requests two parameters: lowerbound and upperbound, representing the lower and upper indexed values according to the guestbook page to display. Basically, what we do is to loop from lower bound to upper bound and do the transformation:


  select="//guest[position() <= $upperbound and position() >= $lowerbound]">
    <xsl:apply-templates select="name"/>

This is, for example, the transformation used to display a guest with its email, if it is not defined as private:

<xsl:template match="name">
        <xsl:when test="../@private='yes'">
            <font face="verdana" size="2">
                <b><xsl:value-of select='.' /></b>
            <font face="verdana" size="2">
                <b><a HREF="mailto:{../email}"><xsl:value-of select='.' ></a></b>

You may look at the file guestbook.xslt for further details.


I would say that you gain to separate data from processes, and in this matter, XML helps a lot. If you would like to change the looks of the guestbook view, you need only to change the guestbook.xslt file.

Problems Faced

  • None.


  • Version 1.00 - May 30 2002

    First release.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Laurent Kempé
Team Leader
France France
I am an experienced Team Leader & Senior Solutions Architect with a passion for shipping high-quality products by empowering development team and culture toward an agile mindset. I bring technical vision and strategy, leading engineering teams to move product, processes and architecture forward.

You may also be interested in...

Comments and Discussions

QuestionMessage Closed Pin
27-Oct-17 0:37
memberMember 1348882227-Oct-17 0:37 
Praisethank you Pin
Muhammet Raşit Coşgun19-Dec-15 6:16
memberMuhammet Raşit Coşgun19-Dec-15 6:16 
GeneralSync Issue Pin
Arch4ngel16-Mar-06 9:25
memberArch4ngel16-Mar-06 9:25 
Generalthank you very much Pin
JonXiang15-Jan-06 3:43
memberJonXiang15-Jan-06 3:43 
GeneralRe: thank you very much Pin
ruhan0077-May-07 10:08
memberruhan0077-May-07 10:08 
GeneralJust a thank you Pin
donrus12-Jan-06 15:48
memberdonrus12-Jan-06 15:48 
Generaldon't support unicode Pin
playhere16-Aug-05 22:41
memberplayhere16-Aug-05 22:41 
QuestionXMl-file is public? Pin
Member 219399414-Aug-05 5:28
memberMember 219399414-Aug-05 5:28 
AnswerRe: XMl-file is public? Pin
Simone Busoli15-Dec-05 15:16
memberSimone Busoli15-Dec-05 15:16 
Generaltest Pin
Anonymous31-Jul-05 22:15
memberAnonymous31-Jul-05 22:15 
GeneralAccess path denied Pin
TarteredSalmon21-Apr-05 14:07
memberTarteredSalmon21-Apr-05 14:07 
GeneralRe: Access path denied Pin
Laurent Kempé21-Apr-05 21:10
memberLaurent Kempé21-Apr-05 21:10 
GeneralRe: Access path denied Pin
Ludwig Boucherie11-Jul-05 19:24
sussLudwig Boucherie11-Jul-05 19:24 
GeneralRe: Access path denied Pin
Darius Odin11-Jul-05 19:25
sussDarius Odin11-Jul-05 19:25 
QuestionHow shield the html tags? Pin
os58615-Apr-04 17:37
memberos58615-Apr-04 17:37 
GeneralGuestbook application Pin
LanChi Tran25-Mar-04 18:05
memberLanChi Tran25-Mar-04 18:05 
GeneralRe: Guestbook application Pin
os58615-Apr-04 17:04
memberos58615-Apr-04 17:04 
GeneralRe: Guestbook application Pin
Bård Eik7-Jul-05 23:52
memberBård Eik7-Jul-05 23:52 
GeneralRe: Guestbook application Pin
Chs Boschen11-Jul-05 19:24
sussChs Boschen11-Jul-05 19:24 
GeneralSimple Question! Pin
kedar_a23-Mar-04 6:33
memberkedar_a23-Mar-04 6:33 
QuestionWhat if... Pin
Lars-Inge Tønnessen25-Oct-03 15:02
memberLars-Inge Tønnessen25-Oct-03 15:02 
AnswerRe: What if... Pin
Laurent Kempé28-Oct-03 9:54
memberLaurent Kempé28-Oct-03 9:54 
GeneralRe: What if... Pin
Lars-Inge Tønnessen30-Oct-03 8:56
memberLars-Inge Tønnessen30-Oct-03 8:56 
GeneralRe: What if... Pin
Frans Diva11-Jul-05 19:24
sussFrans Diva11-Jul-05 19:24 
GeneralRe: What if... Pin
Luis90911-Jul-05 19:24
memberLuis90911-Jul-05 19:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190214.1 | Last Updated 20 Jun 2002
Article Copyright 2002 by Laurent Kempé
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid