Recommendations and advice on creating an online assessment/exam

Posted on 2008-06-24
Medium Priority
Last Modified: 2013-11-07
Hi all,

Can I get some advice on creating an online assessment/exam? I currently have a ASPX page which is comprised as follows:

1. I have an asp:Panel (ID pnlAssessment).
2. I have the questions and answers stored in 2 tables (SQL Server 2005), each in a question and answer table respectively.
3. A question can have 2 types, a multiple choice or an image question. If it is multiple choice there can be many prospective answers, and more than one may be correct.

The way I am doing this at the moment is building a dataset of 2 datatables with a relation between the questions and answers. I then dynamically create a CheckBoxList for each question, with each answer a ListItem.

Here is the crux of the problem, when submitting your answer I attempt to iterate through all the controls on the page, and pull all the answers into a database answers table. This used to work. I submitted a question to EE a while ago because the For Next loop was not finding the controls on the page. I went through mountains of testing and changing code to try and get this too work, I even got Microsoft involved through paid support. In the end, through sheer desperation, I created a new page and copied the code across and the For Next found the controls and submitted the answers. As of yesterday this has stopped working again! So now I am questioning whether this is even the right/most efficient way to do it and I am looking for your help before I kill myself!

I've attached my current code so you can see how it used to work. Hopefully you'll have some suggestions? I wish I could assign 5000 points as this is now so desperate.

<%@ Page Language="VB" MasterPageFile="~/secure/masterpages/2-col-v3.master" AutoEventWireup="false" CodeFile="assessment-4-v3.aspx.vb" Inherits="secure_assessments_precourse_assessment_4_v3" title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="cphNew2ColMain" Runat="Server">
    <div class="pagetitle">
        <asp:Image ID="imgAssessment" ImageAlign="Middle" ImageUrl="~/App_Themes/jcb-v3/images/pageicons/assessment.gif" runat="server" />&nbsp;
        <asp:Label ID="lblOnlineAssessment" Text="Online Assessment" runat="server"></asp:Label>
    <asp:Panel ID="pnlAssessment" EnableViewState="true" CssClass="formwrapper" runat="server"></asp:Panel>
    <div class="forminput">
        <asp:Button ID="btnSubmitAnswers" Text="Submit Answers" runat="server" />
<asp:Content ID="Content2" ContentPlaceHolderID="cphNew2ColRight" Runat="Server">
    <div class="rightsubtitlebar">
        <asp:Label ID="lblAssessmentSubTitle" Text="Assessment Started" SkinID="subtitle" runat="server"></asp:Label>
    <div class="pagetext">
        <asp:Label ID="lblAssessmentWarning" Text="{not loaded}" Font-Bold="true" SkinID="fielderror" runat="server"></asp:Label>
