Solved

Recommendations and advice on creating an online assessment/exam

Posted on 2008-06-24
4
828 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
Comment Utility
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
Comment Utility
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
Comment Utility
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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
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…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

771 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

11 Experts available now in Live!

Get 1:1 Help Now