Skip to main content
Inspiring
March 5, 2011
Answered

Posting Quiz Results to an Internal Server in ASP or .NET

  • March 5, 2011
  • 7 replies
  • 11309 views

Hi,

We're a Microsoft shop and there's no way I'd be able to set up a PHP server on our network.  Are there equivalent ASP or.NET scripts that could work with MS SQL to do the same thing.  Maybe I'm search challenged (likely), but I've been unable to find this alternative anywhere.

Thanks in advance,

Richard

This topic has been closed for replies.
Correct answer marinesct

here you go:

Directory and Filename: \CaptivateResults\My\Office\Here\untitledassessment1_John Jones_1297402012972.xml

<Course>
  <CompanyName value="My"/>
  <DepartmentName value="Office"/>
  <CourseName value="Here"/>
  <LearnerName value="John Jones"/>
  <LearnerID value="me@myemail.com"/>
  <LessonName value="untitledassessment1"/>
  <QuizAttempts value="1"/>
  <TotalQuestions value="1"/>
  <Result>
    <CoreData>
      <Status value="completed"/>
      <Location value="2"/>
      <RawScore value="0"/>
      <MaxScore value="10"/>
      <MinScore value="0"/>
      <SessionTime value="00:00:11"/>
    </CoreData>
    <InteractionData>
      <Interactions>
        <Date value="02/10/2011"/>
        <InteractionTime value="22:26:39"/>
        <InteractionID value="933"/>
        <ObjectiveID value="Quiz10111"/>
        <InteractionType value="choice"/>
        <CorrectResponse value="B"/>
        <StudentResponse value="A"/>
        <Result value="W"/>
        <Weight value="10"/>
        <Latency value="00:00:03"/>
        <Attempt value="1"/>
      </Interactions>
    </InteractionData>
  </Result>
</Course>


This is produced using PHP's internalServerReporting.php file.  I installed WAMP on my home computer with trial of Cp5 to get familiar with it as well.  If you really want to get to know how it works, install SwfScan so that you can take a look at the AS3 inside the flash file you can see the different classes and how they operate depending on your reporting choice. It's helped me out alot, which it will also show you how the xml data is stored as well.

7 replies

Participant
January 9, 2013

I was able to do it a slightly different way with some collaborating help with another developer. We used Captivates internal server reporting and pointed the path to an .ashx page we named LMSProcessor.ashx that handled the xml file that Captivate spit out. The ashx page basically just parses out the xml file and grabs only the stuff we were interested in, and then stores that data in a database. It was actually quite simple, and since we were already working within a "portal" we didn't need to add a login to capture a "user name" since it already existed.

To give other devs who are interested in this route, you can see the code from our .ashx page below:

Public Class LMSProcessor

    Implements System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState

    Private _UserCourse As UserCourse

    Public Property UserCourse As UserCourse

        Get

            If HttpContext.Current.Session("UserCourse") IsNot Nothing Then

                _UserCourse = CType(HttpContext.Current.Session("UserCourse"), UserCourse)

            Else

                Dim userData As Application.AppName.User = HttpContext.Current.Session("UserData")

                _UserCourse = UserCourse.GetLatestCourse(userData.ID)

                _UserCourse.CourseUserID = userData.ID

                _UserCourse.EntityTypeID = UserData.EntityTypeID

                _UserCourse.EntityID = userData.EntityID

                _UserCourse.Save()

                HttpContext.Current.Session("UserCourse") = _UserCourse

            End If

            Return _UserCourse

        End Get

        Set(value As UserCourse)

            HttpContext.Current.Session("UserCourse") = value

        End Set

    End Property

    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

        ' Get xml data

        If context.Request.Form.AllKeys.Count > 0 Then

            Dim fileDataIndex As Integer = Array.IndexOf(context.Request.Form.AllKeys, "Filedata")

            If fileDataIndex > -1 Then

                Dim sectionName As String = ""

                Dim sectionID As Integer = 0

                Dim quizAttempts As Integer = 0

                Dim rawScore As Integer = 0

                Dim maxScore As Integer = 0

                Dim minScore As Integer = 0

                Dim status As String = ""

                Dim fileData As String = context.Request.Form("Filedata").ToString()

                Dim xDoc As New XmlDocument()

                xDoc.LoadXml(fileData)

                Dim xRoot As XmlElement = xDoc.DocumentElement

                ' Get Quiz Attempts

                Dim xQuizAttempts As XmlElement = xRoot.GetElementsByTagName("QuizAttempts")(0)

                If xQuizAttempts IsNot Nothing Then

                    quizAttempts = CInt(xQuizAttempts.Attributes("value").InnerText)

                End If

                ' Get Section Name

                Dim xVariables As XmlElement = xRoot.GetElementsByTagName("Variables")(0)

                If xVariables.ChildNodes.Count > 0 Then

                    Dim xSectionName As XmlElement = xVariables.GetElementsByTagName("section_name")(0)

                    If xSectionName IsNot Nothing Then

                        sectionName = xSectionName.Attributes("value").InnerText

                        ' Lookup Section ID

                        Dim section As New CourseSection(sectionName)

                        If section IsNot Nothing Then

                            sectionID = section.ID

                        End If

                    End If

                End If

                Dim xResult As XmlElement = xRoot.GetElementsByTagName("Result")(0)

                Dim xCoreData As XmlElement = xResult.GetElementsByTagName("CoreData")(0)

                If xCoreData.ChildNodes.Count > 0 Then

                    status = xCoreData.GetElementsByTagName("Status")(0).Attributes("value").InnerText

                    rawScore = CInt(xCoreData.GetElementsByTagName("RawScore")(0).Attributes("value").InnerText)

                    maxScore = CInt(xCoreData.GetElementsByTagName("MaxScore")(0).Attributes("value").InnerText)

                    minScore = CInt(xCoreData.GetElementsByTagName("MinScore")(0).Attributes("value").InnerText)

                End If

                Dim result As New UserCourseResult()

                result.UserCourseID = Me.UserCourse.ID

                result.SectionID = sectionID

                result.Attempts = quizAttempts

                result.Status = status

                result.RawScore = rawScore

                result.MaxScore = maxScore

                result.MinScore = minScore

                result.Save()

                ' Check if we're missing a course id

                If Me.UserCourse.CourseID = 0 Then

                    Dim course As Course = course.GetCourseBySection(sectionID)

                    Me.UserCourse.CourseID = course.ID

                    Me.UserCourse.Save()

                End If

            End If

        End If

    End Sub

    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable

        Get

            Return False

        End Get

    End Property

