cancel
Showing results for 
Search instead for 
Did you mean: 
featherstonej
Community Participant

Rest API C#, RestSharp, and Newtonsoft Enrollments

I am trying to use the API using C#, RestSharp, and Newtonsoft. I am trying to GET enrollments by Section Id. I have created classes to handle the JSON that is returned, but I am getting errors. The classes are listed below.

[JsonObject]
public class Grades
{
public string html_url { get; set; }
public object current_grade { get; set; }
public object current_score { get; set; }
public object final_grade { get; set; }
public double final_score { get; set; }
public object unposted_current_score { get; set; }
public object unposted_current_grade { get; set; }
public double unposted_final_score { get; set; }
public object unposted_final_grade { get; set; }
}
[JsonObject]
public class User
{
public int id { get; set; }
public string name { get; set; }
public DateTime created_at { get; set; }
public string sortable_name { get; set; }
public string short_name { get; set; }
public object sis_user_id { get; set; }
public object integration_id { get; set; }
public object sis_import_id { get; set; }
public string login_id { get; set; }
}
[JsonObject]
public class Enrollment
{
public int id { get; set; }
public int user_id { get; set; }
public int course_id { get; set; }
public string type { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
public object associated_user_id { get; set; }
public object start_at { get; set; }
public object end_at { get; set; }
public int course_section_id { get; set; }
public int root_account_id { get; set; }
public bool limit_privileges_to_course_section { get; set; }
public string enrollment_state { get; set; }
public string role { get; set; }
public int role_id { get; set; }
public object last_activity_at { get; set; }
public object last_attended_at { get; set; }
public int total_activity_time { get; set; }
public object sis_import_id { get; set; }
public Grades grades { get; set; }
public string sis_account_id { get; set; }
public string sis_course_id { get; set; }
public object course_integration_id { get; set; }
public string sis_section_id { get; set; }
public object section_integration_id { get; set; }
public object sis_user_id { get; set; }
public string html_url { get; set; }
public User user { get; set; }
}

public class RootObject
{
public List<Enrollment> enrollList { get; set; }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Below is the the function that is called to get the list of enrollments.

public RootObject getListSectionEnrollments(string baseUrl, string section_id, string authToken, string[] type = null, string[] role = null, string[] state = null )
{
type = type ?? new string[] { "StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "DesignerEnrollment", "ObserverEnrollment" };
role = role ?? new string[] { "StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "DesignerEnrollment", "ObserverEnrollment" };
state = state ?? new string[] { "active", "invited" };

string apiCall = "/api/v1/sections/:section_id/enrollments".Replace(":section_id", section_id);
string url = baseUrl + apiCall;
var client = new RestClient(url);

var request = new RestRequest(Method.GET);

request.AddHeader("Authorization", "Bearer " + authToken);
request.AddParameter("type[]", type);
request.AddParameter("role[]", role);
request.AddParameter("state[]", state);

request.RequestFormat = DataFormat.Json;
var response = client.Execute(request);

RootObject myObject = JsonConvert.DeserializeObject<RootObject>(response.Content);
return myObject;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

All the above code is in a public class called Enrollments. Which is then built into a dll that I use in my C# programs. The program calls the function like this. The second line is meant as a test to ensure that there is something in the enrollments object.

Enrollments.RootObject enrollments = en.getListSectionEnrollments(ConStrings.canvasLiveBaseUrl, canvas_id, ConStrings.canvasProdToken, new string[] { "StudentEnrollment"});   
MessageBox.Show(enrollments.enrollList.Count.ToString()); ‍‍‍‍‍‍‍‍‍‍‍‍‍

The second line above causes the below error.

Object reference not set to an instance of an object.System.NullReferenceException: Object reference not set to an instance of an object.
Labels (1)
Tags (1)
0 Kudos
2 Replies
featherstonej
Community Participant

So, I have figured it out with the help of json2csharp - generate c# classes from json. I pasted the results from a Postman call into this site and clicked the Generate with Quicktype and got the following Class.

namespace Serialize_Enrollments
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public partial class Enrollment
{
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public long? Id { get; set; }
[JsonProperty("user_id", NullValueHandling = NullValueHandling.Ignore)]
public long? UserId { get; set; }
[JsonProperty("course_id", NullValueHandling = NullValueHandling.Ignore)]
public long? CourseId { get; set; }
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
public string Type { get; set; }
[JsonProperty("created_at", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? CreatedAt { get; set; }
[JsonProperty("updated_at", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? UpdatedAt { get; set; }
[JsonProperty("associated_user_id")]
public object AssociatedUserId { get; set; }
[JsonProperty("start_at")]
public object StartAt { get; set; }
[JsonProperty("end_at")]
public object EndAt { get; set; }
[JsonProperty("course_section_id", NullValueHandling = NullValueHandling.Ignore)]
public long? CourseSectionId { get; set; }
[JsonProperty("root_account_id", NullValueHandling = NullValueHandling.Ignore)]
public long? RootAccountId { get; set; }
[JsonProperty("limit_privileges_to_course_section", NullValueHandling = NullValueHandling.Ignore)]
public bool? LimitPrivilegesToCourseSection { get; set; }
[JsonProperty("enrollment_state", NullValueHandling = NullValueHandling.Ignore)]
public string EnrollmentState { get; set; }
[JsonProperty("role", NullValueHandling = NullValueHandling.Ignore)]
public string Role { get; set; }
[JsonProperty("role_id", NullValueHandling = NullValueHandling.Ignore)]
public long? RoleId { get; set; }
[JsonProperty("last_activity_at", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? LastActivityAt { get; set; }
[JsonProperty("last_attended_at")]
public object LastAttendedAt { get; set; }
[JsonProperty("total_activity_time", NullValueHandling = NullValueHandling.Ignore)]
public long? TotalActivityTime { get; set; }
[JsonProperty("sis_import_id", NullValueHandling = NullValueHandling.Ignore)]
public long? SisImportId { get; set; }
[JsonProperty("grades", NullValueHandling = NullValueHandling.Ignore)]
public Grades Grades { get; set; }
[JsonProperty("sis_account_id", NullValueHandling = NullValueHandling.Ignore)]
public string SisAccountId { get; set; }
[JsonProperty("sis_course_id", NullValueHandling = NullValueHandling.Ignore)]
public string SisCourseId { get; set; }
[JsonProperty("course_integration_id")]
public object CourseIntegrationId { get; set; }
[JsonProperty("sis_section_id", NullValueHandling = NullValueHandling.Ignore)]
public string SisSectionId { get; set; }
[JsonProperty("section_integration_id")]
public object SectionIntegrationId { get; set; }
[JsonProperty("sis_user_id", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(ParseStringConverter))]
public long? SisUserId { get; set; }
[JsonProperty("html_url", NullValueHandling = NullValueHandling.Ignore)]
public Uri HtmlUrl { get; set; }
[JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)]
public User User { get; set; }
}
public partial class Grades
{
[JsonProperty("html_url", NullValueHandling = NullValueHandling.Ignore)]
public Uri HtmlUrl { get; set; }
[JsonProperty("current_grade")]
public object CurrentGrade { get; set; }
[JsonProperty("current_score")]
public object CurrentScore { get; set; }
[JsonProperty("final_grade")]
public object FinalGrade { get; set; }
[JsonProperty("final_score")]
public object FinalScore { get; set; }
[JsonProperty("unposted_current_score")]
public object UnpostedCurrentScore { get; set; }
[JsonProperty("unposted_current_grade")]
public object UnpostedCurrentGrade { get; set; }
[JsonProperty("unposted_final_score")]
public object UnpostedFinalScore { get; set; }
[JsonProperty("unposted_final_grade")]
public object UnpostedFinalGrade { get; set; }
}
public partial class User
{
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public long? Id { get; set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("created_at", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? CreatedAt { get; set; }
[JsonProperty("sortable_name", NullValueHandling = NullValueHandling.Ignore)]
public string SortableName { get; set; }
[JsonProperty("short_name", NullValueHandling = NullValueHandling.Ignore)]
public string ShortName { get; set; }
[JsonProperty("sis_user_id", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(ParseStringConverter))]
public long? SisUserId { get; set; }
[JsonProperty("integration_id")]
public object IntegrationId { get; set; }
[JsonProperty("sis_import_id", NullValueHandling = NullValueHandling.Ignore)]
public long? SisImportId { get; set; }
[JsonProperty("login_id", NullValueHandling = NullValueHandling.Ignore)]
public string LoginId { get; set; }
}
public partial class Enrollment
{
public static List<Enrollment> FromJson(string json) => JsonConvert.DeserializeObject<List<Enrollment>>(json, Serialize_Enrollments.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this List<Enrollment> self) => JsonConvert.SerializeObject(self, Serialize_Enrollments.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
internal class ParseStringConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var value = serializer.Deserialize<string>(reader);
long l;
if (Int64.TryParse(value, out l))
{
return l;
}
throw new Exception("Cannot unmarshal type long");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
var value = (long)untypedValue;
serializer.Serialize(writer, value.ToString());
return;
}
public static readonly ParseStringConverter Singleton = new ParseStringConverter();
}
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Then I changed my function to look like this. I had to comment out the optional parameters because they were giving me an error. I will have to test them more in Postman to see what I was doing wrong.

public List<Enrollment> getListSectionEnrollments(string baseUrl, string section_id, int enrolledCount, string authToken/*, out string errorStr, string[] type = null, string[] role = null, string[] state = null */)
{
//type = type ?? new string[] { "StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "DesignerEnrollment", "ObserverEnrollment" };
//role = role ?? new string[] { "StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "DesignerEnrollment", "ObserverEnrollment" };
//state = state ?? new string[] { "active", "invited" };

string apiCall = "/api/v1/sections/:section_id/enrollments".Replace(":section_id", section_id);
string url = baseUrl + apiCall;
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + authToken);
//request.AddParameter("type[]", type);
//request.AddParameter("role[]", role);
//request.AddParameter("state[]", state);
request.RequestFormat = DataFormat.Json;

var response = client.Execute(request);

List<Enrollment> enrollments = Enrollment.FromJson(response.Content);
return enrollments;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

With that in my dll I was able to then use the following code to retrieve the results.

List<Enrollment> enrollments = en.getListSectionEnrollments(ConStrings.canvasLiveBaseUrl, canvas_id, enrolledCount, ConStrings.canvasProdToken/*, out errString, new string[] { "StudentEnrollment"}*/);
foreach(Enrollment enr in enrollments)
{
updateCanvasEnrollmentId(enr.SisSectionId, enr.SisUserId.ToString(), enr.Id.ToString());
}‍‍‍‍‍‍‍‍‍‍‍

With that all working I ran into another issue. Canvas returns a paginated result and I am not sure how to get the next page(s). I did notice each page has 10 students, is there a way to increase that? 

 @featherstonej 

Been following your thread today.

Thanks for coming back and updating the code and examples, it really helps.

I don't know anything about C#, but this might help...

Handling Pagination in C# > https://community.canvaslms.com/message/3587#comment-115040