Class XapiClient
The xAPI resources of one LRS over an HttpClient: Statements, State, Activity Profile, Agent
Profile, Agents, Activities and About (IEEE 9274.1.1, 4.1.6). Every request carries the
X-Experience-API-Version header and, if configured, credentials.
public class XapiClient
- Inheritance
-
XapiClient
- Inherited Members
Remarks
Error responses throw XapiHttpException, or its subclasses XapiConflictException (409) and XapiPreconditionFailedException (412). Methods that fetch one thing by id return null on 404 instead. Network failures and timeouts surface unchanged as HttpRequestException and TaskCanceledException. Nothing is retried.
Responses are read leniently (Lenient): properties the client does not know are ignored.
The client keeps no per-request state and can be shared between threads. The HttpClient is not disposed by the client. Configure timeouts, proxies and handlers on the HttpClient; the transport can be any HttpMessageHandler.
There is no built-in retry. With dependency injection, add one to the HttpClient pipeline; see
AddXapiClient. For offline use and guaranteed delivery, use an outbox instead.
The service methods are virtual so that tests can replace them: derive from the class, call the protected constructor XapiClient() and override the methods the code under test calls. Each method stands alone; overriding one does not change what another does.
Constructors
XapiClient()
Creates a client that cannot send anything, for mocking: a test double derived from XapiClient calls this constructor and overrides the methods it needs.
protected XapiClient()
Remarks
The methods that are not overridden throw InvalidOperationException.
XapiClient(HttpClient, XapiClientOptions)
Creates a client.
public XapiClient(HttpClient httpClient, XapiClientOptions options)
Parameters
httpClientHttpClientThe HTTP client to send requests with.
optionsXapiClientOptionsThe settings. They are copied; later changes have no effect.
Exceptions
- ArgumentException
Endpoint is missing or not absolute.
Methods
DeleteDocumentAsync(DocumentKey, DocumentPrecondition?, CancellationToken)
Deletes one document.
public virtual Task DeleteDocumentAsync(DocumentKey key, DocumentPrecondition? precondition = null, CancellationToken cancellationToken = default)
Parameters
keyDocumentKeyWhich document.
preconditionDocumentPreconditionAn
If-Matchcondition, to delete only the version last read.cancellationTokenCancellationTokenCancels the request.
Returns
- Task
A task that completes when the LRS has deleted the document.
Exceptions
- XapiPreconditionFailedException
The precondition failed.
DeleteStatesAsync(Iri, Agent, Guid?, CancellationToken)
Deletes every State document of an Activity and Agent (and registration).
public virtual Task DeleteStatesAsync(Iri activityId, Agent agent, Guid? registration = null, CancellationToken cancellationToken = default)
Parameters
activityIdIriThe Activity.
agentAgentThe Agent.
registrationGuid?Only the states of this registration; all registrations when null.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task
A task that completes when the LRS has deleted the documents.
GetAboutAsync(CancellationToken)
Fetches the About resource: the xAPI versions the LRS supports, and extensions.
public virtual Task<About> GetAboutAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenCancels the request.
Returns
GetActivityAsync(Iri, CancellationToken)
Fetches the LRS's definition of an Activity (Activities resource).
public virtual Task<Activity?> GetActivityAsync(Iri activityId, CancellationToken cancellationToken = default)
Parameters
activityIdIriThe Activity id.
cancellationTokenCancellationTokenCancels the request.
Returns
GetActivityProfileIdsAsync(Iri, DateTimeOffset?, CancellationToken)
Lists the Activity Profile ids for an Activity.
public virtual Task<IReadOnlyList<string>> GetActivityProfileIdsAsync(Iri activityId, DateTimeOffset? since = null, CancellationToken cancellationToken = default)
Parameters
activityIdIriThe Activity.
sinceDateTimeOffset?Only ids of documents stored or changed after this time.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<IReadOnlyList<string>>
The
profileIdvalues.
GetAgentProfileIdsAsync(Agent, DateTimeOffset?, CancellationToken)
Lists the Agent Profile ids for an Agent.
public virtual Task<IReadOnlyList<string>> GetAgentProfileIdsAsync(Agent agent, DateTimeOffset? since = null, CancellationToken cancellationToken = default)
Parameters
agentAgentThe Agent.
sinceDateTimeOffset?Only ids of documents stored or changed after this time.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<IReadOnlyList<string>>
The
profileIdvalues.
GetDocumentAsync(DocumentKey, CancellationToken)
Fetches one State, Activity Profile or Agent Profile document.
public virtual Task<XapiDocument?> GetDocumentAsync(DocumentKey key, CancellationToken cancellationToken = default)
Parameters
keyDocumentKeyWhich document.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<XapiDocument>
The document with its ETag, or null when the LRS answers 404.
GetMoreStatementsAsync(Uri, CancellationToken)
Fetches the next page of a Statement query.
public virtual Task<StatementResult> GetMoreStatementsAsync(Uri more, CancellationToken cancellationToken = default)
Parameters
moreUriThe More of the previous page.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<StatementResult>
The page.
Remarks
Only the path and query of more are used; they are sent to the scheme, host and port of
Endpoint, so credentials never go to another host. A path without a leading
slash is resolved against the endpoint.
GetPersonAsync(Agent, CancellationToken)
Fetches the Person object the LRS knows for an Agent (Agents resource).
public virtual Task<Person> GetPersonAsync(Agent agent, CancellationToken cancellationToken = default)
Parameters
agentAgentThe Agent.
cancellationTokenCancellationTokenCancels the request.
Returns
GetStateIdsAsync(Iri, Agent, Guid?, DateTimeOffset?, CancellationToken)
Lists the State ids for an Activity and Agent (and registration).
public virtual Task<IReadOnlyList<string>> GetStateIdsAsync(Iri activityId, Agent agent, Guid? registration = null, DateTimeOffset? since = null, CancellationToken cancellationToken = default)
Parameters
activityIdIriThe Activity.
agentAgentThe Agent.
registrationGuid?The registration, if the states are tied to one.
sinceDateTimeOffset?Only ids of documents stored or changed after this time.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<IReadOnlyList<string>>
The
stateIdvalues.
GetStatementAsync(Guid, StatementFormat, CancellationToken)
Fetches one Statement by id (statementId). Voided Statements are not returned.
public virtual Task<Statement?> GetStatementAsync(Guid id, StatementFormat format = StatementFormat.Exact, CancellationToken cancellationToken = default)
Parameters
idGuidThe Statement id.
formatStatementFormatHow much of Agents, Activities and Verbs to return.
cancellationTokenCancellationTokenCancels the request.
Returns
GetVersionAsync(CancellationToken)
The xAPI version used for requests: Version, or the version negotiated with the About resource on first use.
public virtual Task<XapiVersion> GetVersionAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenCancels the wait for the negotiation.
Returns
- Task<XapiVersion>
The version.
Exceptions
- NotSupportedException
The LRS supports neither 2.0.x nor 1.0.x.
GetVoidedStatementAsync(Guid, StatementFormat, CancellationToken)
Fetches one voided Statement by id (voidedStatementId).
public virtual Task<Statement?> GetVoidedStatementAsync(Guid id, StatementFormat format = StatementFormat.Exact, CancellationToken cancellationToken = default)
Parameters
idGuidThe id of the voided Statement (not of the voiding one).
formatStatementFormatHow much of Agents, Activities and Verbs to return.
cancellationTokenCancellationTokenCancels the request.
Returns
MergeDocumentAsync(DocumentKey, JsonElement, DocumentPrecondition?, CancellationToken)
Merges a JSON object into a document (POST): each top-level property replaces the one in the stored JSON object. Creates the document if it does not exist.
public virtual Task MergeDocumentAsync(DocumentKey key, JsonElement json, DocumentPrecondition? precondition = null, CancellationToken cancellationToken = default)
Parameters
keyDocumentKeyWhich document.
jsonJsonElementA JSON object.
preconditionDocumentPreconditionAn
If-MatchorIf-None-Matchcondition.cancellationTokenCancellationTokenCancels the request.
Returns
- Task
A task that completes when the LRS has stored the result.
Exceptions
- ArgumentException
jsonis not an object.- XapiPreconditionFailedException
The precondition failed.
PutDocumentAsync(DocumentKey, XapiDocument, DocumentPrecondition?, CancellationToken)
Stores a document, replacing any existing one (PUT).
public virtual Task PutDocumentAsync(DocumentKey key, XapiDocument document, DocumentPrecondition? precondition = null, CancellationToken cancellationToken = default)
Parameters
keyDocumentKeyWhich document.
documentXapiDocumentThe content and content type. Its ETag and Last-Modified are not sent.
preconditionDocumentPreconditionAn
If-MatchorIf-None-Matchcondition.cancellationTokenCancellationTokenCancels the request.
Returns
- Task
A task that completes when the LRS has stored the document.
Remarks
Without a precondition, xAPI 2.0 LRSs answer 409 when the document already exists
(IEEE 9274.1.1, 4.1.4). Use IfNoneMatchAny to create and
IfMatch(string) to replace.
Exceptions
- XapiPreconditionFailedException
The precondition failed.
- XapiConflictException
The document exists and no precondition was sent.
QueryAllStatementsAsync(StatementQuery, CancellationToken)
Runs a Statement query and follows more until the last page, one page request at a time.
public virtual IAsyncEnumerable<Statement> QueryAllStatementsAsync(StatementQuery query, CancellationToken cancellationToken = default)
Parameters
queryStatementQueryFilters and options.
cancellationTokenCancellationTokenCancels the enumeration.
Returns
- IAsyncEnumerable<Statement>
Every matching Statement.
Remarks
Attachment data is not returned; use QueryStatementsAsync(StatementQuery, CancellationToken) for that.
QueryStatementsAsync(StatementQuery, CancellationToken)
Fetches the first page of a Statement query.
public virtual Task<StatementResult> QueryStatementsAsync(StatementQuery query, CancellationToken cancellationToken = default)
Parameters
queryStatementQueryFilters and options.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<StatementResult>
The page; follow More with GetMoreStatementsAsync(Uri, CancellationToken).
SaveStatementAsync(Statement, IReadOnlyList<AttachmentPayload>?, CancellationToken)
Stores one Statement: PUT with statementId when Id is set, POST otherwise.
public virtual Task<Guid> SaveStatementAsync(Statement statement, IReadOnlyList<AttachmentPayload>? attachments = null, CancellationToken cancellationToken = default)
Parameters
statementStatementThe Statement.
attachmentsIReadOnlyList<AttachmentPayload>Data for the Statement's Attachments that have no
fileUrl. When there is any, the request is sent asmultipart/mixed.cancellationTokenCancellationTokenCancels the request.
Returns
Exceptions
- XapiValidationException
The Statement is invalid and ValidateBeforeSend is on.
- XapiConflictException
The LRS has a different Statement with the same id.
SaveStatementsAsync(IReadOnlyList<Statement>, IReadOnlyList<AttachmentPayload>?, CancellationToken)
Stores a batch of Statements with one POST. The LRS stores all or none of them.
public virtual Task<IReadOnlyList<Guid>> SaveStatementsAsync(IReadOnlyList<Statement> statements, IReadOnlyList<AttachmentPayload>? attachments = null, CancellationToken cancellationToken = default)
Parameters
statementsIReadOnlyList<Statement>The Statements.
attachmentsIReadOnlyList<AttachmentPayload>Data for Attachments that have no
fileUrl, in any of the Statements.cancellationTokenCancellationTokenCancels the request.
Returns
- Task<IReadOnlyList<Guid>>
The Statement ids, in the order of
statements.
Remarks
An empty batch returns an empty list without a request.
Exceptions
- XapiValidationException
A Statement is invalid, or two share an id, and ValidateBeforeSend is on.
- XapiConflictException
The LRS has a different Statement with the id of one in the batch.
VoidStatementAsync(Guid, Actor, CancellationToken)
Voids a Statement by storing a Statement with the voided Verb and a StatementRef to it.
public virtual Task<Guid> VoidStatementAsync(Guid statementId, Actor actor, CancellationToken cancellationToken = default)
Parameters
statementIdGuidThe id of the Statement to void.
actorActorWho voids it.
cancellationTokenCancellationTokenCancels the request.
Returns
Remarks
IEEE 9274.1.1, 4.2.5. The voided Statement is then only returned by GetVoidedStatementAsync(Guid, StatementFormat, CancellationToken).