VBTrain.Net Documentation

Techniques For Calling LMSFinish (SCORM 1.2) or Terminate (SCORM 1.3)

Discussion

When a SCORM lesson (also called a Sharable Content Object or SCO) is finished communicating with the Learning Management System (LMS), it needs to send LMSFinish (SCORM 1.2) or Terminate (SCORM 1.3). The SCORM_1.2_RunTimeEnv.doc from Advanced Distributed Learning (ADL), http://www.adlnet.org/, explains the purpose of this as follows.

This call signifies two things:

  1. The SCO can be assured that any data set using SetValue() calls has been persisted by the LMS.
  2. The SCO has finished communicating with the LMS.

Therefore you want to call LMSFinish/Terminate when and only when you are done communicating with the LMS. You want to avoid calling it when a lesson page changes or unloads in a postback situation.

When you provide a server side Exit button in your lesson, it is a fairly simple matter to handle the Click event and use the LmsApi object to insert the necessary JavaScript as shown (the sendFinish = false is explained in detail below):

[Visual Basic]
Private Sub BtnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnExit.Click
   Dim apiObject As LmsApi2 = Me.LmsApiObject
   Dim js As String
   Dim sb As New StringBuilder

   js = apiObject.GetJsApiLocate()
   Me.RegisterClientScriptBlock("apiLocate", js)

   With sb
      .Append("<script language='javascript'>" & CrLf)
      .Append("var sendFinish = false;" & CrLf)
      .Append("</script>" & CrLf)
      .Append(apiObject.GetJsForLogoff(LogoffEnum.Terminate, _
         LogoffOptionsEnum.callsPlusWindowClose, "parent"))
   End With
   SetSendFinishLiteral.Text = sb.ToString

   apiObject.Dispose()
   apiObject = Nothing
   Me.LmsApiObject.Dispose()
   Me.LmsApiObject = Nothing
End Sub

A more difficult issue is how to handle the user closing the SCO with the x in the upper right of the SCO window. One answer, demonstrated in the LmsApi sample applications, is to place a JavaScript function on your page that calls LMSFinish/Terminate. You invoke this function, again in JavaScript, on window unload. However you don't want to call this in postback situations or when the user closes the window with the Exit button -- only when the user closes the window with the x.

To check for a postback situation or an Exit button click, we use a flag, sendFinish, that we initialize to true when the page loads and set to false in the onsubmit JavaScript handler and in the BtnExit_Click Code Behind handler (shown above). We then check this flag in the onunload handler and only call our logoff function if the flag is still true. See the related JavaScript and Code Behind shown below for details.

JavaScript

The following code is in the HTML of the navigation form (navBar.aspx) of the LmsApi Navigation Sample. We use a similar technique in the LmsApi Question Sample.

[JavaScript]
<script id="clientEventHandlersJS" language="javascript">

var sendFinish = true;

function window_onunload() {
   if (sendFinish == true)
      lmsLogoff();
}

function navBar_onsubmit() {
   sendFinish = false;
}

</script>

Code Behind

The following code is in the navigation form (navBar.aspx.vb) of the LmsApi Navigation Sample. It assumes that the VBTrain.WebTracking namespace has been imported, and that the LmsApi for the session is stored as a property (LmsApiObject) of the class.

We use a similar technique in the LmsApi Question Sample.

[Visual Basic]
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

   ' other code here
   Call InsertLogoffFunction()
End Sub

Private Sub InsertLogoffFunction()
   Dim apiObject As LmsApi2 = Me.LmsApiObject
   Dim js As String

   ' locate api 
   js = apiObject.GetJsApiLocate()
   Me.RegisterClientScriptBlock("apiLocate", js) 
   ' logoff function
   js = apiObject.GetJsForLogoff(LogoffEnum.Terminate, _
      LogoffOptionsEnum.callsInsideFunction)
   Me.RegisterClientScriptBlock("logoffFunction", js)
End Sub

See Also

LmsApi2 Class | LmsApi Members | Navigation Sample | Question Sample