Protected Sub getAssessmentQuestions()
        Dim courseID As Integer = 31
        Dim con As New SqlConnection(ConnectionStrings("dev").ConnectionString)
        Dim sqlQuestions As String = "SELECT questionID, questionType, questionText, questionImageFilename, courseID, " & _
            "questionStatus FROM dbo.trn_assessmentQuestions " & _
            "where courseID = " & courseID
        Dim dtStamp As Date = Now()
        Dim scnd As Integer = dtStamp.Second
        Dim sqlApd As String
        If scnd Mod 2 = 0 Then
            sqlApd = "DESC"
            sqlApd = "ASC"
        End If
        Dim sqlAnswers As String = "SELECT answerID, questionID, answerText, answerStatus, correct " & _
            "FROM dbo.trn_assessmentAnswers order by answerID " & sqlApd
        Dim da As New SqlDataAdapter(sqlQuestions, con)
        Dim ds As New DataSet()
            da.Fill(ds, "Questions")
            da.SelectCommand.CommandText = sqlAnswers
            da.Fill(ds, "Answers")
            Dim relation As New DataRelation("questions", ds.Tables("Questions").Columns("questionID"), ds.Tables("Answers").Columns("questionID"))
            Dim i As Integer = 10
            Dim x As Integer = 1
            Dim dummy As Integer = 1
            For Each row As DataRow In ds.Tables("Questions").Rows
                Dim lbl As Label = New Label()
                lbl.ID = "QID" & row("questionID").ToString
                lbl.Attributes("name") = dummy
                lbl.Style("margin-top") = i
                lbl.Style("margin-left") = "10px"
                lbl.Style("width") = "200px"
                lbl.SkinID = "question"
                lbl.Style("padding-top") = "20px"
                lbl.Style("padding-bottom") = "10px"
                Dim question As String = row("questionText").ToString
                lbl.Text = Convert.ToString(x) & ": " & question
                dummy = dummy + 1
                If row("questiontype") = 37 Then
                    Dim img As Image = New Image
                    Dim test As String = Server.MapPath("~/App_Themes/jcb-v3/images/aqimages/" & row("questionImageFilename").ToString)
                    If Request.ServerVariables("LOCAL_ADDR") = "" Then
                        img.ImageUrl = "http://localhost/jcbtraining/app_themes/jcb-v3/images/aqimages/" & row("questionImageFilename").ToString
                        img.ImageUrl = "http://www.jcbtraining.com/app_themes/jcb-v3/images/" & row("questionImageFilename").ToString
                    End If
                End If
                Dim childRows As DataRow() = row.GetChildRows(relation)
                Dim rbl As CheckBoxList = New CheckBoxList()
                For Each childRow As DataRow In childRows
                    rbl.ID = row("questionid").ToString
                    Dim tPos As Integer = 60 * (i + 1)
                    rbl.Style("margin-top") = i + 20
                    rbl.Style("margin-left") = "50px"
                    rbl.Style("margin-bottom") = "20px"
                rbl.SkinID = "CheckBoxList"
                rbl.Attributes("name") = "myname"
                x = x + 1
        Catch ex As Exception
            System.Diagnostics.Debug.WriteLine("Error " & ex.Message & vbCrLf)
        End Try
    End Sub
    Protected Sub btnSubmitAnswers_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmitAnswers.Click
        endAssessment(Convert.ToInt32(Session("AssessmentTrackingID")), 1, 1)
        pnlAssessment.Visible = False
        Dim i As Integer = 0
        For Each c As Control In Me.Controls
            For Each c1 As Control In c.Controls
                If c1.ID = "form1" Then
                    For Each c2 As Control In c1.Controls
                        If c2.ID = "cphNew2ColMain" Then
                            For Each c3 As Control In c2.Controls
                                If c3.ID = "pnlAssessment" Then
                                    For Each c4 As Control In c3.Controls
                                        System.Diagnostics.Debug.WriteLine("Control ID =  " & c4.ID & vbCrLf)
                                        If c4.GetType.ToString.Equals("System.Web.UI.WebControls.Label") Then
                                            System.Diagnostics.Debug.WriteLine("Label ID =  " & c4.ID & vbCrLf)
                                        End If
                                        If c4.GetType.ToString.Equals("System.Web.UI.WebControls.CheckBoxList") Then
                                            System.Diagnostics.Debug.WriteLine("CheckBoxList ID: " & c4.ID & vbCrLf)
                                            Dim tempCBL As CheckBoxList = CType(c4, CheckBoxList)
                                            For Each li As ListItem In tempCBL.Items
                                                If li.Selected Then
                                                    System.Diagnostics.Debug.WriteLine("Answer Checked: " & li.Value & vbCrLf)
                                                    storeTestAnswer(c4.ID, li.Value)
                                                End If
                                        End If
                                End If
                        End If
                End If
    End Sub
    Protected Sub endAssessment(ByVal trackingID As Integer, ByVal endCode As Integer, ByVal completed As Integer)
        Dim objAs As New assessments()
        Dim success As Boolean = objAs.endAssessment(Convert.ToInt32(Request.Cookies("userid").Value), completed, endCode, trackingID, _
    End Sub
    Protected Sub storeTestAnswer(ByVal questionID As Integer, ByVal answer As String)
        Dim con As New SqlConnection(ConnectionStrings("dev").ConnectionString)
        Dim cmd As New SqlCommand("sp_enterAssessmentAnswer", con)
        cmd.CommandType = CommandType.StoredProcedure
        Dim pAssessID As SqlParameter = cmd.Parameters.AddWithValue("@assessmentID", Convert.ToInt32(Request.Cookies("assessmenttrackingrecordid").Value))
        pAssessID.Direction = ParameterDirection.Input
        Dim pUserID As SqlParameter = cmd.Parameters.AddWithValue("@userid", Convert.ToInt32(Request.Cookies("userid").Value))
        pUserID.Direction = ParameterDirection.Input
        Dim pQuestionID As SqlParameter = cmd.Parameters.AddWithValue("@questionID", questionID)
        pQuestionID.Direction = ParameterDirection.Input
        Dim pScalarAnswer As SqlParameter = cmd.Parameters.AddWithValue("@scalarAnswer", answer)
        pScalarAnswer.Direction = ParameterDirection.Input
        Catch ex As Exception
            submitToTextFile(Convert.ToInt32(Request.Cookies("assessmenttrackingrecordid").Value), _
                             Convert.ToInt32(Request.Cookies("userid").Value), questionID, answer)
        End Try
    End Sub
    Protected Sub submitToTextFile(ByVal assID As Integer, ByVal uid As Integer, ByVal qid As Integer, ByVal answer As String)
        Dim filePath As String = Server.MapPath("~/secure/pca/assessbackup/" & Convert.ToString(uid) & "_" & Convert.ToString(assID) & ".txt")
        If File.Exists(filePath) Then
            Dim sr As StreamWriter
            sr = File.AppendText(filePath)
            sr.WriteLine(assID & " " & uid & " " & qid & " " & answer)
            Dim sr As StreamWriter = File.CreateText(filePath)
            sr.WriteLine("The assessment for user ID " & Convert.ToString(uid) & ", assessment ID " & Convert.ToString(assID) & ", could not be stored in the database, " & _
            "the results are saved here.")
            sr.WriteLine(" ")
        End If
    End Sub

Open in new window

Question by:G0ggy
  • 2
LVL 25

Expert Comment

ID: 21858399
You are statically checking / looking controls.  It will break when there is change in ur control structure. use recursive like below so it can traverse to any level / child nodes.

You can go through them recursively:

public static void ListControls(System.Web.UI.Control ctrl)
foreach(Control subCtrl in ctrl.Controls)
   //Look for the control type here and take necessary action else call the function again to do recursive
LVL 11

Accepted Solution

G0ggy earned 0 total points
ID: 21863675
I could dance an absolute jig! I have fixed it, sorry apeter it wasn't your solution.

I moved the creation of the controls to the Page_InitComplete event of the page and changed my code to:

For Each ctrl As Control In pnlAssessment.Controls
            If TypeOf (ctrl) Is CheckBoxList Then
                System.Diagnostics.Debug.WriteLine("C Control ID =  " & ctrl.ID.ToString & vbCrLf)

                Dim tempCBL As CheckBoxList = CType(ctrl, CheckBoxList)

                For Each li As ListItem In tempCBL.Items
                    If li.Selected Then
                        System.Diagnostics.Debug.WriteLine("Answer Checked: " & li.Value & vbCrLf)
                        storeTestAnswer(ctrl.ID, li.Value)
                    End If
            End If

Sorry to go on, but I have worked on this problem for so long! I'm soooo happy etc...
LVL 25

Expert Comment

ID: 21864837
Its ok. It may not be recursive but "foreach" statement is from the code snippet  i guess...any way your problem is solved :)

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
Watch the video to know how one can repair corrupt Exchange OST file effortlessly and convert OST emails to MS Outlook PST file format by using Kernel for OST to PST converter tool. It can convert OST to MSG, MBOX, EML to access them. It can migrate…
Watch the software video of Kernel Import PST to Office 365 tools which can easily import PST and OST files to Office 365 for bulk mailboxes. The process of migration is simple and user can map source and destination mailboxes and easily import data…

569 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question