How to create a new grade - getting a 400

101 views
Skip to first unread message

Jeffrey Kahn

unread,
Jul 16, 2014, 1:02:17 PM7/16/14
to valenc...@googlegroups.com
Folks,

I am trying to create a grade item.  I am getting a 400 response, which suggests an issue with the JSON.  Does anything look amiss?

I am posting this JSON in the request body:


{"Name":"Jeff1","GradeSchemeId":null,"Description":{"Text":"","Html":""},"CategoryId":"128","Weight":100,"ExcludeFromFinalGradeCalculation":false,"IsBonus":false,"GradeType":"Numeric","CanExceedMaxPoints":false,"ShortName":"J1","MaxPoints":10}


I am using the following code in Java to make the post:


URI gradesURL = _DUC.createAuthenticatedUri( "/d2l/api/le/1.3/6691/grades/", "POST");
 java.net.URL url = new java.net.URL("https://" + gradesURL.toString());
java.net.URLConnection connection = url.openConnection();
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
java.net.HttpURLConnection http = (java.net.HttpURLConnection)connection;

DataOutputStream printout = new DataOutputStream (http.getOutputStream ());
printout.writeBytes(gradesJson.toString());
printout.flush();
printout.close();
           
InputStreamReader in = new InputStreamReader(http.getInputStream());


I am getting a 400 error:


Server returned HTTP response code: 400 for URL: https://hbsp.desire2learndemo.com/d2l/api/le/1.3/6691/grades/?x_a=dTrjhraYSvSn5LvsODpBng&x_b=63fbwYKCepuuUfT5rCYyAJ&x_c=6gfsKzBaSKKAzxS_knMRj-095v3uQNtofuLwl459ZcM&x_d=NNj6lAsnCDzpo_W-XWO2zY_bVmI9W1RA5JIO8-cNoC8&x_t=1405529425&

Desire2Learn Staff: Viktor

unread,
Jul 17, 2014, 9:10:15 AM7/17/14
to valenc...@googlegroups.com
Jeff -- while your 'Description' structure will look like that when passed to you by the back-end service, that's an output representation of the property. The proper input representation of the Description for grade objects is a RichTextInput composite:

{
   "Content": <string>,
   "Type": "Text|Html"
}

This is called out in the docs for Grade.GradeObject, but perhaps not explicitly enough (see the bullets in the sub-section called Providing grade object data blocks).

Jeffrey Kahn

unread,
Jul 17, 2014, 12:04:29 PM7/17/14
to valenc...@googlegroups.com
Viktor,

This is working now, thanks.

I am trying to get grades for all the users for a specific orgUnitId and gradeObjectId.  Is there such a call, I only saw ones for a specific user's grade.  Also, is there a notion of a number / decimal grade distinct from a percentage grade?  I chose the percentage grade type, but saw numeric come back in the JSON.

Jeff


Scott

unread,
Jul 18, 2014, 10:33:39 AM7/18/14
to valenc...@googlegroups.com
Hi Jeff,
You have to do multiple calls to retrieve the grades for multiple users for one gradeObject. There is no single call for multiple users. It would be great if there was though.
Here is the link to the Valence REST routing table if you want to check further: http://docs.valence.desire2learn.com/http-routingtable.html

You have to calculate your percentage from the numerator/denominator or weightednumerator/weighteddenominator which are returned in the JSON block.

Scott

Jeffrey Kahn

unread,
Jul 19, 2014, 6:56:28 PM7/19/14
to valenc...@googlegroups.com
Viktor,

I have been able to perform a variety of grade-related operations successfully.  I am getting a 403 when I don't expect to.

I am calling:

/d2l/api/le/1.3/6691/grades/139/values/1890

where the orgUnitId, gradeObjectId, and userId should all be valid.  I have gone into the course using the user interface and logged in with the user whose credentials are part of the user context.  I can see and enter a grade.  When I PUT, I get 403.

This is my grade object JSON


Any ideas?

Jeff

Desire2Learn Staff: Viktor

unread,
Jul 31, 2014, 2:43:56 PM7/31/14
to valenc...@googlegroups.com
Jeff -- are you getting back body content in the 403? What message is being sent back, if any? 

Desire2Learn Staff: Viktor

unread,
Jul 31, 2014, 3:28:10 PM7/31/14
to
Jeff,

Using the techniques outline in the "Investigating Role Permissions" walkthrough topic in our documentation, I have determined against a development instance (but using the v1.3) APIs, that I can successfully update the grade of a student user in an org unit.

I provided this JSON to the service:

{"PointsNumerator": 5.2, "GradeObjectType": 1}

The calling user context has no role permissions at all except for:

- Grades > See the Grades tool
- Grades > Enter Grades
- Grades > Manage Grades

With these three permissions set for the user role at the course offering level, I can successfully make a call to set a grade for a student in a course.

