65.9K
CodeProject 正在变化。 阅读更多。
Home

使用XML序列化创建一个留言簿

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (11投票s)

2008年11月23日

CPOL

4分钟阅读

viewsIcon

144729

downloadIcon

488

本文介绍了一种使用 ASP.NET 和 XML 序列化创建留言簿的简便方法。

引言

本文介绍了一种使用 ASP.NET 和 XML 序列化构建留言簿的简便方法。该留言簿是一个简单的“后进后出”日志,条目数量限制为 20 条。当提交第 21 条条目时,列表中的第一条将被删除。为了格式化数据,我使用了 Visual Studio .NET 自带的 DataList 控件。本文旨在演示以下技术:

  • ASP.NET Web Forms
  • DataList 控件
  • 对象的 XML 序列化
  • Generics

留言簿应在 Visual Studio 2005 或 2008 中创建一个网站项目。以下是完成后的留言簿外观:

Guestbook.JPG

代码

GuestBookEntry 类

首先,我们将创建一个名为 GuestBookEntry 的新类文件。该类将包含留言簿条目的代码。稍后,GuestBookEntry 对象的数组将被序列化为 XML 并存储在服务器上。

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

/// <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;
    public string IPAddress;

    /// <summary>
    /// Public parameterless constructor required by XML serialization.
    /// </summary>
    public GuestBookEntry()
    {
    }

    public GuestBookEntry(string message, string name, DateTime date, string ipAddress)
    {
        this.Message = message;
        this.Name = name;
        this.Date = date;
        this.IPAddress = ipAddress;
    }

    public override string ToString()
    {
        return "<b>" + Message + "</b><br>" + "Name: <b>"

            + Name + "</b><br>" + "Date: " + Date.ToString();
    }
}

请注意对 ToString() 方法的重写。在 .NET 中,每个类都继承自 Object,因此继承了多个方法的实现。其中一个方法是 ToString(),它返回一个代表当前对象的字符串。但是,默认实现并不是很有用。如果您不重写 ToString(),调用它将返回类名。

在此实现中,我们重写了 ToString() 以获得 GuestBookEntry 对象的 HTML 表示形式。我们还为每个条目存储了提交者的 IP 地址。此信息未在留言簿中显示,但可用于在留言簿被篡改时阻止特定地址。

GuestBookHandler 类

我们将创建的第二个类是 GuestBookHandler。该类的主要职责是将留言簿以 XML 格式存储到服务器。该类还负责将条目数量限制为 20 条,并将文本编码为 HTML(将换行符替换为 <br />)。

该类包含以下代码:

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;
using System.Web.Hosting;

