ASP.NET是微软公司.Net框架中用以开发Web程序的主要的语言,由于ASP.NET融合C#和VB.NET等其他的.Net开发语言,并且在ASP.NET页面可以为页面中组件定义相应事件。更为重要的,ASP.NET和其前辈ASP相比,摆脱了服务器端脚本语言的局限,成为了一种Web上程序开发的编译语言,这些就使得用ASP.NET编写Web程序,无论是灵活性,还是页面的执行速度有了空前的提高。因此ASP.NET正在受到越来越多程序员欢迎。
留言本是一个非常有用的Web程序,在留言本中,访问者可以来发表自己的意见,并且还可以用以信息的发布和交流。在互联网上,曾经看过用其他语言编写的各种留言本,有些功能强大,有些短小精干、非常实用。但无论那一种,构建留言本的程序都非常多,一般都有,浏览留言本程序、删除留言程序、插入留言程序等。本文介绍的用ASP.NET作的留言本,将充分利用ASP.NET的强大功能,只用一个"guestbook.aspx"程序,就可以完成需要多个程序的功能。
用ASP.NET编写留言本,其实就是ASP.NET利用ADO.NET解决实际问题的一个应用,其归根到底其实质是ASP.NET数据库编程。因为发表留言,其实就是在数据表中插入一条留言记录;删除留言,就是在数据表中删除指定的留言记录;而查看留言,其实就是如何显示数据表中的记录。所以作者希望,在本文讲述完毕之后,读者能够对ASP.NET进行数据库编程有了更深的了解。下面就来介绍ASP.NET编写留言本的具体步骤。
一.本文中程序设计及运行环境
(1).微软视窗2000 服务器版
(2)..Net Framework SDK 正式版
二.编写留言本所用的数据库和数据字典:
为了更方便的程序发布,本留言本采用了本地数据库--Access 2000,数据库的结构也非常简洁,只有一张数据表"Guestbook",数据表的结构也很明了,总共只有5个字段,而这些字段都是编写留言本所必须得,具体如下表:
字段名称 字段类型 说明
No 自动编号 留言编号,是主键
Date 日期/时间 留言时间
Name 文本 留言人名字
EMail 文本 留言人邮件地址
Text 备注 留言内容
三.ASP.NET编写留言本的关键步骤以及实现:
正如上文所说,ASP.NET编写留言本的过程,其实就是ASP.NET对数据库操作的过程。其中最为关键的几个步骤是:发表留言、删除留言、显示留言(其中包括分页显示)。
(1).发表留言:
在程序中,通过一个标示位来确定页面所处的状态,在整个程序中,页面所处的状态共分成4种:插入状态,也就是发表留言;正常状态,也就是正常的留言显示、浏览状态;删除状态,就是删除留言;管理状态,这是留言本管理者所处的状态,可以管理整个留言本。所以在发表留言之前,首先要设定标示位为"插入状态",然后再通过ADO.NET往数据库中插入一条留言,最后再通过页面重定向到普通状态,这样插入的留言才能显示出来。下面是具体实现代码:
//页面状态判断
if ( HasMode ( MODE_INSERT ) )
{
//插入留言
try
{
string name = Request [ "gb_name" ] ;
string email = Request [ "gb_email" ] ;
string text = Request [ "gb_text" ] ;
OleDbConnection conn = new OleDbConnection( DB_STR );
OleDbDataAdapter da = new OleDbDataAdapter ( "SELECT * FROM Guestbook" , conn ) ;
OleDbCommandBuilder cb = new OleDbCommandBuilder ( da );
cb.QuotePrefix = "[" ;
cb.QuoteSuffix = "]" ;
DataSet ds = new DataSet ( ) ;
da.Fill ( ds );
DataTable table = ds.Tables [ 0 ] ;
DataRow row = table.NewRow ( ) ;
row["Date"] = DateTime.Now ;
row["Name"] = name ;
row["EMail"] = email ;
row["Text"] = text ;
table.Rows.Add ( row ) ;
da.Update( ds ) ;
conn.Close ( ) ;
}
catch ( Exception e )
{
Response.Redirect ( "插入留言出错!" , true ) ;
return ;
}
//页面重定向到普通状态
Response.Redirect( NormalUrl ( ) , true );
return ;
}
注释:代码中HasMode和NormalUrl分别是状态判断函数和获得普通状态的URL函数,DB_STR是连接数据库的字符串。
(1).删除留言:
和发表留言差不多,首先要确定页面所出的是删除状态,然后通过留言所在数据库的编号,删除指定的留言,然后再通过重定向,刷新页面。下面是具体实现代码:
if ( HasMode ( MODE_DELETE ) )
{
try
{
int id = Convert.ToInt32( Request [ "id" ] ) ;
OleDbConnection conn = new OleDbConnection( DB_STR ) ;
conn.Open ( ) ;
OleDbCommand cmd = new OleDbCommand ( "DELETE FROM Guestbook WHERE [No]=" + id , conn ) ;
cmd.ExecuteNonQuery ( ) ;
conn.Close ( ) ;
}
catch ( Exception e )
{
Response.Redirect ( " 错误删除: " + e.Message , true ) ;
return ;
}
Response.Redirect ( NormalUrl ( ) , true ) ;
return ;
} 在本文中的程序中,一般用户和管理者的区别并没有采用其他的留言本中经常使用的,利用数据库的方法来实现,而是采用了一种比较简单的方法,在平常的状态下,留言本认为使用者都是一般用户,只可以发表留言,并不可以删除留言,留言本认定使用者是的管理者,是通过修改URL中的"mode"参数来实现的,当把"mode"的值改成"16",留言本就认为现在是管理者来操作留言本,也就可以看到了图01所示的界面。留言本的管理者"口令"可以通过修改程序代码中的"MODE_ADMIN"值来实现。具体可参考后面的完整代码清单。
(3).显示留言:
为了使访问者能够更直观的浏览留言,在本文中,对留言采用了二种方式的页面导航,其一:不是直接的进入页面,而是通过"下一页"、"上一页"等来循序的浏览。其二:列出所有页面,读者可以直接进入相应页面进行浏览。具体的试样可以参照图01中的头部的页面导航区。
实现这二种不同的数据导航的具体思路是:首先要得到留言本中的所有留言数目,然后得到要把这些留言分成多少页面。在程序中有一个参数HITS_PER_PAGE",它的主要作用是设定每一页显示的留言数目,读者可以通过修改它来设定每一页中显示留言的数目。在下面程序中,我们设定的是每一页显示3条留言,但实际应用中,一般把此值设定为"10"或者"15"。在得到了这二个关键的数值后,显示留言主要是根据当前页面的序号来实现的,当前页面序号在程序中,通过一个整型"cur_page"来确定。在第一次访问留言本的时候,"cur_page"值为"1"。在得到当前页面的序号和每一页设定的留言数目后,就可以通过当前页面序号得到要显示的留言。并通过一个循环显示当前页面所包括的留言。由于实现代码较长,这里就不给具体代码了,读者可以参考下面的留言本的完整代码,里面有具体介绍。
四.用ASP.NET打造留言本的完整代码(guestbook.aspx):
上面的三个步骤对编写一个完整的留言本是至关重要的。下面是ASP.NET编写的留言本的完整代码,是总结了上面的三个步骤后,编写出来的,具体如下:
<%@ Page Language = "C#" %>
<%@ Import Namespace = "System.Data" %>
<%@ Import Namespace = "System.Data.OleDb" %>
<%
//判断页面所处的状态,缺省为普通状态
if ( Request [ "mode" ] == null )
{
Mode = MODE_NORMAL ;
}
else
{
Mode = Convert.ToInt32 ( Request [ "mode" ] ) ;
}
//页面状态判断
if ( HasMode ( MODE_INSERT ) )
{
//插入留言
try
{
string name = Request [ "gb_name" ] ;
string email = Request [ "gb_email" ] ;
string text = Request [ "gb_text" ] ;
OleDbConnection conn = new OleDbConnection( DB_STR );
OleDbDataAdapter da = new OleDbDataAdapter ( "SELECT * FROM Guestbook" , conn ) ;
OleDbCommandBuilder cb = new OleDbCommandBuilder ( da );
cb.QuotePrefix = "[" ;
cb.QuoteSuffix = "]" ;
DataSet ds = new DataSet ( ) ;
da.Fill ( ds );
DataTable table = ds.Tables [ 0 ] ;
DataRow row = table.NewRow ( ) ;
row["Date"] = DateTime.Now ;
row["Name"] = name ;
row["EMail"] = email ;
row["Text"] = text ;
table.Rows.Add ( row ) ;
da.Update( ds ) ;
conn.Close ( ) ;
}
catch ( Exception e )
{
Response.Redirect ( "插入留言出错!" , true ) ;
return ;
}
//页面重定向到普通状态
Response.Redirect( NormalUrl ( ) , true );
return ;
}
// 删除指定的留言
if ( HasMode ( MODE_DELETE ) )
{
try
{
int id = Convert.ToInt32( Request [ "id" ] ) ;
OleDbConnection conn = new OleDbConnection( DB_STR ) ;
conn.Open ( ) ;
OleDbCommand cmd = new OleDbCommand ( "DELETE FROM Guestbook WHERE [No]=" + id , conn ) ;
cmd.ExecuteNonQuery ( ) ;
conn.Close ( ) ;
}
catch ( Exception e )
{
Response.Redirect ( " 错误删除: " + e.Message , true ) ;
return ;
}
Response.Redirect ( NormalUrl ( ) , true ) ;
return ;
}
//下面是实现页面导航
//打开数据库,并以留言发表的降序排列
OleDbConnection myconn = new OleDbConnection ( DB_STR ) ;
OleDbCommand mycmd = new OleDbCommand ( "SELECT * FROM Guestbook ORDER BY [Date] DESC" , myconn ) ;
OleDbDataAdapter myda = new OleDbDataAdapter ( ) ;
myda.SelectCommand = mycmd ;
DataSet myds = new DataSet ( ) ;
myda.Fill ( myds ) ;
myconn.Close ( ) ;
DataTable Table = myds.Tables [ 0 ] ;
//得到所有留言的数目
int sum_cnt = Table.Rows.Count ;
int cur_page ;
if ( Request [ "pg" ] == null )
cur_page = 0 ;
else
cur_page = Convert.ToInt32 ( Request [ "pg" ] ) ;
//得到所有页面数目
int total_pages = sum_cnt / HITS_PER_PAGE ;
if ( sum_cnt % HITS_PER_PAGE > 0 && sum_cnt > HITS_PER_PAGE )
total_pages++ ;
if ( total_pages <=0 )
total_pages = 1 ;
int hit_display_start = 1+cur_page * HITS_PER_PAGE ;
int hit_display_end = hit_display_start + Math.Min ( sum_cnt , HITS_PER_PAGE ) - 1 ;
if ( hit_display_end > sum_cnt ) hit_display_end = sum_cnt ;
int cntdwn_start = sum_cnt - hit_display_start + 1 ;
int cntdwn_end = sum_cnt - hit_display_end + 1 ;
//设定标示位,以确定显示不同的导航连接
bool can_prev_page = cur_page > 0 ;
bool can_next_page = cur_page < total_pages - 1 ;
bool can_prevornext_page = can_prev_page || can_next_page ;
bool can_first_page = can_prevornext_page && cur_page > 0 ;
bool can_last_page = can_prevornext_page && cur_page < total_pages - 1 ;
int table_index = hit_display_start - 1 ;
%>
请您留言
总共有 <%= sum_cnt %> 个留言.
页次: <%= cur_page + 1 %> / <%= total_pages %> 页 ,
从 <%= cntdwn_end %> 到 <%= cntdwn_start %> .
//页面导航试样一
<% if ( can_first_page ) { %>">首页 <%}%>
<% if ( can_prev_page ) { %> ">上一页<%}%>
<% if ( can_next_page ) { %>">下一页 <%}%>
<% if ( can_last_page ) { %>">尾页 <%}%>
//页面导航试样二
<%
for ( int i = 1 ; i <= total_pages ; ++i )
{
%>
"><%= i %>  
<%
}
%>
//显示当前选定导航页面的留言
<%
int cntdwn = cntdwn_start ;
int cnt = 0 ;
while ( table_index < Table.Rows.Count && cnt < HITS_PER_PAGE )
{
cnt++ ;
DataRow row = Table.Rows [ table_index ] ;
bool e = row [ "EMail" ] != null ;
%>
<%= cntdwn %> . <% if ( e ) {%> "
href = "mailto : <%= row [ "EMail" ] %> " > <% } %> <%= row [ "Name" ] %> <% if ( e ) { %> <% } %> : <%= row [ "Date" ] %>
<% if ( HasMode ( MODE_ADMIN ) ) {%> " >删除留言 <% } %>
<%= row [ "Text" ] %>
<%
cntdwn-- ;
table_index++ ;
}
%>
请您留言
下图是留言本处于正常浏览状态下,所示的界面。在正常状态下,访问者是不能删除留言的,只能发表留言.
五.总结:
通过编写网络留言本,可以让我们对在ASP.NET中操作数据库有更深的了解。由于篇幅所致,本文的留言本在美工方面没有更多的修饰。如果读者感兴趣,可以方便的实现像其他留言本那样,为每一个留言加入一个漂亮的图片。下面是一个具体的思路。首先修改Guestbook数据表的数据字典,在其中加入一个图片名称字段,这个字段就用来存放留言所对于的图片名称。当发表留言的时候,不仅要在数据表中插入上文中的那些数据,还要把留言所选择的的图片名称写入到图片名称字段中。而当显示留言的时候,就可以通过读取图片名称字段的值,得到留言的图片的文件名称,并通过新加入的"Image"组件,把留言所选择的图片显示出来。当然这只是美工中的一个方面,要想更加完美,还有很多的具体的细节工作要做,希望读者和我一起来完成这个工作。
|