Click here to Skip to main content
5,786,882 members and growing! (20,416 online)
Email Password   helpLost your password?
Web Development » ASP.NET » Samples     Intermediate License: The Code Project Open License (CPOL)

Create a guestbook by using XML serialization

By Mikael Sundfors

This article shows an easy way to create a guestbook using ASP.NET and XML serialization.
C# (C# 1.0, C# 2.0, C# 3.0, C#), Windows, .NET, ADO.NET, ASP.NET, Dev

Posted: 23 Nov 2008
Updated: 23 Nov 2008
Views: 22,963
Bookmarked: 16 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
5 votes for this Article.
Popularity: 2.80 Rating: 4.00 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 20.0%
3
2 votes, 40.0%
4
2 votes, 40.0%
5

Introduction

This article shows an easy way to create a guestbook built using ASP.NET and XML serialization. The guestbook is a simple last-entry-last log, and the number of entries is limited to 20. When the 21st entry is submitted, the first one in the list is removed. To format the data, I use the DataList control that comes with Visual Studio .NET. The article is written to demonstrate the following technologies:

  • ASP.NET Web Forms
  • The DataList control
  • XML serialization of objects
  • Generics

The guestbook should be created as a Web Site project in Visual Studio 2005 or 2008. This is how the guestbook will look when it is ready:

The code

The GuestBookEntry class

To start with, we will create a new class file named GuestBookEntry. This class will contain the code for the entries in the guest book. An array of GuestBookEntry objects will be serialized to XML later and stored on the server.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// The class containing data and funtionality for one 
/// guest book entry.
/// </summary>
public class GuestBookEntry
{
    public string Message;
    public string Name;
    public DateTime Date;
    /// <summary>
    /// Public parameterless constructor needed by XML serialization.
    /// </summary>
    public GuestBookEntry() {
    }
    public GuestBookEntry(string message, string name, DateTime date) {
        this.Message = message;
        this.Name = name;
        this.Date = date;
    }
     public override string ToString() {
        return "<b>" + Message + "</b><br>" + "Name: <b>" 
            + Name + "</b><br>" + "Date: "+ Date.ToString();
    }
}

Note the overriding of the ToString() method. In .NET, every class inherits from Object, and therefore inherits implementations of several methods. One of those methods is ToString(), which returns a string that represents the current object. The default implementation isn’t very helpful, though. If you don’t override ToString(), then calling it will return the class name.

In this implementation, we override ToString() in order to get an HTML representation of the GuestBookEntry object.

The GuestBookHandler class

The second class we are going to create is the GuestBookHandler. The main responsibility for this class is to store the guestbook to the server as XML. The class also takes care of limiting the number of entries to 20 and stripping HTML from the entries submitted to the guestbook.

The class contains the following code:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

/// <summary>
/// The GuestBook handler will take care
/// of serializing the GuestBookEntry objects
/// to XML and storing it to the server.
/// </summary>
public class GuestBookHandler
{
    private List<GuestBookEntry> entrys = new List<GuestBookEntry>(); 
    private const string fileName = "App_Data\\GuestBook.xml";
    private const int maxNumberOfEntries = 20;
    private HttpServerUtility server;
    
    public GuestBookHandler(HttpServerUtility serverUtility) 
    {
        server = serverUtility;
        Load(); // Read data from XML file. 
    }

    public GuestBookEntry[] Entrys {
        get { return entrys.ToArray(); } 
    } 
    
    public void Add(string message, string name, DateTime date) 
    {
        if (entrys.Count >= maxNumberOfEntries) {
            entrys.RemoveAt(0); // Remove first entry.
        }
        // Add new entry.
        entrys.Add(new GuestBookEntry(StripHtml(message), StripHtml(name), date));
    }

    
    public string StripHtml(string HTML) {
        // Removes tags from passed HTML           
        System.Text.RegularExpressions.Regex objRegEx 
            = new System.Text.RegularExpressions.Regex("&lt;[^>]*>");
        return objRegEx.Replace(HTML, "");
    }
 
    public void Save() 
    { 
        // Create a new XmlSerializer instance with the type of the test class 
        XmlSerializer serializerObj = new XmlSerializer(entrys.GetType()); 
        
        // Create a new file stream to write the serialized object to a file 
        StreamWriter writeFileStream = new StreamWriter(server.MapPath(fileName));
        serializerObj.Serialize(writeFileStream, entrys); 
        
        // Cleanup 
        writeFileStream.Close(); 
    } 
    
    
    private void Load() 
    { 
        // Create an instance of the XmlSerializer specifying type and namespace. 
        XmlSerializer serializer = new XmlSerializer(typeof(List<GuestBookEntry>)); 
        
        // A FileStream is needed to read the XML document. 
        FileStream fs = null; 
        try {
            fs = new FileStream(server.MapPath(fileName), FileMode.Open); 
        } 
        catch (System.IO.FileNotFoundException) { 
            return; 
            // No entrys to load. 
        } 
        XmlReader reader = XmlReader.Create(fs); 
        
        // Use the Deserialize method to restore the object's state. 
        entrys = (List<GuestBookEntry>)serializer.Deserialize(reader); 
        fs.Close(); 
        
    } 
}

