Skip to content

Extensions

Extension methods over ILmsRuntime for the handful of operations every course performs. Nothing here adds capability — each method is a shorter, harder-to-misuse spelling of a data-model write — and each group is in its own file so the set stays browsable.

File Methods
LmsStatusExtensions MarkCompleted, MarkPassed, MarkFailed, MarkIncomplete, SetScore
LmsCompletionExtensions CompleteCourseAsync, PassCourseAsync, FailCourseAsync
LmsBookmarkExtensions SetBookmark, GetBookmark, HasBookmark, ClearBookmark, GetResumeLocation
LmsSuspendDataExtensions SetSuspendObjectSafe<T>, TryGetSuspendObject<T>, and the raw-JSON pair
LmsSessionTimeExtensions AddSessionTime, AddSessionSeconds, ResetSessionTime
LmsCommitExtensions SaveProgressAsync
LmsExitExtensions SuspendAsync, SetExit

The ...Async ones are the pairings worth knowing: PassCourseAsync sets score, success and completion and then commits, in the order a 2004 LMS expects, rather than leaving the caller to get the sequence right.

SetScore takes raw, min and max together for the same reason. SCORM 2004 derives scaled from the range, so a raw score written without its bounds is reportable but not comparable.

Why extensions rather than interface members

Every one of these could have been an ILmsRuntime member. Keeping them out means the interface stays small enough to implement — the stub runtime, the WebGL runtime and the test fakes each implement it in full — while this layer grows without forcing a new member on every implementor. A course can also ignore the lot and write to Cmi directly.

The trap next door

DescribeLastError() is the method you will reach for alongside these, and it lives in SCORM/Helpers/ScormErrors.cs rather than here, because it decodes SCORM error numbers.

It reports the most recent call that actually reached the LMS. A write RevLearning blocks before it gets there — after FinishAsync, or outside a live session — does not refresh LastError, because the LMS was never asked; those are console warnings instead. So a single LastError check after a batch of writes can read None precisely when the writes are being discarded. Check the result of SaveProgressAsync/CommitAsync, or check after the individual write you care about.