Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 886
  • Last Modified:

Recommendations and advice on creating an online assessment/exam

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.

Thanks.
<%@ 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>
    </div>
 
    <asp:Panel ID="pnlAssessment" EnableViewState="true" CssClass="formwrapper" runat="server"></asp:Panel>
 
    <div class="forminput">
        <asp:Button ID="btnSubmitAnswers" Text="Submit Answers" runat="server" />
    </div>
</asp:Content>
 
<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>
 
    <div class="pagetext">
        <asp:Label ID="lblAssessmentWarning" Text="{not loaded}" Font-Bold="true" SkinID="fielderror" runat="server"></asp:Label>
    </div>
</asp:Content>
 
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"
        Else
            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()
 
        Try
            con.Open()
 
            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"))
 
            ds.Relations.Add(relation)
 
            Dim i As Integer = 10
            Dim x As Integer = 1
 
            'Markus
            Dim dummy As Integer = 1
 
            For Each row As DataRow In ds.Tables("Questions").Rows
                Dim lbl As Label = New Label()
 
                'Markus
                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
                pnlAssessment.Controls.Add(lbl)
 
                'Markus
                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") = "127.0.0.1" Then
                        img.ImageUrl = "http://localhost/jcbtraining/app_themes/jcb-v3/images/aqimages/" & row("questionImageFilename").ToString
                    Else
                        img.ImageUrl = "http://www.jcbtraining.com/app_themes/jcb-v3/images/" & row("questionImageFilename").ToString
                    End If
                    pnlAssessment.Controls.Add(img)
                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.Items.Add(childRow("answerText".ToString))
                Next
                rbl.SkinID = "CheckBoxList"
                rbl.Attributes("name") = "myname"
                pnlAssessment.Controls.Add(rbl)
 
                x = x + 1
            Next
 
        Catch ex As Exception
            System.Diagnostics.Debug.WriteLine("Error " & ex.Message & vbCrLf)
        Finally
            con.Close()
        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
                                            Next
                                        End If
                                    Next
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        Next
 
        getResult(Convert.ToInt32(Session("AssessmentTrackingID")))
    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, _
                                                      Convert.ToInt32(Session("AssessmentTrackingID")))
    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
 
        Try
            con.Open()
            cmd.ExecuteNonQuery()
        Catch ex As Exception
            submitToTextFile(Convert.ToInt32(Request.Cookies("assessmenttrackingrecordid").Value), _
                             Convert.ToInt32(Request.Cookies("userid").Value), questionID, answer)
        Finally
            con.Close()
        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)
            sr.WriteLine("--------------------------------------------------")
            sr.Flush()
            sr.Close()
        Else
            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(" ")
            sr.Close()
        End If
    End Sub

Open in new window

0
G0ggy
Asked:
G0ggy
  • 2
1 Solution
 
apeterCommented:
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
ListControls(subCtrl);
}
}
0
 
G0ggyAuthor Commented:
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
                Next
            End If
        Next

Sorry to go on, but I have worked on this problem for so long! I'm soooo happy etc...
0
 
apeterCommented:
Its ok. It may not be recursive but "foreach" statement is from the code snippet  i guess...any way your problem is solved :)
0

Featured Post

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now