Note the use of generic lists in the source code: List<GuestBookEntry>.

Generics is a new feature introduced with .NET 2.0, which provides type safety at compile time. Generics letd you create data structures without committing to a specific data type in your code at design time. At compile time, the compiler ensures that the types used with the data structure are consistent with type safety. In other words, generics provides type safety, but without any loss of performance or code bloat. Generics is similar to templates in C++, even though the implementation is very different.

The GuestBookHandler class also stores data to the server by using XML serialization. Serialization is the process of persisting an object to disk. Another application can deserialize your object, and it will be in the same state it was before the serialization. This tutorial uses XML serialization. The namespace containing the classes and methods suitable for such a serialization is System.Xml.Serialization.

In order to serialize an object, we first create an XmlSerializer object. We also create a stream that will write to or read from a file. Then, you call the appropriate method of serialization, passing it the stream object you created. To deserialize an XML serialized object you created, you simply call the Deserialize method, passing it the stream that reads from the XML document. The final step is to cast the object into the correct type.

XML provides the following benefits over standard serialization techniques:

  1. Greater interoperability: XML is a text file based format, and all modern Operating Systems and developing environments include libraries for processing such files.
  2. Administrator friendly: by storing objects in XML format, it gives the administrators the opportunity to view and edit XML files. So, an administrator can easily modify your object or troubleshoot problems.
  3. Better forward compatibility: XML-serialized objects are self-described. When you need to replace your application with a newer one, the transition will be straightforward.

The GuestBook.aspx file

The GuestBook.aspx file contains the following HTML code:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="GuestBook.aspx.cs" 
Inherits="GuestBook" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Guestbook</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h1>
            Simple Guestbook</h1>
            
        <asp:DataList ID="DataList1" runat="server" 
                  CellPadding="4" ForeColor="#333333" Width="100%">
            <ItemTemplate> 
                <%# Container.DataItem %> 
            </ItemTemplate>         
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <AlternatingItemStyle BackColor="White" />
            <ItemStyle BackColor="#EFF3FB" />
            <SelectedItemStyle BackColor="#D1DDF1" Font-Bold="True" 
                 ForeColor="#333333" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
        </asp:DataList><br />
        </div>
        Message<br />
 <asp:TextBox ID="txtMessage" runat="server" Height="75px" Width="301px" >
</asp:TextBox><br />
        <br />
    Name<br />
    <asp:TextBox ID="txtName" runat="server" Width="138px"></asp:TextBox>
    <br />
        <br />
        <asp:Button ID="butSubmit" runat="server" Text="Submit" 
        OnClick="butSubmit_Click" />
    </form>
</body>
</html>

Note the following code under the DataList tag.

<asp:DataList ID="DataList1" runat="server" CellPadding="4" Width="305px">
            <ItemTemplate> 
                <%# Container.DataItem %> 
            </ItemTemplate>         
</asp:DataList>

The <%# %> means this is a data binding expression, and Container.DataItem is an alias for the current item in the data source. In other words, when we are binding to a collection of objects, Container.DataItem is the current row of that collection.

The code-behind: Guestbook.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

 
public partial class GuestBook : System.Web.UI.Page 
{
    private GuestBookHandler guestBookHandler;
    protected void Page_Load(object sender, EventArgs e)
    {
        guestBookHandler = new GuestBookHandler(this.Server);
        BindData();
    }
    protected void butSubmit_Click(object sender, EventArgs e) {
        guestBookHandler.Add(txtMessage.Text, txtName.Text, DateTime.Now);
        guestBookHandler.Save();
        txtMessage.Text = "";
        txtName.Text = "";
        // Re-bind data since the data has changed.
        BindData();
    }
    private void BindData() {
        DataList1.DataSource = guestBookHandler.Entrys;
        DataList1.DataBind();
    }
}

Conclusion

As you can see, it is not very difficult to create a guestbook in .NET. This guestbook is a last-entry-last guestbook, and contains the base code for developing your own. With minor changes, this guestbook can be made to a last-entry-first guestbook. All comments and improvement suggestions are welcome.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mikael Sundfors


Mikael Sundfors is a software developer living in Pietarsaari, Finland. He has been working with software development in .NET and in embedded Linux systems for over a decade. He is also a member of the Finnish Microsoft .NET Architect Council.
Occupation: Software Developer (Senior)
Location: Finland Finland

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 4 of 4 (Total in Forum: 4) (Refresh)FirstPrevNext
GeneralMost recent entry to disply firstmemberFiorina8110:13 24 Nov '08  
AnswerRe: Most recent entry to disply firstmemberMikael Sundfors11:48 24 Nov '08  
GeneralCannot enter multiline input.memberAtit Changsan21:55 23 Nov '08  
AnswerRe: Cannot enter multiline input.memberMikael Sundfors23:14 23 Nov '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 23 Nov 2008
Editor: Smitha Vijayan
Copyright 2008 by Mikael Sundfors
Everything else Copyright © CodeProject, 1999-2009
Web13 | Advertise on the Code Project