860 likes | 942 Views
第 9 章 ASP.NET 编程实例. 本章力图通过一个网上考试系统实例来讲解如何综合运用 ASP.NET 解决实际问题。 网上考试系统是一个 ASP.NET 和 ADONET 相结合的一个实例,用于完成网上考试的整个流程。即从组卷一直到判卷的整个过程。. 9.1 实例分析与设计. 网上考试系统主要包括注册、登陆、用户管理、组卷、在线考试、成绩查询、试题库管理等功能。 1. 注册的主要功能 *显示注册页面 *用户在线注册 2. 登陆的主要功能 *显示登陆页面 *进行用户验证
E N D
第9章 ASP.NET编程实例 本章力图通过一个网上考试系统实例来讲解如何综合运用ASP.NET解决实际问题。 网上考试系统是一个ASP.NET和ADONET相结合的一个实例,用于完成网上考试的整个流程。即从组卷一直到判卷的整个过程。
9.1 实例分析与设计 网上考试系统主要包括注册、登陆、用户管理、组卷、在线考试、成绩查询、试题库管理等功能。 1. 注册的主要功能 *显示注册页面 *用户在线注册 2. 登陆的主要功能 *显示登陆页面 *进行用户验证 *根据用户权限进入相应模块 3. 用户管理的主要功能 *用户信息录入 *用户信息修改 *用户信息删除 *用户信息查询
4. 组卷的主要功能 *确定试卷名称 *确定试卷考试题类型 *确定试卷考题数目 *确定试卷考题分数 5. 在线考试的主要功能 *根据组卷情况从试题库中随机抽取试题 *给用户的试卷评分 *保存用户考试成绩 6. 成绩查询的主要功能 *查询当前用户的考试成绩 7. 试题库管理的主要功能 *添加试题 *修改试题 *删除试题 *查询试题
9.2 数据库分析与设计 根据系统功能,为网上考试系统设计了四个数据表:试题数据表、试卷数据表、用户数据表、考试分数数据表。 9.2.1 创建数据库 网上考试系统采用Microsoft Access 2000数据库,因此应确保在您的机器上安装有Access2000数据库。 下面是创建数据库的具体步骤: 1. 从开始菜单运行Access2000。 2. 出现如图9-1所示的“Microsoft Access”对话框,选择“Access 数据库向导、数据页和项目”,单击“确定”按钮。
3.出现如图9-2所示“新建”对话框,选择“常用”选项卡,“数据库”项,单击“确定”按钮。3.出现如图9-2所示“新建”对话框,选择“常用”选项卡,“数据库”项,单击“确定”按钮。 图9-2 新建对话框
4. 出现如图9-3所示的“文件新建数据库”对话框。在“文件名”文本框中输入数据库的名字Exam,并选择数据库文件存放位置,这里选择与网页文件存放在同一个文件夹下。单击“创建”按钮,一个空数据库就生成了。 图9-3 文件新建数据库对话框
9.2.2 创建数据表 下面以创建“user1(用户)”数据表为例,演示创建数据表的步骤。User1数据表的基本结构如表9-1所示: 表9-1 User1(用户)表 创建数据表的步骤: 1.双击刚创建的数据库文件Exam.mdb,打开Exam数据库。 2.出现如图9-4所示的“Exam:数据库”对话框,选择左侧“对象”选项,并选择“表”项。双击右侧的“使用设计器创建表”。
3. 出现如图9-5所示的“表”对话框,在“字段名称”栏中输入“UserID”字段名;在“数据类型”栏中选择“自动编号”;在“表”对话框的下部“常规”选项卡的“字段大小”栏中,选择“长整型”;在“新值”栏中,选择“递增”。至此就创建该数据表的“UserID”字段。依照以上步骤,分别创建“UserName”字段、“Pwd”字段、“Demo”字段。在“UserID”字段上右键单击,从弹出的快捷菜单中,选择“主键”,把“UserID”字段设为该表的主键。设计后的结果如图9-6所示。单击工具栏上的“保存”按钮,保存表,并且为表起一个名字“User1”。
依照以上步骤分别创建试题数据表、试卷数据表、考试分数数据表。依照以上步骤分别创建试题数据表、试卷数据表、考试分数数据表。 试题数据表的结构如表9-2所示,试卷数据表的结构如表9-3所示,考试分数表的结构如表9-4所示。 表9-2 Subject(试题)表
表9-4 Score(分数)表 9.2.3 创建查询 为“查询成绩”建立一个查询SubjectScore,以下是创建的步骤: 1. 双击数据库文件Exam.mdb,打开Exam数据库。 2. 出现如图9-4所示的“Exam:数据库”对话框,选择左侧“对象” 选项,并选择“查询”项。双击右侧的“在设计器视图中创建查询”。
3. 在出现的“显示表”对话框中,选中Paper、Score和User1数据表,单击“添加”按钮。单击“关闭”按钮。 4. 出现如图9-7所示的“选择查询”对话框。在对话框的上部,用鼠标右键单击,在出现的快捷菜单中,选择“SQL设计视图”。 5. 在出现的“选择查询”对话框中,输入 SELECT Paper.ExamName AS 考试名称, User1.UserName AS 用户名, Score.Score AS 考试分数 FROM (Paper INNER JOIN Score ON Paper.ExamID = Score.ExamID) INNER JOIN User1 ON Score.UserID = User1.UserID; 6. 单击工具栏上的“保存”按钮,给查询起一个名字SubjectScore。
9.3 主页面 主页面主要完成的功能是:让用户选择是进入登陆页面,还是进入注册页面。 9.3.1 主页面设计 主页面上使用的控件如表9-5所示,运行后的效果如图9-8所示。 表9-5 控件及属性
9.3.2 主页面实现 主页面只使用一个文件main.aspx来实现,具体代码如下: <%@ Page Language="VB" Debug="true" %> <Html> <Head> <Title>网上考试系统</Title> <Script Language="VB" runat="Server"> Sub OnRegister_Click(byval Sender As object,e As Eventargs) Response.Redirect("register.aspx") End Sub Sub OnLogin_Click(byval Sender As object,e As Eventargs) Server.Transfer("default.aspx") End Sub </Script> </Head> <Body> <Form runat="server">
<P> <P> <CENTER> <FONT Size=6 COLOR="Blue">欢迎使用网上考试系统</FONT> <HR><P align="center"> <P> <P> <asp:Button id="Register" Text="新用户注册" OnClick="OnRegister_Click" runat="server" /> <asp:Button id="Login" Text="登 陆" OnClick="OnLogin_Click" runat="server" /> </Form> </Body> </Html> 页面中的Register按钮控件定义了一个按钮单击事件,用于跳转到“注册”页面。在该事件响应程序OnRegister_Click中,使用Response对象的Redirect方法,即: Response.Redirect("register.aspx") 跳转到注册页面。
为Longin按钮控件定义了一个按钮单击事件,用于跳转到“登陆”页面。在该事件响应程序OnLogin_Click中,使用了Server对象的Transfer方法,即:为Longin按钮控件定义了一个按钮单击事件,用于跳转到“登陆”页面。在该事件响应程序OnLogin_Click中,使用了Server对象的Transfer方法,即: Server.Transfer("default.aspx") 跳转到登陆页面。虽然在这两个事件中使用了不同方法,但执行的效果是一样的。 9.4 用户注册 “用户注册”主要完成的功能是:实现用户在线注册功能。 9.4.1 注册页面设计 注册页面上使用的控件如表9-6所示,运行后的效果如图9-9所示。
注册不成功页面如图9-10和图9-11所示。 图9-10 注册不成功页面
注册成功页面上使用的控件如表9-7所示,运行后的效果如图9-12所示。注册成功页面上使用的控件如表9-7所示,运行后的效果如图9-12所示。 表9-7 控件及属性
9.4.2 注册页面实现 注册页面只使用一个文件register.aspx来实现。 1.注册 注册功能主要在“注册”按钮的事件响应函数Button_Click中实现,该函数的具体代码如下: Sub Button_Click(Sender As Object, e As EventArgs) Dim com as OleDbCommand ComStr = "Select UserName From user1 Where UserName='" & Trim(Name.Text) & "'" Com = New OleDbCommand(ComStr,conn) Dim rd as OledbDataReader rd = Com.ExecuteReader() '判断该用户名是否存在 if rd.Read() then rd.close Message.Text="注册失败!此用户名已经有人使用" Message.Text= Message.Text & ",请选择另一个用户名重新注册。" exit sub
else '在User1数据表中记录用户信息 ComStr="insert into user1(UserName,Pwd) values('" & Name.Text ComStr= ComStr & "','" & Pwd.Text & "')" Com = New OleDbCommand(ComStr,conn) rd.close Com.ExecuteNonQuery() conn.close Response.Redirect("regSuccess.aspx") end if End Sub 在函数中,首先根据用户提供的用户名,在用户数据表user1中查询表中该用户名是否存在。如果存在,提示用户“注册失败!此用户名已经有人使用,请选择另一个用户名重新注册。”。如果不存在,则在用户数据表User1中记录该用户信息,并跳转到用户注册成功页面。
2.用户名和密码验证 在注册页面中,“用户名”、“密码”和“确认密码”是必录项。这一功能是通过验证控件RequiredFieldValidator来实现的。 “密码”和“确认密码”要求一致,这一功能是通过验证控件CompareValidator实现的。 3.返回 在注册页面中,没有使用按钮来完成“返回”功能,主要是因为验证控件会发生作用,要求输入“用户名”和“密码”,从而使按钮不能完成“返回”功能。为了解决这一个问题,采用Hyperlink控件,因为他不会向服务器提交表单内容,所以不会触发验证控件的验证功能。如果想使用按钮来完成“返回”功能,必须停用该按钮的验证功能(详见7.1.3)。 4.全部代码 <%@ Import Namespace="system.Data" %> <%@ Import Namespace="system.Data.Oledb" %> <%@ Page Language="VB" Debug="true" %> <HTML> <HEAD> <TITLE>网上考试系统</TITLE>
<Script Language="VB" runat="server"> Dim conn as OleDbConnection Dim conStr,comStr as String Sub Page_Load(Sender As object,e As Eventargs) conStr="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" conStr=conStr & server.mappath("EXAM.MDB") conn = New OleDbConnection(conStr) Conn.Open() End Sub Sub Button_Click(Sender As Object, e As EventArgs) Dim com as OleDbCommand ComStr = "Select UserName From user1 Where UserName='" ComStr = ComStr & Trim(Name.Text) & "'" Com = New OleDbCommand(ComStr,conn) Dim rd as OledbDataReader rd = Com.ExecuteReader() if rd.Read() then rd.close Message.Text="注册失败!此用户名已经有人使用" Message.Text= Message.Text & ",请选择另一个用户名重新注册。" exit sub
else ComStr="insert into user1(UserName,Pwd) values('" ComStr=Comstr & Name.Text & "','" & Pwd.Text & "')" Com = New OleDbCommand(ComStr,conn) rd.close Com.ExecuteNonQuery() conn.close Response.Redirect("regSuccess.aspx") end if End Sub </script> </HEAD> <BODY> <FORM runat="Server"> <p> <p> <CENTER> <FONT size=6 COLOR="Blue">网上考试系统</FONT> <HR><P align="center"> <asp:Label id="Message" Forecolor="Red" runat="server"/><P>
用户名:<asp:TextBox id="Name" runat="server" size="14"/> <asp:RequiredFieldValidator id="NameValid" ControlToValidate="Name" runat="server"> (请输入用户名!) </asp:RequiredFieldValidator><p> 密码: <asp:TextBox id="Pwd" TextMode="Password" runat="server" size="16"/> <asp:RequiredFieldValidator id="PwdValid" ControlToValidate="Pwd" runat="server"> (请输入密码!) </asp:RequiredFieldValidator><p> 确认密码: <asp:TextBox id="RePwd" TextMode="Password" runat="server" size="16"/> <asp:RequiredFieldValidator id="RePwdValid" ControlToValidate="RePwd" runat="server"> (请输入确认密码!) </asp:RequiredFieldValidator><p> <asp:comparevalidator id="comparePwd" controltovalidate="RePwd" controltocompare="Pwd" errormessage="注册失败!密码输入有误。
runat="server"/><P> <asp:Button id="Entry" Text="注 册" Runat="server" OnClick="Button_Click"/> <asp:Hyperlink id="Return" Text="返 回" Runat="server" NavigateUrl="main.aspx"/> </FORM> </CENTER> </BODY> </HTML> 9.5 登陆 “登陆”主要完成的功能是:用户身份确认。它决定用户是否有权限使用系统,如果有权限,则根据用户的权限跳转到相应的页面,完成相应的任务。 9.5.1 登陆页面设计 登陆页面上使用的控件如表9-8所示,运行后的效果如图9-13所示。
9.5.2 登陆页面实现 登陆页面只使用一个文件default.aspx来实现。 1.用户验证和权限判断 使用“登陆”按钮的事件响应函数OnLogin_Click来实现,该函数的具体代码如下: Sub OnLogin_Click(Sender As Object, e As EventArgs) Dim com as OleDbCommand ComStr = "Select Power,UserID From user1 Where UserName='" ComStr=ComStr & Trim(Name.Text) & "' And Pwd='" & Trim(Pwd.Text) & "'" Com = New OleDbCommand(ComStr,conn) Dim rd as OledbDataReader '生成DataReader对象 rd = Com.ExecuteReader() '判断用户是否存在
if not rd.Read() then Label1.Text="用户名、密码有误!" exit sub end if '判断用户权限 if rd.Item(0)="管理员" then Response.Redirect("admin.aspx") else Session("username") = Name.Text Session("pwd") = Pwd.Text Session("userid") = rd.Item(1) Response.Redirect("Exam.aspx") end if End Sub 首先,根据用户名和密码,在用户表user1中查询该用户是否存在。如果不存在,提示“用户名或密码错误”。如果存在,判断用户权限是管理员,还是学生。如果是管理员,则跳转到管理页面。如果是学生,则在会话变量中存储“用户名”、“用户号”和“密码”,并跳转到“考试或查询成绩选择”页面。
2.完整代码 <%@ Import Namespace="system.Data" %> <%@ Import Namespace="system.Data.Oledb" %> <%@ Page Language="VB" Debug="true" %> <HTML> <HEAD> <TITLE>网上考试系统</TITLE> <Script Language="VB" runat="server"> Dim conn as OleDbConnection Dim conStr,comStr as String Sub Page_Load(Sender As object,e As Eventargs) '建立数据库连接 conStr="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" conStr=conStr & server.mappath("EXAM.MDB") conn = New OleDbConnection(conStr) Conn.Open() End Sub Sub OnLogin_Click(Sender As Object, e As EventArgs) Dim com as OleDbCommand ComStr = "Select Power,UserID From user1 Where UserName='"
ComStr=ComStr & Trim(Name.Text) & "' And Pwd='" & Trim(Pwd.Text) & "'" Com = New OleDbCommand(ComStr,conn) Dim rd as OledbDataReader '生成DataReader对象 rd = Com.ExecuteReader() '判断用户是否存在 if not rd.Read() then Label1.Text="用户名、密码有误!" exit sub end if '判断用户权限 if rd.Item(0)="管理员" then Response.Redirect("admin.aspx") else Session("username") = Name.Text Session("pwd") = Pwd.Text Session("userid") = rd.Item(1) Response.Redirect("Exam.aspx") end if End Sub </Script> </HEAD>
<BODY> <FORM runat="Server"> <p> <p> <CENTER> <FONT size=6 COLOR="Blue">网上考试系统</FONT> <HR><P align="center"> <asp:Label id="Bulletin" ForeColor="Blue" runat="server">用户登陆</asp:Label><P> 姓 名:<asp:TextBox id="Name" runat="server" size="14"/> <asp:RequiredFieldValidator id="NameValid" ControlToValidate="Name" runat="server"> (请输入姓名!) </asp:RequiredFieldValidator><p> 密 码:<asp:TextBox id="Pwd" TextMode="Password" runat="server" size="16"/> <asp:RequiredFieldValidator id="PwdValid" ControlToValidate="Pwd"
runat="server"> (请输入密码!) </asp:RequiredFieldValidator><p> <asp:Button id="Login" Text="登 陆" Runat="server" OnClick="OnLogin_Click"/> <asp:Hyperlink id="Return" Text="返 回" Runat="server" NavigateUrl="main.aspx"/> <asp:Label id="label1" runat="server"/> </FORM> </CENTER> </BODY> </HTML>
9.6 在线考试 “在线考试”主要完成的功能是:根据组卷情况从试题库中随机抽取试题;给用户的试卷评分。 9.6.1 考试页面设计 考试页面上使用的控件如表9-9所示,运行后的效果如图9-14所示。
9.6.2 考试页面实现 考试页面只使用一个文件paper.aspx来实现。 1.获取试题参数 在网上考试系统中,实现了“单项选择题”、“多项选择题”和“判断题”考试题型,并能根据考生考试情况自动评分。 为了在考试中,按照要求来抽取试题。必须在“组卷”页面中确定具体要求,即每次考试考什么样的题型、题量、每题分数等。这些要求都保存在Paper数据表中。因此,每次出题时都要查询该表以获取这些信息。这里使用一个过程ReadPaper来实现,具体代码如下: Sub ReadPaper() Dim conn as OledbConnection Dim com as OledbCommand Dim rd As OledbDataReader Dim conStr As String ="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("EXAM.MDB") Dim SQL As String SQL="select type1,number1,score1,type2,number2,score2" SQL=SQL & ",type3,number3,score3,examname,examid from paper " SQL=SQL & " where examdate=(select max(examdate) from paper) " conn = New OleDbConnection(conStr) '建立与Exam数据库的连接 Conn.Open() '生成命令对象
Com = New OledbCommand(SQL,conn) '查询Paper数据表,并把结果放入DataReader中 rd=Com.ExecuteReader() '初始化题目类型 type1="type" type2="type" type3="type" If rd.read() '获取考试名称,并在Label上显示出来 label1.Text=rd.GetString(9) '如果Paper数据表的type1字段不为空,说明有单项选择题 if not rd.IsDbNull(0) then '获取单项选择题 type1=trim(rd.GetString(0)) '获取单选选择题的数目 number1=rd.GetInt16(1) '获取单项选择题的分数 score1=rd.GetFloat(2) end if '如果Paper数据表的type2字段不为空,说明有多项选择题 if not rd.IsDbNull(3) then type2=trim(rd.GetString(3)) number2=rd.GetInt16(4) score2=rd.GetFloat(5) end if
'如果Paper数据表的type3字段不为空,说明有判断题 '如果Paper数据表的type3字段不为空,说明有判断题 if not rd.IsDbNull(6) then type3=trim(rd.GetString(6)) number3=rd.GetInt16(7) score3=rd.GetFloat(8) end if '获取考试号,并存放在会话变量examid中 session("examid")=rd.GetInt32(10) end If rd.close() conn.Close() End Sub 在Paper数据表中,可以保存多个组卷信息,而我们只需要本次考试的组卷信息,因此采用只获取组卷时间离我们最近的记录,即SQL语句中的Where子句: examdate=(select max(examdate) from paper) 然后,判断Paper数据表的题型字段。如果相应的题型字段不为空,则表示考试中有该题型。提取该题型的相应信息。 最后,把考试号保存在会话变量examid中,供程序的其他部分使用。
2.在线考试要求从试题库中随机抽取试题组成试卷,并且用DataList控件显示出来。这就需要为DataList控件动态产生数据源,即创建一个动态表。本系统中,使用两个过程产生动态表,即创建动态表过程CreateTable和创建动态表列过程CreateColumn。2.在线考试要求从试题库中随机抽取试题组成试卷,并且用DataList控件显示出来。这就需要为DataList控件动态产生数据源,即创建一个动态表。本系统中,使用两个过程产生动态表,即创建动态表过程CreateTable和创建动态表列过程CreateColumn。 创建动态表: Sub CreateTable() '生成动态表对象 dt = New DataTable("Paper") '为动态表生成相应列,这些列为SubjectID、question、option1、option2、option3、option4、answer CreateColumn("System.Int32","SubjectID") CreateColumn("System.String","question") CreateColumn("System.String","option1") CreateColumn("System.String","option2") CreateColumn("System.String","option3") CreateColumn("System.String","option4") CreateColumn("System.String","answer") End Sub