You will want to ensure that the calling user context has an enrolled role with those permissions, applied to the org unit type in question (a course offering AND/OR the org unit type of the other org unit that owns the grade book, if it's a custom org unit).

If you're getting a 403, Not Authorized (or No Permission) type error here, then the only real reason that should happen is (a) the underlying service cannot establish the operations context for this request, or (b) your calling user context doesn't have the permissions required for the call (and I believe, through experimentation, that it's those three permissions above).

Jeffrey Kahn

unread,
Jul 31, 2014, 4:48:33 PM7/31/14
to valenc...@googlegroups.com
Viktor,

I don't quite understand.  Let's say I have an user enrolled in a course offering with the role Administrator. I want to have this user context post a grade to a course.  When I look at the D2L System Admin Permissions UI, I see that Administrators can do all kinds of grade operations on a course offering.  But I am getting the 403.  Note I am using the same grade JSON you have.

I thought I would try and find out the permissions of the user context.  I seem to need a tool ID for that.  I get the tools, but these only have IDs, I don't know which tool is the grades tool.  So how do I ask whether the user context can enter grades -- even though I don't see why the user wouldn't have the permission I seek.  Alternatively, how do I ask what Grade-related permissions the user has?  I also don't see how to add the permission if I did need it.

I must be missing something basic about how the permissions work.

Jeff

 

 

Desire2Learn Staff: Viktor

unread,
Aug 5, 2014, 10:59:55 AM8/5/14
to valenc...@googlegroups.com
The way role permissions work:

- The system knows about kinds of Roles by a list of role types.

- The system knows about kinds of org units by a list of org unit types.

- Every org unit has an org unit record, keyed by ID, and part of the org unit record is its org unit type (i.e. whether 'course offering', 'department', etc)

- Every user has a user record keyed by ID, part of that user record coming out of the act of user creation, is a "default enrollment"... the enrollment of the user in the org unit context in which they're created -- this is almost certainly going to be the "organization" or the special root org unit node that has the org unit type "organization".

- Every time a user has an enrollment in an org unit, that enrollment represents a binding between the user record, the org unit record, and a role type -- absent of enrollments in org units, users don't really have roles (except for the "special" role they get from their special enrollment-upon-creation).

- Permissions to do things are divided into sets of permissions for 'Tools' -- in the LMS' Admin UI, when you edit permissions, you can look at the entire table, or just the permissions associated with a particular 'Tool'... rarely do permissions from more than one tool bear on what a user is allowed to do, but it does happen (for example, the "User Information Privacy" permissions apply to activity where potentially private user information can be revealed, not just within some "UIP Tool").

- Permissions to do things are also divided into org unit types and role types -- that is, a particular permission applies to any user enrolled with Role X in Org Unit Type Y -- or any user that's enrolled as a "Student" in a "Course Offering" for example.

- Because the tools available on a back-end service are definable client-to-client, and the org unit types and role types are definable client-to-client, the manifestation of what a particular client's permissions sets look like get really varied and really complex, really fast.

- The data about what role types are available, what org unit types are available, and particularly what role a user enrollment binds to, are often judged to be sensitive information by clients, and the ability to see that stuff is ALSO governed by permissions -- this means that your calling user context may not have any ability to, programmatically, "know or determine" what particular things it can and cannot do, other than just to try to do things and cope with potential failure. Administer type users can often see enrollment details that show role, and so can make some judgements, but, really, all they'll know is role type and then they have to "know" what that role type can actually do. (We're only just starting to programmatically expose views on the permissions sets out through the API, and it might not yet really have all the support there you'd need for effective permission investigation and processing at run-time: <http://docs.valence.desire2learn.com/res/permissions.html>.)


In your particular case, you probably need to know exactly what role your calling user context has in the context of the org unit you're trying to operate on. It's possible that your user context may need to be explicitly enrolled in the org unit (course), and not just enrolled via cascading enrollment. But, in any case, your user context needs to have permissions that allow the user's enrolled role to do the right stuff within org units of the appropriate type.

In nearly all cases, the permissions governing API functions and "through the web UI" equivalents are exactly the same; unfortunately, for one reason or another, in some small number of cases, they are not. Thus, while in most cases, it does hold true that "if you can do it in the Web UI, you can do it through the API if you make the API call as the same user", in a few cases, it may not, and the Grades functionality may well be one of those exceptions.

To do the kind of interactive role-permission testing outlined in the walkthrough really requires you to have direct access to a back-end LMS service, preferably a test one, so that you can use it with the org unit and role types expected by the production platform (or at least provide information that a production platform can map to), and go through the sticky parts in your client integration to find out exactly what role permissions are required of user contexts using your client application.

This is potentially quite laborious and frustrating, admittedly. However, on the whole, the general statement holds true -- types of users that can generally do things through the web UI can also do those things through the API, and designing with this principle in mind, and designing to cope gracefully with API call failure, are the right way to go.


I hope this helps. I admit that it's all fairly complex.

--
V.


Reply all
Reply to author
Forward
0 new messages