/// <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";
    // Configurable number of entries in the log.
    private const int maxNumberOfEntries = 20;
    // Static object used for locking critical section.
    private static object writeLock = new object();

    public GuestBookHandler() 
    {
        Load(); // Read data from XML file. 
    }

    // Returns array of Guestbook entries to presentation layer.
    public GuestBookEntry[] Entrys {
        get { return entrys.ToArray(); } 
    } 
    
    // Method to add a guestbook entry.
    public void Add(string message, string name, DateTime date, string ipAddress) 
    {
        if (entrys.Count >= maxNumberOfEntries) {
            entrys.RemoveAt(0); // Remove first entry.
        }
        // Add new entry.
        GuestBookEntry ge = new GuestBookEntry(message.Replace(Environment.NewLine,
            "<br />"),
            name, date, ipAddress);
        entrys.Add(ge);
    }
 
    public void Save() 
    {
        // Use shared lock to assure only one user at a time
        // has access to the file for writing.
        lock(writeLock) {
            // 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 = null;
            try {
                string mappedPath = HostingEnvironment.MapPath(fileName);
                writeFileStream = new StreamWriter(mappedPath);
                serializerObj.Serialize(writeFileStream, entrys);
                writeFileStream.Flush();
            }
            finally {
                // Cleanup 
                if (writeFileStream != null) {
                    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 {
            try {
                fs = new FileStream(HostingEnvironment.MapPath(fileName), FileMode.Open);
            }
            catch (System.IO.FileNotFoundException) {
                // No entrys to load.
                return; 
            }
            XmlReader reader = XmlReader.Create(fs);

            // Use the Deserialize method to restore the object's state. 
            entrys = (List<GuestBookEntry>)serializer.Deserialize(reader);
        }
        finally {
            if (fs != null) {
                fs.Close();
            }
        }
    } 
}

请注意源代码中使用泛型列表:List<GuestBookEntry>

泛型是 .NET 2.0 引入的一项新功能,它在编译时提供了类型安全性。泛型允许您创建数据结构,而不必在设计时将代码指定为特定数据类型。在编译时,编译器会确保与数据结构一起使用的数据类型符合类型安全。换句话说,泛型在不损失性能或代码臃肿的情况下提供了类型安全。泛型类似于 C++ 中的模板,尽管实现方式大不相同。

GuestBookHandler 类还使用 XML 序列化将数据存储到服务器。序列化是将对象持久化到磁盘的过程。另一个应用程序可以反序列化您的对象,它将处于序列化之前的状态。本教程使用 XML 序列化。包含适用于此类序列化的类和方法的命名空间是 System.Xml.Serialization

为了序列化一个对象,我们首先创建一个 XmlSerializer 对象。我们还创建一个将写入或读取文件的流。然后,调用适当的序列化方法,将您创建的流对象传递进去。要反序列化您创建的 XML 序列化对象,只需调用 Deserialize 方法,将从 XML 文档读取的流传递进去。最后一步是将对象强制转换为正确的类型。

与标准序列化技术相比,XML 提供了以下优势:

  1. 互操作性更强:XML 是一种基于文本文件的格式,所有现代操作系统和开发环境都包含处理此类文件的库。
  2. 对管理员友好:通过以 XML 格式存储对象,管理员有机会查看和编辑 XML 文件。因此,管理员可以轻松修改您的对象或排除故障。
  3. 更好的前向兼容性:XML 序列化的对象是自描述的。当您需要用新版本替换应用程序时,过渡将非常顺利。

GuestBook.aspx 文件

GuestBook.aspx 文件包含以下 HTML 代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GuestBook.aspx.cs"
    Inherits="GuestBook" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</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" 
        TextMode="MultiLine"></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>

请注意 DataList 标记下的以下代码。

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

</asp:DataList>

<%# %> 表示这是一个数据绑定表达式,Container.DataItem 是数据源中当前项的别名。换句话说,当我们将数据绑定到对象集合时,Container.DataItem 就是该集合中的当前行。

代码隐藏:Guestbook.aspx.cs

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

public partial class GuestBook : System.Web.UI.Page
{
    private GuestBookHandler guestBookHandler;

    protected void Page_Load(object sender, EventArgs e)
    {
        guestBookHandler = new GuestBookHandler();
        BindData();
    }

    protected void butSubmit_Click(object sender, EventArgs e)
    {
        if (txtMessage.Text != "" && txtName.Text != "") {
            guestBookHandler = new GuestBookHandler();
            guestBookHandler.Add(txtMessage.Text,
                txtName.Text, DateTime.UtcNow, 
                HttpContext.Current.Request.UserHostAddress);
            guestBookHandler.Save();
            txtMessage.Text = "";
            txtName.Text = "";
            // Re-bind data since the data has changed.
            BindData();
        }
    }

    private void BindData()
    {
        DataList1.DataSource = guestBookHandler.Entrys;
        DataList1.DataBind();
    }
}

结论

如您所见,在 .NET 中创建一个留言簿并非难事。此留言簿基于 XML 序列化,是一个“后进后出”的留言簿。它可以作为开发您自己具有更高级功能的留言簿的基础代码。稍作修改,此留言簿也可以实现“先进先出”的功能。欢迎所有评论和改进建议。

历史

  • 2008年11月22日:文章首次发布。
  • 2009年1月14日:更新以支持输入中的换行符并改进了错误处理。
© . All rights reserved.