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

使用 Atlas 的简单 AJAX 测验

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (9投票s)

2006 年 8 月 1 日

CPOL

3分钟阅读

viewsIcon

82499

downloadIcon

1421

使用 Atlas 控件和 Web 服务创建测验的简单方法。

Sample Image - SimpleAjaxQuizUsingAtlas.png

引言

作为我在 Code Project 上的第一篇文章,我想谈谈我围绕 AJAX/Atlas 技术创建的一个小小的概念验证。当我看到 这个截屏时,我认为它可以很容易地用于一个简单的 AJAX 测验系统,所以我就在这里了 :) 代码确实很简单,而且没有错误管理,但也许以后,我会更新此代码以创建一个更完整的解决方案。

必备组件

为了能够使用此代码,您需要执行以下操作

  • 安装 Atlas
  • 创建一个名为 AjaxQuiz 的 SQL 数据库,并执行源代码附带的 SQL 脚本。
  • 添加对 Atlas DLL 的引用(通常位于 C:\Program Files\Microsoft ASP.NET\Atlas\v2.0.50727\Atlas)。
  • 修改 web.config 中的 AjaxQuiz 连接字符串。

SQL 代码

AjaxQuiz 数据库包含三个表:t_Questionst_Answerst_UserAnswers。还有一个由我们的 Web 方法调用的存储过程来处理数据

CREATE PROCEDURE dbo.ProcessNextQuestion 
    (
    @intQuestionID int = 0,
    @intAnswerID int = 0,
    @intUserID int = 0
    )
AS
    IF @intQuestionID > 0 AND @intAnswerID > 0 AND @intUserID > 0
    BEGIN
        INSERT INTO t_UserAnswers(UserID, AnswerID, QuestionID)
        VALUES(@intUserID, @intAnswerID, @intQuestionID)
    END

    SELECT TOP 1 QuestionID, QuestionText
    FROM t_Questions
    WHERE QuestionID > @intQuestionID

如您所见,如果 SQL 输入参数不为 null,存储过程会在数据库中插入上一个问题的结果。然后,它返回下一个问题的文本和 ID。由于 QuestionID 是自动递增的,因此始终返回下一个问题,但它假设 ID 对应于所需的问题顺序。

标记代码

在这个小项目中只有一个网页:Default.aspx。首先,我必须描述 ScriptManager 元素

<atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
 <Scripts>
  <atlas:ScriptReference Path="AjaxQuiz.js" />
 </Scripts>
 <Services>
  <atlas:ServiceReference Path="QuestionService.asmx" />
 </Services>
</atlas:ScriptManager>

这就是 Atlas 真正好的地方:我们只需要引用我们的 JS 客户端脚本和我们的 Web 服务,Atlas 就会完成剩下的工作(用于使用 WS 的客户端代码等)。在我们的 JS 代码中,我们还将能够创建在服务器代码中定义的类的实例。Atlas 将为我们进行对应。

<div id="StartForm">
  <input id="btnStart" type="button" value="Start the Ajax Quiz !" onclick="Callback()" />
</div>
<div id="QuizForm" style="display: none;">
<div id="QuestionText"></div><br />
 <input type="radio" id="YesAnswer" name="Answer" checked="checked" /> Yes
 <input type="radio" id="NoAnswer" name="Answer" /> No
 <input type="radio" id="DontKnowAnswer" name="Answer" /> ?<br /><br />
 <input id="btnCallBack" type="button" value="Next" onclick="Callback()" /> 
 <img id="imgUpdate" src="Images/spinner.gif" alt="Updating data" style="display: none;" />
 <input id="QuestionID" type="hidden" value="0" />
</div>
<div id="EndForm" style="display: none;">
Thank you, this quiz is now finished ! 
</div>

然后,我们添加一些 HTML 控件来创建我们的表单。首先,有三个 DIV:一个在启动时显示,另一个用于测验问题,最后一个在测验完成后显示。主部分 QuizForm 包含三个用于答案的单选按钮、一个用于调用我们的 Web 服务的按钮以及在 AJAX 调用期间显示的图像。

Web服务

Web 服务只包含一个 WebMethod,StoreAnswer

