Search code examples
coldfusionscormtin-can-apiarticulate-storyline

TinCan/xAPI - Resume Prompt Not Working


I have built my own simple LMS in ColdFusion. It just uses an iframe to display the course and there is a page that records the tin can statements. It works perfect but I have a course designed in Studio '13/presenter '13, output is tincan, that the resume feature doesn't work on my LMS.

If I use presentation.html, example

https://www.domainname.com/folder/courses/example_course/presentation.html?&actor={"name":["My_Name"],"mbox":["mailto:[email protected]"],"objectType":["Agent"]}&endpoint=https://www.domainname.com/folder/courses/&course_id=5&uuid=9AE6DEA4-9C19-F477-19B9822F1E2F0722&registration=36fc1ee0-2849-4bb9-b697-71cd4cad1b6e&activity_id=https://www.domainname.com/folder/courses/&auth=Basic TG9naW46UGFzc3dvcmQ=

the resume doesn't work but the tincan statements post to my site properly.

If I use presentation_html5.html, example

https://www.domainname.com/folder/courses/example_course/presentation_html5.html?&actor={"name":["My_Name"],"mbox":["mailto:[email protected]"],"objectType":["Agent"]}&endpoint=https://www.domainname.com/folder/courses/&course_id=5&uuid=9AE6DEA4-9C19-F477-19B9822F1E2F0722&registration=36fc1ee0-2849-4bb9-b697-71cd4cad1b6e&activity_id=https://www.domainname.com/folder/courses/&auth=Basic TG9naW46UGFzc3dvcmQ=

the resume does work but the tincan statements don't post.

I've followed the tutorial and setup the resume feature: http://www.articulate.com/support/presenter-09/enabling-and-disabling-the-prompt-to-resume-function

I have tried the course on several different websites on several different server, and in several different browsers (IE 11, FF 34.0.5, Chrome 39.0.2171.95 m), current version of Flash.

The resume function doesn't work.

I have tried the course with all the different options, prompt, etc, flash cookies enable and disabled.

The resume function doesn't work.

I have tried the course on Scorm Cloud. The resume function works! I have opened presentation.html on my computer in FireFox. The resume function works.

I've narrowed the issue down to TinCan. If I turn TinCan off in the presentation.html file by changing

var g_bTinCan = true; to var g_bTinCan = false;

The course resumes as it should. But since TinCan is off, it doesn't post any statements to my LMS.

I've figured out that I probably need to respond to POST state?method=GET with the state/resume data. So something like this

1Nk30a010904050607080b0on1001811f016110171101811000 (tells the course to go to slide 4 or some thing like that).

I understand the data is encoded/compressed. The data actually comes from the state data posted to the LMS. Each slide posts a resume point. I'm guessing I just need to grab that resume point data from the previous session and post back when the user resumes the course and tincan asks for resume data.

But for some reason, no matter what I return and how I return it. My course just sits there loading. Everything is there, nav bar, course extras, exit button, just the content has the loading sign. Nothing is clickable.

I've tried posting back similar headers that scorm cloud uses in ColdFusion:

Access-Control-Allow-Header: Content-Type,Content-Length,Authorization,If-Match,If-None-Match,X-Experience-API-Version,X-Experience-API-Consistent-Through
Access-Control-Allow-Origin: *
Access-Control-Expose-Header: ETag,Last-Modified,Cache-Control,Content-Type,Content-Length,WWW-Authenticate,X-Experience-API-Version,X-Experience-API-Consistent-Through
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
X-Experience-API-Version: 1.0.0
access-control-allow-methods: HEAD,GET,POST,PUT,DELETE

They come through properly along with the response: 1Nk30a010904050607080b0on1001811f016110171101811000

I've tried the return format as json, plain text, an array. But the course doesn't load. I've also found odd behavior if I refresh then stop the browser immediately (the course never refreshes). It will bring up the resume prompt and then I can click Yes/No. And it works. Obviously that isn't right.

Any ideas? What am I missing? I'm looking for what an Articulate course is expecting as a response from my (or any) LMS/LRS when it asks for a resume point on state?method=GET.

Edit

@Brian: content-type is application/json

LRS should be returning the Content-Type as it was received This is where it gets tricky. state?method=GET redirects to a cfc function. ../includes/LRSCFC.cfc?method=GetState&returnFormat=plain

This is the function:

<cfheader name="Access-Control-Allow-Header" value="Content-Type,Content-Length,Authorization,If-Match,If-None-Match,X-Experience-API-Version,X-Experience-API-Consistent-Through">
<cfheader name="Access-Control-Allow-Origin" value="*">
<cfheader name="Access-Control-Expose-Header" value="Last-Modified,Cache-Control,Content-Type,Content-Length,WWW-Authenticate,X-Experience-API-Version,X-Experience-API-Consistent-Through">
<cfheader name="Cache-Control" value="no-cache">
<cfheader name="Connection" value="keep-alive">
<cfheader name="Content-Type" value="application/json">
<cfheader name="X-Experience-API-Version" value="1.0.0">
<cfheader name="access-control-allow-methods" value="HEAD,GET,POST,PUT,DELETE">
<cfreturn '1s43040ji1001111a0101101111000'>

The problem is if tell CF to return as json using the function, returnFormat=json, or serializeJSON(). It adds stuff to the returned data.

The above code will return:

1s43040ji1001111a0101101111000

telling CF to use json:

//"1s43040ji1001111a0101101111000"

Which is a secure feature of CF.

But what confuses me is Scorm Cloud just returns

1s43040ji1001111a0101101111000

It isn't formatted like JSON. It just seems like it is plain text even though the Content-Type is application/json.

If I return all the cfheader info but leave cfreturn blank cfreturn "" the course just sits there as if I returned "1s43040ji1001111a0101101111000"

1s43040ji1001111a0101101111000 - Should jump the user to slide 3.

What status code are you returning? 200 OK

Any other status, the course will play but will complain it can't connect to the server.

@Andrew

Any errors, successes, requests in progress? No errors. Seems like everything is successful. no requests in progress.


Solution

  • I figured out my problem. I was missing Content-Length in the headers. Content-Length is just the length of the response data. So I added this:

    <cfheader name="Content-Length" value="#len('1s43040ji1001111a0101101111000')#">
    

    To my current code, like so:

    <cfheader name="Access-Control-Allow-Header" value="Content-Type,Content-Length,Authorization,If-Match,If-None-Match,X-Experience-API-Version,X-Experience-API-Consistent-Through">
    <cfheader name="Access-Control-Allow-Origin" value="*">
    <cfheader name="Access-Control-Expose-Header" value="Last-Modified,Cache-Control,Content-Type,Content-Length,WWW-Authenticate,X-Experience-API-Version,X-Experience-API-Consistent-Through">
    <cfheader name="Cache-Control" value="no-cache">
    <cfheader name="Connection" value="keep-alive">
    <cfheader name="Content-Type" value="application/json">
    <cfheader name="X-Experience-API-Version" value="1.0.0">
    <cfheader name="access-control-allow-methods" value="HEAD,GET,POST,PUT,DELETE">
    <cfheader name="Content-Length" value="#len('1s43040ji1001111a0101101111000')#">
    <cfreturn '1s43040ji1001111a0101101111000'>