End Class

I hope this helps devs out there going this route. Happy coding.

Inspiring
January 31, 2013

We moved to C# and with the training department moving to Cp6, we can no longer use the mail methodology as provided above. I am working on a conversion from VB to C# for this and had a question. I'll probably have more later on

Can you tell me more about Application.AppName.User?

Inspiring
June 17, 2011

I've updated the script in the article on my blog.  Head on over to http://ian.meinertfamily.us/?p=84 to see the full code.

Inspiring
April 15, 2011

I've posted the series on my personal blog so I can more easily update the code as I find better solutions. When tracking the student information, you'll have to create an alternative means of getting and storing their name and work location. I use an internal database that houses that information.

For the course name, I was wasn't able to grab it from the swf directly. An alternative method is to have the Captivate developer assign the assessments Objective ID (under preferences) as the name of the course so you can differentiate between the assessments.

Part One of the series is just a quick down and dirty of setting up the tables.

Part Two of the series modifies the email_body.html template.

Part Three will be for creating the ASP file to insert the results into the database.

I've gotta get the article together still, but the first two should get you started.

If you want to see what the data looks like prior to submitting to a database, change the form elements from hidden to text.

Inspiring
April 19, 2011

Part III is up here.

That completes the set.  What I hadn't covered was the database connections. I also updated the first two parts to include the capability to record the name of the asessment.

Now that there's the capability to store the results in a database environment, you can use your own method of using the data.

Let me know how it goes for you!

Inspiring
June 8, 2011

Hi Marinesct,

So, I should replace email_boy.html in /Templates/Publish with the modified program in Part II of your post.

In the Captivate Quiz, I should still choose "Email" and "body text", right?

I did the above and previewed the quiz.  At the end of the quiz, there is a "Send E-mail" button.  When I click that, my exchange email window came up with quiz result data.

From looking at modified Part II program, I was expecing another webpage with a submit button.

What did I do wrong?

Thank you.

dchan

P.S. I am trying to post Quiz result to SQL database at the backend, but we don't use Php.

Inspiring
April 14, 2011

So I was able to put together a solution. I did use a concept from another post here in the forums that used JavaScript to call the variables from Cp2 and post them to MySQL.

I used the JavaScript in my html template and created a form to have the JavaScript post the data to an ASP page. From there, I was able to connect and insert the data into my tables.

I send the data to three tables:

employee (one-to-many) coreData (one-to-many) interactionData

I'll post the scripts on my blog and link to my blog from here. But to give you an idea, I used the sendMail() to grab the variable that contained the string of Core Data AND Interaction Data. from there, I built it into an array, looped through the array, creating hidden input elements for the form. Then after I posted it to the ASP, I reversed the process by looping through the form elements as I inserted one row at a time into my interactionDate table.