/// <summary>
/// That's the only Web Method used. It both stores the answer to the current question 
/// and sends data for the next one.
/// </summary>
/// <param name="previousQuestion">A Question object containing user answer.</param>
/// <returns>Returns a Question object containing data 
///          for the next question (question ID, question Text)</returns>
[WebMethod]
public Question StoreAnswer(Question previousQuestion)
{
    // We initialize a Question object to null. It will be our return value.
    Question nextQuestion = null;
    if (previousQuestion == null)
    {
        // If no previous question is submitted, we create a new one with default values.
        previousQuestion = new Question(0, "", 0);
    }
    // SQL connection initialization (connection string is in web.config file)
    using (SqlConnection cn = new SqlConnection(
      ConfigurationManager.ConnectionStrings["AjaxQuizConnectionString"].ConnectionString))
    {
        try
        {
            // Then we call our stored procedure
            SqlCommand cmd = new SqlCommand("dbo.ProcessNextQuestion", cn);
            cmd.CommandType = CommandType.StoredProcedure;
            // First parameter for question ID.
            SqlParameter parm = new SqlParameter("@intQuestionID", SqlDbType.Int);
            parm.Value = previousQuestion.QuestionID;
            parm.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(parm);
            // Second parameter for answer ID.
            SqlParameter parm2 = new SqlParameter("@intAnswerID", SqlDbType.Int);
            parm2.Value = previousQuestion.AnswerID;
            parm2.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(parm2);
            // Third parameter for user ID.
            SqlParameter parm3 = new SqlParameter("@intUserID", SqlDbType.Int);
            parm3.Value = userID;
            parm3.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(parm3);
            // Opening sql connection
            cn.Open();
            using (SqlDataReader rd = 
                     cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (rd.Read())
                {
                    // We read data returned by our SP. It only returns one row.
                    nextQuestion = new Question(rd.GetInt32(0), rd.GetString(1));
                }
            }
            // We make the web service sleep for one second,
            // so that we can see the spinner image appear.
            // This line should be removed
            // if you seriously think about using this code ^^
            Thread.Sleep(1000);
        }
        finally
        {
            // Important : we always have to close the sql connection
            cn.Close();
        }
    }
    return nextQuestion;
}

WebMethod 调用一个存储过程,然后将下一个问题作为 Question 对象返回。我让线程休眠一秒钟,这样我就可以看到旋转图像。

JavaScript 代码

JavaScript 代码可能是最难的部分,因为我们必须引用我们所有的 HTML 对象并获取/设置它们的值。肯定有更简单的方法来完成这项工作,所以请不要犹豫,在评论部分提出一些建议。OnTimeoutOnError 函数未包含在内,但存在于 Zip 文件中。

// Called on 'Next' button click event.
function Callback()
{
    // Gets a reference to the hidden field containing the question ID

    var questionID = document.getElementById('QuestionID');
    // Gets references to the 3 possible answers

    var answer1 = document.getElementById('YesAnswer');
    var answer2 = document.getElementById('NoAnswer');
    var answer3 = document.getElementById('DontKnowAnswer');
    // Initializes a variable to hold the user answer

    var answerID = 0;
    // Gets user answer

    if(answer1.checked) answerID = 1;
    if(answer2.checked) answerID = 2;
    if(answer3.checked) answerID = 3;
    // Creates a new Question object. Atlas makes
    // the translation for us : JS and ASP.NET

    // know exactly the same class !

    var object = new Question();
    object.QuestionID = questionID.value;
    object.AnswerID = answerID;
    // Displays a image during the AJAX call

    DisplayUpdateImage(true);
    // Ajax call. QuestionService is the Web Service
    // we registered in Atlas ScriptManager
    // and as you can see, we can directly
    // call our WebMethod. Isn't it nice ? :)
    // We also add 3 events : one when process is completed,
    // another when a timeout occurs, 
    // and a last one if an error occurs.

    QuestionService.StoreAnswer(object, OnComplete, OnTimeout, OnError);
}

// Called when Ajax request is done
function OnComplete(response)
{
    // 3 references to our 3 DIVs

    var StartForm = document.getElementById('StartForm');
    var QuizForm = document.getElementById('QuizForm');
    var EndForm = document.getElementById('EndForm');

    // A reference to the hidden field used to hold the question ID

    var questionID = document.getElementById('QuestionID');
    // A reference to the DIV which will contain the next question text

    var questionText = document.getElementById('QuestionText');

    // If there is a next question

    if(response != null)
    {
        StartForm.style.display = 'none';
        EndForm.style.display = 'none';
        QuizForm.style.display = 'block';
        questionID.value = response.QuestionID;
        questionText.innerHTML = response.QuestionText;
    }
    // If there's no more questions, we display the EndForm div.
    else
    {
        EndForm.style.display = 'block';
        QuizForm.style.display = 'none';
    }
    // We hide the updating image

    DisplayUpdateImage(false);
}

结论

就是这样!当用户单击“开始”按钮时,他会看到第一个问题出现。由于输入 Question 对象为空,因此不会将结果插入数据库。然后,当他单击“下一步”按钮时,结果会存储在数据库中,我们的存储过程会发送下一个问题……等等,直到存储过程没有任何返回。在这种情况下,最后,用户会看到结束消息。

好的,我知道这是一篇相当简单的文章,但我认为它可以说明您可以使用 Atlas 做什么以及它有多么容易。我也希望我的英语不是太差 :)

© . All rights reserved.