我是ASP.NET的新手,我刚刚开发了一个简单的在线考试门户来学习。我使用了ADO.NET,MySQL,并在VS 2010中开发。
我有一个登录页面,用户可以在其中登录并为新用户注册。成功登录后,用户将被重定向到问题页,我从数据库中获取第一个问题。我在标签中填写了问题,在单选按钮列表中填充了选项。用户可以选择一个选项并单击“下一步”按钮。在“下一步”按钮的单击事件中,我计算标记。我只存储会话中的所有值。当用户单击最后一个问题的下一个(即4个用户)时,将重定向到结果页并打印标记。
public partial class Questions : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
Response.Cache.SetNoStore();
if (!IsPostBack)
{
renderQuestions(1);
Session["buttonIndex"] = 1;
Session["Marks"] = 0;
}
}
public void renderQuestions(int index)
{
MySqlConnection con = null;
string conString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
string qry = "SELECT * FROM QUESTIONS WHERE QUESTION_ID="+index+"";
try
{
using (con = new MySqlConnection(conString))
{
con.Open();
using (MySqlCommand cmd = new MySqlCommand(qry, con))
{
using (MySqlDataAdapter ada = new MySqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
ada.Fill(dt);
if (dt.Rows.Count > 0)
{
clsQuestion ques = new clsQuestion();
ques.QuestionId = Convert.ToInt32(dt.Rows[0][0]);
ques.Question = Convert.ToString(dt.Rows[0][1]);
ques.Option1 = Convert.ToString(dt.Rows[0][2]);
ques.Option2 = Convert.ToString(dt.Rows[0][3]);
ques.Option3 = Convert.ToString(dt.Rows[0][4]);
ques.Option4 = Convert.ToString(dt.Rows[0][5]);
ques.Answer = Convert.ToInt32(dt.Rows[0][6]);
renderQuesAndAnswers(ques);
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
}
public void renderQuesAndAnswers(clsQuestion quest)
{
lblQuestion.Text = quest.Question;
RadioButtonList1.Items.Clear();
RadioButtonList1.Items.Add(quest.Option1);
RadioButtonList1.Items.Add(quest.Option2);
RadioButtonList1.Items.Add(quest.Option3);
RadioButtonList1.Items.Add(quest.Option4);
Session["QuestionNumber"] = quest.QuestionId ;
Session["Answer"] = quest.Answer;
}
public class clsQuestion
{
private int questionId;
private string question;
private string option1;
private string option2;
private string option3;
private string option4;
private int answer;
public int QuestionId
{
get { return questionId; }
set { questionId = value; }
}
public string Question
{
get { return question; }
set { question = value; }
}
public string Option1
{
get { return option1; }
set { option1 = value; }
}
public string Option2
{
get { return option2; }
set { option2 = value; }
}
public string Option3
{
get { return option3; }
set { option3 = value; }
}
public string Option4
{
get { return option4; }
set { option4 = value; }
}
public int Answer
{
get { return answer; }
set { answer = value; }
}
}
protected void option1_CheckedChanged(object sender, EventArgs e)
{
if (Convert.ToInt32 (Session["Answer"]) == 1)
{
int marks=Convert.ToInt32 (Session["Marks"]);
marks++;
Session["Marks"] = marks;
}
}
protected void option2_CheckedChanged(object sender, EventArgs e)
{
if (Convert.ToInt32(Session["Answer"]) == 2)
{
int marks = Convert.ToInt32(Session["Marks"]);
marks++;
Session["Marks"] = marks;
}
}
protected void option3_CheckedChanged(object sender, EventArgs e)
{
if (Convert.ToInt32(Session["Answer"]) == 3)
{
int marks = Convert.ToInt32(Session["Marks"]);
marks++;
Session["Marks"] = marks;
}
}
protected void option4_CheckedChanged(object sender, EventArgs e)
{
if (Convert.ToInt32(Session["Answer"]) == 4)
{
}
}
protected void btnNext_Click(object sender, EventArgs e)
{
}
protected void btnNext_Click1(object sender, EventArgs e)
{
int buton = Convert.ToInt32(Session["buttonIndex"]);
if (buton < 5)
{
if (RadioButtonList1.SelectedIndex + 1 == Convert.ToInt32(Session["Answer"]))
{
int marks = Convert.ToInt32(Session["Marks"]);
marks++;
Session["Marks"] = marks;
}
Session["buttonIndex"] = Convert.ToInt32(Session["buttonIndex"]) + 1;
renderQuestions(Convert.ToInt32(Session["buttonIndex"]));
if (buton == 4)
{
Server.Transfer("Results.aspx");
Session.RemoveAll();
}
}
}
}
}HTML
<form id="form1" runat="server">
<div>
<h3>Please choose the right answer</h3>
</div>
<table class="style1">
<tr>
<td class="style3">
<asp:Panel ID="Panel1" runat="server">
<asp:Label ID="lblQuestion" runat="server" Text=""></asp:Label>
</asp:Panel>
</td>
<td class="style4">
</td>
</tr>
<tr>
<td class="style2">
Answers:</td>
<td>
</td>
</tr>
<tr>
<td class="style2">
<asp:Panel ID="Panel2" runat="server">
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
</asp:RadioButtonList>
<asp:RadioButton ID="option1" runat="server" Checked="false" AutoPostBack="True"
GroupName="Option" oncheckedchanged="option1_CheckedChanged" />
<asp:RadioButton ID="option2" runat="server" Checked="false" AutoPostBack="True"
GroupName="Option" oncheckedchanged="option2_CheckedChanged" />
<asp:RadioButton ID="option3" runat="server" Checked="false" AutoPostBack="True"
GroupName="Option" oncheckedchanged="option3_CheckedChanged" />
<asp:RadioButton ID="option4" runat="server" Checked="false" AutoPostBack="True"
GroupName="Option" oncheckedchanged="option4_CheckedChanged" />
</asp:Panel>
</td>
<td>
</td>
</tr>
<tr>
<td class="style2">
</td>
<td>
</td>
</tr>
<tr>
<td class="style2">
<asp:Button ID="btnNext" runat="server" onclick="btnNext_Click1" Text="Next" />
</td>
<td>
</td>
</tr>
</table>
</form>我得到了完美的结果,还没有任何问题。但我想确保我这样做是最好的方式,如果我的代码符合标准,如果有任何安全问题。
发布于 2017-03-25 05:08:38
总的来说,我认为这是一个伟大的第一次尝试。也就是说,它在简化和提高可读性方面还有很大的改进余地。
顺便说一句,我不确定您是否有使用Visual 2010的强烈动机,但如果没有,我建议您考虑使用更最新的版本。Visual 2017最近发布了。
方法的命名应该是PascalCase,而不是缩写。例如,不要使用renderQuesAndAnswers,而是使用RenderQuestionAndAnswers。这提高了可读性,并与C#约定保持一致。
问题类也使用匈牙利符号。我也要指出,这是一种模式。而不是clsQuestion,它应该是QuestionModel。
有关参考,请参见https://msdn.microsoft.com/en-us/library/ms229045(v=vs.110).aspx和https://msdn.microsoft.com/en-us/library/ms229043(v=vs.110).aspx。在这些文档中有一些很棒的地方。
Question类可以使用C#自动实现的属性大大简化.使用public string Property { get; set; }而不是创建您自己的备份字段。参考见https://msdn.microsoft.com/en-us/library/bb384054.aspx。我还将问题属性重命名为QuestionText,以避免混淆。
这样,问题类可能非常简单:
public class QuestionModel {
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public string Option1 { get; set; }
public string Option2 { get; set; }
public string Option3 { get; set; }
public string Option4 { get; set; }
public int Answer { get; set; }
}catch (Exception ex) {
throw ex;
}这是不必要的。如果没有它,它将传播异常,就像手动重新抛出异常一样。
你似乎同时有一个单选按钮列表和4个单选按钮。我们只需要单选按钮列表。也有一些面板是不需要的。
我们可以使用ViewState,而不是使用会话来存储问题之间的数据。ViewState不将数据保存在服务器上,而是存储在客户端。因为我们不需要使用内部状态数据(比如当前的问题),所以我们可以将其存储在ViewState中。使用ViewState还允许用户在不同的窗口中一次进行多个问题会话,而会话数据则会在它们之间混合。
我们也可以使用属性来简化这种访问。与使用字符串访问变量不同,我们可以在属性中实现访问,这将防止我们意外地使用错误的键。例如:
private int QuestionNumber {
get {
return (int)ViewState["QuestionNumber"];
}
set {
ViewState["QuestionNumber"] = value;
}
}我们还可以将整个当前问题存储在ViewState中,以避免存储单个属性,例如答案索引。我们可以通过将[Serializable]属性添加到QuestionModel类来做到这一点。请注意,如果我们确实使用ViewState,我们也应该加密它,以避免泄露答案和其他内部信息。为此,我们可以将ViewStateEncryptionMode="Always"添加到.aspx文件的Page指令中。
还要注意,我们需要找到一种方法来提供对Results.aspx正确计数的访问。为了简单起见,我们可以在这种特殊情况下使用会话数据:
Session["CorrectCount"] = CorrectCount.ToString();
Server.Transfer("Results.aspx");
Session.Contents.Remove("CorrectCount");理想情况下,最好有一个我们可以序列化和传递的结果信息类,其中可能包括百分比,答案是对的/错的,等等。注意:它真的不应该在这里使用会话(参见上面的推理),但是传输数据的架构不在这个问题的范围之内,所以这里是为了证明概念。
分开
目前,renderQuestions既处理数据访问,又调用呈现方法。我会提取对它自己的方法的数据访问,类似于:
private QuestionModel GetQuestion(int index) {
// Data Access Logic
}这使我们有了一个更清晰的呈现逻辑:
private void RenderQuestion() {
CurrentQuestion = GetQuestion(QuestionNumber);
lblQuestion.Text = CurrentQuestion.QuestionText;
rblOptions.Items.Clear();
rblOptions.Items.Add(CurrentQuestion.Option1);
rblOptions.Items.Add(CurrentQuestion.Option2);
rblOptions.Items.Add(CurrentQuestion.Option3);
rblOptions.Items.Add(CurrentQuestion.Option4);
}上的答案检查
在选中所选选项时,没有充分的理由检查它;我们只关心用户何时单击next。这大大简化了逻辑,因为我们可以删除所有这些方法,并在next按钮单击方法中实现所有的逻辑。例如:
protected void btnNext_Click(object sender, EventArgs e)
{
if (rblOptions.SelectedIndex + 1 == CurrentQuestion.Answer) {
CorrectCount++;
}
if (QuestionNumber == 4) {
Server.Transfer("Results.aspx");
}
else {
QuestionNumber++;
RenderQuestion();
}
}有了所有这些,我们就得出了以下结论。注意,我们已经将类的大小减少了近一半,并使其更具可读性。
CodeBehind
using System;
using System.Web;
using System.Data;
using System.Configuration;
using MySql.Data.MySqlClient;
namespace questions
{
public partial class Question : System.Web.UI.Page
{
[Serializable]
protected class QuestionModel
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public string Option1 { get; set; }
public string Option2 { get; set; }
public string Option3 { get; set; }
public string Option4 { get; set; }
public int Answer { get; set; }
}
private int QuestionNumber { get { return (int)ViewState["QuestionNumber"]; } set { ViewState["QuestionNumber"] = value; } }
private int CorrectCount { get { return (int)ViewState["CorrectCount"]; } set { ViewState["CorrectCount"] = value; } }
private QuestionModel CurrentQuestion { get { return ViewState["CurrentQuestion"] as QuestionModel; } set { ViewState["CurrentQuestion"] = value; } }
protected void Page_Load(object sender, EventArgs e) {
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
Response.Cache.SetNoStore();
if (!IsPostBack) {
QuestionNumber = 1;
CorrectCount = 0;
RenderQuestion();
}
}
private QuestionModel GetQuestion(int index) {
MySqlConnection connection = null;
var connectionString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
var query = "SELECT * FROM QUESTIONS WHERE QUESTION_ID=" + index;
try
{
using (connection = new MySqlConnection(connectionString))
{
connection.Open();
using (var command = new MySqlCommand(query, connection))
{
using (var adapter = new MySqlDataAdapter(command))
{
var dataTable = new DataTable();
adapter.Fill(dataTable);
if (dataTable.Rows.Count > 0)
{
return new QuestionModel
{
QuestionId = Convert.ToInt32(dataTable.Rows[0][0]),
QuestionText = Convert.ToString(dataTable.Rows[0][1]),
Option1 = Convert.ToString(dataTable.Rows[0][2]),
Option2 = Convert.ToString(dataTable.Rows[0][3]),
Option3 = Convert.ToString(dataTable.Rows[0][4]),
Option4 = Convert.ToString(dataTable.Rows[0][5]),
Answer = Convert.ToInt32(dataTable.Rows[0][6])
};
}
else
{
return null;
}
}
}
}
}
finally
{
connection.Close();
}
}
private void RenderQuestion() {
CurrentQuestion = GetQuestion(QuestionNumber);
lblQuestion.Text = CurrentQuestion.QuestionText;
rblOptions.Items.Clear();
rblOptions.Items.Add(CurrentQuestion.Option1);
rblOptions.Items.Add(CurrentQuestion.Option2);
rblOptions.Items.Add(CurrentQuestion.Option3);
rblOptions.Items.Add(CurrentQuestion.Option4);
}
protected void btnNext_Click(object sender, EventArgs e)
{
if (rblOptions.SelectedIndex + 1 == CurrentQuestion.Answer) {
CorrectCount++;
}
if (QuestionNumber == 4) {
Session["CorrectCount"] = CorrectCount.ToString();
Server.Transfer("Results.aspx");
Session.Contents.Remove("CorrectCount");
}
else {
QuestionNumber++;
RenderQuestion();
}
}
}
}HTML
<form id="form1" runat="server">
<div>
<h3>Please choose the right answer</h3>
</div>
<table class="style1">
<tr>
<td class="style3">
<asp:Label ID="lblQuestion" runat="server" Text=""></asp:Label>
</td>
<td class="style4"> </td>
</tr>
<tr>
<td class="style2">Answers:</td>
<td> </td>
</tr>
<tr>
<td class="style2">
<asp:RadioButtonList ID="rblOptions" runat="server"></asp:RadioButtonList>
</td>
<td> </td>
</tr>
<tr>
<td class="style2"> </td>
<td> </td>
</tr>
<tr>
<td class="style2">
<asp:Button ID="btnNext" runat="server" onclick="btnNext_Click" Text="Next" />
</td>
<td> </td>
</tr>
</table>
</form>https://codereview.stackexchange.com/questions/158591
复制相似问题