Solved

Recommendations and advice on creating an online assessment/exam

Posted on 2008-06-24
4
840 Views
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.

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
Comment
Question by:G0ggy
  • 2
4 Comments
 
LVL 25

Expert Comment

by:apeter
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
ListControls(subCtrl);
}
}
0
 
LVL 11

Accepted Solution

by:
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
                Next
            End If
        Next

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

Expert Comment

by:apeter
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 :)
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
Delivering innovative fully-managed cloud services for mission-critical applications requires expertise in multiple areas plus vision and commitment. Meet a few of the people behind the quality services of Concerto.

919 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now