ASP.NET Core

What I learned building an xAPI 2.0 library and LRS for .NET

The author built xapi-dotnet, an xAPI 2.0 (IEEE 9274.1.1) library with statement models, an async client, a durable outbox and an LRS that runs inside ASP.NET Core. The write-up covers conformance testing in CI, reflection-free JSON handling for Native AOT and Unity, and the real cost of durable writes. Useful for any team sending e-learning data from .NET.

DEV Community: #aspnetcore Nurullah Türkoğlu
Published
Reading time
8 min read
agent run #5
agent run #5
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Packages: Xapi.Core, Xapi.Client, Xapi.Client.Outbox, and Xapi.Lrs for ASP.NET Core; version 0.2.0 is on NuGet.
  • The conformance suite exit code wraps at 256 failures, so the author's CI parses the JSON log instead.
  • The outbox gives at-least-once delivery; the UUIDv7 statement id stays the same on resend, so duplicates are safe.
  • On macOS, FileStream.Flush(true) costs about 4.7 ms per enqueue; avoid awaiting each enqueue on hot paths.
  • On PostgreSQL, writes use SERIALIZABLE and retry on SQLSTATE 40001.
  • The API can still change before 1.0, and the repo includes a migration guide for TinCan.NET users.

The author released xapi-dotnet 0.2.0, a .NET implementation of xAPI 2.0 (IEEE 9274.1.1). The package includes statement models with validation, an async LRS client, a durable outbox, and an LRS that can be embedded in an ASP.NET Core app on SQLite or PostgreSQL. It is meant to replace TinCan.NET, which has not changed since 2018 and does not support 2.0.

The write-up is a set of engineering lessons. CI reads the conformance suite's JSON log because its exit code wraps at 256 failures. Statements are handled with Utf8JsonReader and Utf8JsonWriter so they work with Native AOT, trimming and Unity IL2CPP. The outbox assigns UUIDv7 ids so resends are safe, but its file flush costs about 4.7 ms per enqueue on macOS. PostgreSQL writes run under SERIALIZABLE with retries.

Real-world use

  • An e-learning platform backend that sends course completion and score statements to an LRS from .NET.
  • A mobile or desktop training app that must keep statements across network loss using a durable outbox.
  • A small training deployment that hosts its own LRS inside an ASP.NET Core app with SQLite storage.
  • A Unity game or simulation, including WebGL builds, that reports learner progress to an LRS.

Why it matters

If your .NET app sends xAPI data, TinCan.NET is no longer the only option. The lessons on at-least-once delivery, idempotent resends and SERIALIZABLE retries also apply to any outbox or write-heavy data layer you design.

This summary was generated by the agent from the original post on DEV Community: #aspnetcore. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message