It sounds awkward, but it works.  It is a bit complex and fortunately not very long.

This is all just a process to get the data into a SQL database. From there, you should be able to generate any reports you want using any serverside script.

Participating Frequently
April 15, 2011

Thats awesome! I didn't think it was even possible.

I'm really keen to see how you did it and to pick up more ASP. Do post the solution up please!

Participating Frequently
April 12, 2011

Just wondering if anyone has submitted a feature request Adobe to put in a script for ASP?

Or at least to provide much more documentation.

I quote from http://help.adobe.com/en_US/captivate/cp/using/WS365a66ad37c9f510-67fa130d1265cad66a2-7fff.html:

"internalServerReporting.php is the sample PHP that is available in the Adobe Captivate installation folder. You can either use it or create your own server-side file, for example a PHP or ASP to write files to the server. Ensure that the server allows writing to files."

Yes, we can, but we also need to jump through a gazillion hoops without Adobe support.

Inspiring
April 12, 2011

I don't foresee Adobe providing support for ASP implementation anytime soon dues to a licensing issue with Microsoft. Since PHP is opensource, it's free to use and develop with. I've spoken to one of their Cp5 PHP developers and didn't get much help from their end with trying to come up with an ASP solution.

I've taken a different approach to getting the variables.  I came across Pipwerks site recently and was able to pull some variables using JavaScript and email reporting. I'm waiting for my Cp5 developer to come back in so I can do some further testing. So far, Pipwerk's method is able to obtain the quiz test results without the interaction data.

Participating Frequently
April 12, 2011

Hey guys, great to find some other people who are looking into this. We haven't got PHP here either. And I haven't got any experience with ASP or .NET. Let me know if you have any luck with the getting it to ASP.

Inspiring
March 14, 2011

Im working on trying to get ASP to work ,so far without any success or support from the community. Maybe we can collaborate on this some; especially since I don't have any .NET experience.

The Adobe help site mentions that any serverside script can be used in place of the internalServerReporting.php file, but I find this hard to believe. Like you, my organization doesn't authorize open-source. So I've been working to translate the PHP into ASP without any success.

The biggest issue that I have had with the conversion process is getting the variables from the SWF. Once I can get that, I'll be able to create the new internalServerReporting.asp file without a hitch.

So far, I've tried using request.form("companyName"), session("companyName"), request.querystring("companyName") without any success in order to just grab the variables needed to create the directory. I've also dissected the AS3 in the SWF file itself, found where it creates the XML and everything; I just cant figure out how to get the information from the dataString variable in the SWF to the ASP page.

So right now, I'm stumped for using the internal server reporting. There also seems to be an article at CaptivateDev that has a complete How-To using SCORM. I may try going that route using ASP shortly.

RichardGAuthor
Inspiring
March 18, 2011

When I looked at the php code, it is definitely submitting form variables, so I would think also that the request.form("companyName") should work.  I'm very inexperienced at .NET so can't really offer any assistance, but is there a facility for .net to receive and dump to the screen all form variables submitted to a page?  As a structure or array perhaps? I could put a page together in Coldfusion for you to submit either the php or .net page to which would return all form variables to the screen.  It would basically be:

<cfdump var="#form#">

Is there an equivalent in .NET?

This would at least tell us what the data looks like.Do you want to try and work on this off-line?

Inspiring
March 23, 2011

I'm not too familiar with .net either. But with ASP classic, W3 Schools discusses the different objects that get information from the visitor. Since I wasn't able to get the information from the visitor, I even tried grabbing the session variables with Session.Contents without any success.

Request.Form by itself will check for the querystring in the URL and for form objects; neither have worked that I can tell. Now, if the variables are dumped via an array, I'd have to know what array to look for and that doesn't look too promising without knowing the name of the array.

Here's something else.  I threw the below code (along with other ServerVariables) into my InternalServerReporting.asp file that my quiz points to:

f.WriteLine("CONTENT_TYPE: " & Request.ServerVariables("CONTENT_TYPE") & vbcrlf & vbcrlf)

The results came back as:

CONTENT_TYPE: multipart/form-data; boundary=314159265358979323846

I'm kinda glad I found this. ASP classic has issues (pretty much doesn't support) with multipart/form-data according to MSDN's article Uploading Files Using the File Field Control and other Google searches. So asp is out of the question for grabbing the variables. ASP101 has an article on Uploading multiple files to your ASP script which I'm going to take a look and to try and implement.

From what I gather .NET and ColdFusion both can handle multipart/form-data. Can you take a look into ColdFusion? I think keeping here will help eleviate other peoples issues when trying to move to another serverside script.