rusticisoftware / tincan.net Goto Github PK
View Code? Open in Web Editor NEWC#/.NET library for Tin Can API
Home Page: http://rusticisoftware.github.io/TinCan.NET/
License: Apache License 2.0
C#/.NET library for Tin Can API
Home Page: http://rusticisoftware.github.io/TinCan.NET/
License: Apache License 2.0
Because AgentAccount.HomePage
is of type System.Uri
, its ToString()
returns a canonicalized version of the original string (for more details, see this link and scroll down to question 4). This leads to issues the value that is stored could be different from the value that was used when creating the object. For example, the value is automatically lowercased, as evidenced by this dotnetfiddle.
There's been a similar issue with Activity IDs (see #10 for more). This could be handled similarly, or by using Uri.OriginalString
like I've shown in the earlier dotnetfiddle.
Hi, I'm a pretty experienced Unity dev with little to no web security experience and I've been struggling a lot to get xAPI working here over the last few months. Currently, I am using WebScarab to debug my HTTp traffic, and I see that each of my xAPI posts to the endpoint with code 200: Ok. However, within the code in Unity it is clear that OK is not okay, as HTTPStatusCode.OK causes lrsResponse.success to always return false. Thus, no UUID is generated and my statement doesn't post to the LRS. I do not understand why OK is not sufficient for xAPI in Unity, as the W3 documentation on HTTP status codes says that OK indicates "The request has succeeded. The information returned with the response is dependent on the method used in the request." Does something need to happen on my end? Or on the end of the LRS? I'd be happy to provide further details for anyone who may be able to help.
Hey everyone,
if the connection is not stable (maybe because of wrong url or other stuff) I would like to make a local backup. so far everything is already implemented. But when for example I entered the wrong url, the whole execution takes a very long time. During this time my application is frozen.
I guess the timeout is quite long, so the idea would be that the timeout needs to be smaller so that the user does not get the feeling of a frozen application.
Here is my code:
var lrs = new RemoteLRS(
trackingInitializer.LRS,
trackingInitializer.BasicAuthUsername,
trackingInitializer.BasicAuthPassword
);
try
{
StatementLRSResponse lrsResponse = lrs.SaveStatement(statement);
if (lrsResponse.success)
{
....Do Stuff ....
}
}
catch(Exception e)
{
... save local backup ....
}
App can be built in 32bit mode (Mono scripting backend), but building for 64bit creates a Linker error:
"No action for the assembly TinCan, Version=1.3.0.0, Culture=neutral, PublicKeyToken=7e2d97554f738180 defined"
Is TinCan not compatible with 64bit publishing?
The sample code under Basic Usage (http://rusticisoftware.github.io/TinCan.NET/) will not compile.
The first issue is that the code is not contained in a function.
The second is that the line:
``activity.id = new Uri ("http://rusticisoftware.github.io/TinCan.NET");
gives the error "Cannot implicitly convert type "system.Uri" to string. Oddly, the previous section following this format does not give this error.
When I try to build for webGL in Unity 202.3.23, I get a long error which includes the following: System.InvalidOperationException: No action for the assembly TinCan, Version=1.3.0.0, Culture=neutral, PublicKeyToken...
The build for Android is successful, and the LRS receives the xAPI statement as it should.
Hi,
I'm trying to insert gps positions as Extensions into Context Object.
When I call the object i can't find how to insert the values.
This is the code I use to write a context part in the statement
var objContext = new Context();
objContext.extensions = new TinCan.Extensions();
how can now insert the user gps positions?
"http://id.tincanapi.com/extension/latitude" = userLatCoord;
"http://id.tincanapi.com/extension/longitude" = userLongCoord;
Thanks in advance...
Andrea
According to the xAPI specification:
A Client making a PUT request to either the Agent Profile Resource or Activity Profile Resource MUST include the "If-Match" header or the If-None-Match header.
This breaks the RemoteLRS.SaveActivityProfile()
and RemoteLRS.SaveAgentProfile()
methods, as they don't set any of these headers and don't expose the possibility to manage them. These methods are unusable with the ADL LRS, or any LRS strictly following the specification.
A quick test using TinCanJS shows that the client sends the following header with the PUT request: If-None-Match:*
.
Side note
The ADL LRS has a strange behavior when handling the request without If-None-Match
header. It returns a HTTP 400 status code (as expected), but a subsequent call listing the profiles associated with the activity or agent (ex : GET https://lrs.adlnet.gov/xAPI/activities/profile?activityId=xxx
) returns a list containing the ID of the profile included in the invalid request. The associated document is empty.
I have the Tincan.dll file that act as intermediarie for sending XAPI statements in an android app build with Unity using Vuforia, .
When I try the same app within the editor it works and send the correspondent XAPI statements inmediatelly but when I run the app with the android device (whereas it is normally or in debug) it does not send the statements.
By debugging I notice that the problem is in the tincan.dll function called lrs.SaveStatement(statement); which does not return neither a valid or an error message response. As I can not debug the dll function I can not determine if the error is within the dll function or the android device settings (which can be probable but I do not know the settings to change).
I have followed the tutorial from amazick119 https://www.youtube.com/watch?v=zX8Pq9STvoo
ADL released xAPI 2.0.0 as an IEEE Standard on October 20th, 2021. Here are the spec : xAPI Base Standard Documentation.
When will TinCan.NET support 2.0.0?
From the TinCan API spec, I believe that the ActivityID specified as a query parameter should be case-sensitive.
While using an Uri object to store the ActivityID, this is actually helpful in ensuring proper format, URIs in .Net are case insensitive and actually lose their casing when converted to string. I suggest using a different approach that can keep the original casing. I found Uri.OriginalString to be helpful.
This behavior is implemented in TinCan.StatementsQuery.ToParameterMap()
I hope you can also review this for the other parameters as well.
I am attempting to use the StatementQuery class to create a query of a specific actor name. However, each time I query the LRS it returns all the statements regardless of actor name. My code is identical to the sample code for Statement query.
Hey everyone,
is it possible to convert a json/string object easily into the statement object?
If the xAPI can not be transmitted to an LRS (due to connection problems or something else) the statement needs to be locally stored. An easy option would be to just save it in an extra json or txt file, but therefore the statement object needs to be converted into json or into a string. In order to transmit the statement later, the string/json needs to be reconverted into a statement.
Thanks in advance
Annabelll
The current implementation allows an actor to have nested groups. Since a Group inherits from an Agent you can have a group containing nested groups.
This is against the spec:
ADL released xAPI 1.0.3 on september 21st, 2016. When will TinCan.NET support 1.0.3? Even if it just means updating the supported versions list and the latest/default version used by the client.
I'm working on integrating this TinCan library into some software and am finding that it freezes briefly whenever I try writing some data to the LRS. Has there been any thought towards making this asynchronous? Ideally it could internally manage an ongoing queue of requests rather than blocking for each one.
Hi,
I have recently gotten xAPI messages working out of unity to the Scorm cloud LRS. However, whenever I attempt to use the endpoint I actually want to use I get "Object reference not set to an instance of an object" in the Catch block on line 186. Is there anything in particular that could cause this on my end? And if not, is there anything glaringly wrong with their url?
connection succeeds at: https://cloud.scorm.com/tc/(MyUserID)/
WebException caused at: https://me.backpack.education/planner/api/
Thanks for your time
I have the following WebAPI controller code to catch PUT STATEMENT calls and inside the controller call my ViewModel to save the statement to my repository. On looking at the TinCan.Statement variable statement on the controller the StatementTarget always returns null despite this being called in the GolfCourseExample so I think that there may be an issue with this. The name of the pages in the GolfCourseExample eg 'Par' 'Golf Etiquette' are all displayed in SCORM cloud statements but using this method I cannot get the required object
//Controller
public void Put([FromBody]TinCan.Statement statement)
{
xvm.PutStatement(statement);
}
//ViewModel
public void PutStatement(TinCan.Statement statement)
{
ExperienceStatement newStatement = new ExperienceStatement();
newStatement.StatementString = statement.ToJObject().ToString();
ExperienceStatementRepository.Add(newStatement);
ExperienceStatementRepository.SaveChanges();
}
After putting all the necessary info into RemoteLRS (url, username, password), I receive an error trying to save the statement to the LRS. After I build the statement, I do a lrs.SaveStatement(statement) but receive the following error
Error getting response stream (Write: The authentication or decryption has failed.): SendFailure. It happens in the MakeSyncRequest() once it hits the GetRequestStream() call. Both myself and ADL get the same error even though ADL can see pinging of the IP address each time a statement attempts to be sent. Anyone know why this is an issue.
Need to implement saving of attachments with statements.
Need to implement the various interaction parts of the Statement model.
Not sure if I'm missing something, but extensions are in the spec for Activity definitions, but not included in the Activity class.
https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#41-extensions
https://xapi.com/blog/deep-dive-extensions/
When I want to add an id to an activity, I get this error:
CS0029 C# Cannot implicitly convert type 'System.Uri' to 'string'
Seems to be some wrong implementations for activity id. Id for Verb is okay, but not for activity.
Any chance of getting this recompiled into .NET Standard? As it is it's blocking upgrades. (yes with .NET Standard you can sort of us this, but you can't use it to deploy to Linux or docker as a result.)
Thanks!
The saveDocument
implementation doesn't send the ETag when available on the passed document. It needs to, it may also need to set it when 'content' is set.
I used the following code:
var verb = new Verb();
verb.id = new Uri("http://adlnet.gov/expapi/verbs/" + verbString);
verb.display = new LanguageMap();
verb.display.Add("Test", "Test2");
verb.display.Add("en-US", verbString);
Console.WriteLine(JsonConvert.SerializeObject(verb, Formatting.Indented));
the output is:
{
"id": "http://adlnet.gov/expapi/verbs/focussed",
"display": {}
}
As you can see, the Language Map seems to be initialized, but adding was not successful.
Debugging gives me this:
-- | -- | -- | --
◢ | verb | {TinCan.Verb} | TinCan.Verb
| ◢ display | {TinCan.LanguageMap} | TinCan.LanguageMap
| ◢ Non-Public members | |
| ◢ map | Count = 2 | System.Collections.Generic.Dictionary<string, string>
| ▶ [0] | {[Test, Test2]} | System.Collections.Generic.KeyValuePair<string, string>
| ▶ [1] | {[en-US, focussed]} | System.Collections.Generic.KeyValuePair<string, string>
| ▶ Raw View | |
| ◢ id | {http://adlnet.gov/expapi/verbs/focussed} | System.Uri
Need to handle reading multipart/mixed responses from querying statements.
We use the ADL LRS for testing purposes. I started to write unit tests to validate a set of functionality and stumbled accross this problem in my 1st test:
var lrs = new RemoteLRS("https://lrs.adlnet.gov/xAPI/", "<username>", "<password>");
AboutLRSResponse about = this._lrs.About(); // throws exception
The problem is that the LRS returns a json containing this list of versions: "version": ["1.0.0", "1.0.1", "1.0.2", "1.0.3"]
, and the .NET client tries to map each of them to a known hard coded version, although it does not yet "know" the version 1.0.3! (deserialization exception when executing version.Add((TCAPIVersion)item);
)
Other related issue: TCAPIVersion.latest()
currently returns 1.0.1
, although 1.0.2
is in the supported versions list. In my opinion, TCAPIVersion.latest()
should return the latest entry in the supported list, and the supported list should or should not include 1.0.2
, depending on the state of your implementation.
I've successfully integrated this library into my Unity3D application. However, I now have a client that is asking for me to provide a "tincan zip package".
My understanding is that tincan zip packages can be dropped into any LMS and will automatically send statements to that LMS. This seems problematic for me because I am currently hard-coding the URL for the endpoint in my application, and passing it to the RemoteLRS
constructor.
From what I've read on the tincanapi.com
, the tincan zip package needs to include a tincan.xml file at the root of the package, then it looks like it retrieves the endpoint and user information by parsing the URL query parameters? This is where I'm a bit unclear.
So my question is, now that I'm successfully using the TinCan.NET library in my application, how do I make my application into a tincan zip package?
Thanks
Is it possible to change this technology (WebClient ) to use HttpClient?
as it is no longer compatible with the latest technologies, such as blazor.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.