|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionAs my first article on Code Project, I'd like to talk about a little proof of concept I created around AJAX/Atlas technologies. When I saw this screencast, I thought it could be easily used for a simple AJAX quiz system, so here I am :) The Code is really simple and there's no error management, but maybe later, I'll update this code to create a more complete solution. PrerequisitesTo be able to use this code, you'll have to do the following:
SQL codeThe AjaxQuiz database contains three tables: t_Questions, t_Answers, and t_UserAnswers. There's also a single Stored Procedure called by our Web Method to process the data: 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
As you can see, if the SQL input parameter isn't null, the Stored Procedure inserts results of the previous question in the database. Then, it returns the text and ID for the next question. As the Markup codeThere's only one web page in this small project: Default.aspx. First, I have to describe the <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
<Scripts>
<atlas:ScriptReference Path="AjaxQuiz.js" />
</Scripts>
<Services>
<atlas:ServiceReference Path="QuestionService.asmx" />
</Services>
</atlas:ScriptManager>
That's where Atlas is really nice: we just need to reference our JS client script and our Web Service, and Atlas will do the rest (the client code to consume the WS, etc.) In our JS code, we will also be able to create instances of classes defined in the server code. Atlas will do the correspondence for us. <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>
Then, we add some HTML controls to create our form. First of all, there are three Web ServiceThe Web Service contains only one WebMethod, /// <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;
}
The WebMethod calls a stored procedure, then returns the next question as a JavaScript codeThe JavaScript code might be the hardest part, because we have to reference all our HTML objects and get/set their values. There must certainly be a simpler way to do the job, so don't hesitate to propose something in the comments section. The // 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);
}
ConclusionAnd that's all! When the user clicks on the Start button, he sees the first question appear. No result is inserted in the database, because the input OK, I know this is a quite simple article, but I think it can illustrate what you can do with Atlas and how easy it is. I hope my English isn't too bad too :)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||