()))
+ .ReturnsAsync(response);
+
+ var service = new CanvasService(mockRequestor.Object);
+ var canvasTerms = await service.GetTerms();
+
+ canvasTerms.Should().BeEquivalentTo(expectedTerms);
+
+ }
+
+}
\ No newline at end of file
diff --git a/Management.Web/Pages/FetchData.razor b/Management.Web/Pages/Testing.razor
similarity index 94%
rename from Management.Web/Pages/FetchData.razor
rename to Management.Web/Pages/Testing.razor
index 719c75a..4670cc9 100644
--- a/Management.Web/Pages/FetchData.razor
+++ b/Management.Web/Pages/Testing.razor
@@ -1,4 +1,4 @@
-@page "/fetchdata"
+@page "/testing"
@using Management.Web.Data
@inject WeatherForecastService ForecastService
diff --git a/Management.Web/Shared/NavMenu.razor b/Management.Web/Shared/NavMenu.razor
index e3a3158..a1a1412 100644
--- a/Management.Web/Shared/NavMenu.razor
+++ b/Management.Web/Shared/NavMenu.razor
@@ -20,8 +20,8 @@
-
- Fetch data
+
+ Testing Page
diff --git a/Management/Management.csproj b/Management/Management.csproj
index 4658cbf..b12872f 100644
--- a/Management/Management.csproj
+++ b/Management/Management.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/Management/Models/CanvasModel/Courses/CalendarLinkModel.cs b/Management/Models/CanvasModel/Courses/CalendarLinkModel.cs
index b3b0cc1..276412e 100644
--- a/Management/Models/CanvasModel/Courses/CalendarLinkModel.cs
+++ b/Management/Models/CanvasModel/Courses/CalendarLinkModel.cs
@@ -1,8 +1,5 @@
-
-
namespace CanvasModel.Courses;
-public struct CalendarLinkModel
-{
- [JsonPropertyName("ics")]
- public string Ics { get; set; }
-}
\ No newline at end of file
+public record CalendarLinkModel
+(
+ [property: JsonPropertyName("ics")] string Ics
+);
\ No newline at end of file
diff --git a/Management/Models/CanvasModel/Courses/TermModel.cs b/Management/Models/CanvasModel/Courses/TermModel.cs
index e39f7ff..2447ccb 100644
--- a/Management/Models/CanvasModel/Courses/TermModel.cs
+++ b/Management/Models/CanvasModel/Courses/TermModel.cs
@@ -1,17 +1,8 @@
-
namespace CanvasModel.Courses;
-public class TermModel
-{
-
- [JsonPropertyName("id")]
- public ulong Id { get; set; }
-
- [JsonPropertyName("name")]
- public string Name { get; set; }
-
- [JsonPropertyName("start_at")]
- public DateTime? StartAt { get; set; }
-
- [JsonPropertyName("end_at")]
- public DateTime? EndAt { get; set; }
-}
\ No newline at end of file
+public record TermModel
+(
+ [property: JsonPropertyName("id")] ulong Id,
+ [property: JsonPropertyName("name")] string Name,
+ [property: JsonPropertyName("start_at")] DateTime? StartAt,
+ [property: JsonPropertyName("end_at")] DateTime? EndAt
+);
diff --git a/Management/Models/CanvasModel/EnrollmentTerms/EnrollmentTermModel.cs b/Management/Models/CanvasModel/EnrollmentTerms/EnrollmentTermModel.cs
index 0a7e08d..2858bf7 100644
--- a/Management/Models/CanvasModel/EnrollmentTerms/EnrollmentTermModel.cs
+++ b/Management/Models/CanvasModel/EnrollmentTerms/EnrollmentTermModel.cs
@@ -1,43 +1,21 @@
-using System;
-using System.Collections.Generic;
-
-
namespace CanvasModel.EnrollmentTerms;
-public class EnrollmentTermModel
-{
- [JsonPropertyName("id")]
- public ulong Id { get; set; }
- [JsonPropertyName("sis_term_id")]
- public string SisTermId { get; set; }
+public record EnrollmentTermModel
+(
+ [property: JsonPropertyName("id")] ulong Id,
+ [property: JsonPropertyName("name")] string Name,
+ [property: JsonPropertyName("sis_term_id")] string? SisTermId = null,
+ [property: JsonPropertyName("sis_import_id")] ulong? SisImportId = null,
+ [property: JsonPropertyName("start_at")] DateTime? StartAt = null,
+ [property: JsonPropertyName("end_at")] DateTime? EndAt = null,
+ [property: JsonPropertyName("grading_period_group_id")] ulong? GradingPeriodGroupId = null,
+ [property: JsonPropertyName("workflow_state")] string? WorkflowState = null,
+ [property: JsonPropertyName("overrides")]
+ Dictionary? Overrides = null
+);
- [JsonPropertyName("sis_import_id")]
- public ulong? SisImportId { get; set; }
-
- [JsonPropertyName("name")]
- public string Name { get; set; }
-
- [JsonPropertyName("start_at")]
- public DateTime? StartAt { get; set; }
-
- [JsonPropertyName("end_at")]
- public DateTime? EndAt { get; set; }
-
- [JsonPropertyName("grading_period_group_id")]
- public ulong? GradingPeriodGroupId { get; set; }
-
- [JsonPropertyName("workflow_state")]
- public string WorkflowState { get; set; }
-
- [JsonPropertyName("overrides")]
- public Dictionary Overrides { get; set; }
-}
-
-public struct EnrollmentTermDateOverrideModel
-{
- [JsonPropertyName("start_at")]
- public DateTime? StartAt { get; set; }
-
- [JsonPropertyName("end_at")]
- public DateTime? EndAt { get; set; }
-}
+public record EnrollmentTermDateOverrideModel
+(
+ [property: JsonPropertyName("start_at")] DateTime? StartAt = null,
+ [property: JsonPropertyName("end_at")] DateTime? EndAt = null
+);
diff --git a/Management/Models/CanvasModel/EnrollmentTerms/RedundantEnrollmentTermsResponse.cs b/Management/Models/CanvasModel/EnrollmentTerms/RedundantEnrollmentTermsResponse.cs
index 9261307..1178ea4 100644
--- a/Management/Models/CanvasModel/EnrollmentTerms/RedundantEnrollmentTermsResponse.cs
+++ b/Management/Models/CanvasModel/EnrollmentTerms/RedundantEnrollmentTermsResponse.cs
@@ -1,9 +1,7 @@
-using System.Collections.Generic;
-
namespace CanvasModel.EnrollmentTerms;
-public struct RedundantEnrollmentTermsResponse
-{
- [JsonPropertyName("enrollment_terms")]
- public IEnumerable EnrollmentTerms { get; set; }
-}
+public record RedundantEnrollmentTermsResponse
+(
+ [property: JsonPropertyName("enrollment_terms")]
+ IEnumerable EnrollmentTerms
+);
diff --git a/Management/Services/CanvasService.cs b/Management/Services/CanvasService.cs
index 639c842..85390f7 100644
--- a/Management/Services/CanvasService.cs
+++ b/Management/Services/CanvasService.cs
@@ -1,4 +1,68 @@
+using CanvasModel.Courses;
+using CanvasModel.EnrollmentTerms;
+using RestSharp;
public class CanvasService
{
-
+ private const string BaseUrl = "https://snow.instructure.com/api/v1/";
+ private readonly IWebRequestor webRequestor;
+ private RestClient client;
+ private string courseid { get; }
+ public CanvasService(IWebRequestor webRequestor)
+ {
+ courseid = "774898";
+ this.webRequestor = webRequestor;
+ }
+
+ public async Task> GetTerms()
+ {
+ var url = $"accounts/10/terms";
+
+ var request = new RestRequest(url);
+ var terms = await PaginatedRequest(request);
+ return terms;
+ }
+
+ private async Task> PaginatedRequest(RestRequest request)
+ {
+ var requestCount = 1;
+ request.AddQueryParameter("per_page", "100");
+ IEnumerable returnData = new T[] { };
+ RestResponse response = await webRequestor.GetAsync(request);
+ returnData = returnData.Concat(response.Data);
+
+ var nextUrl = getNextUrl(response);
+
+ while (nextUrl is not null)
+ {
+ requestCount += 1;
+ var nextRequest = new RestRequest(nextUrl);
+ var nextResponse = await webRequestor.GetAsync(nextRequest);
+ if (nextResponse.Data is not null)
+ returnData = returnData.Concat(nextResponse.Data);
+ nextUrl = getNextUrl(nextResponse);
+ }
+
+ System.Console.WriteLine($"Requesting {typeof(T)} took {requestCount} requests");
+
+ return returnData;
+ }
+
+
+ private static string? getNextUrl(RestResponse response) => response.Headers?
+ .ToList()
+ .Find(h => h.Name == "Link")?
+ .Value?
+ .ToString()?
+ .Split(",")
+ .Where(url => url.Contains("rel=\"next\""))
+ .FirstOrDefault()?
+ .Split(";")
+ .FirstOrDefault()?
+ .TrimEnd('>')
+ .TrimStart('<')
+ .Replace(" ", "")
+ .Replace(BaseUrl, "");
+
+
+
}
\ No newline at end of file
diff --git a/Management/Services/IWebRequestor.cs b/Management/Services/IWebRequestor.cs
new file mode 100644
index 0000000..cda00d0
--- /dev/null
+++ b/Management/Services/IWebRequestor.cs
@@ -0,0 +1,7 @@
+using RestSharp;
+
+public interface IWebRequestor
+{
+ Task> GetManyAsync(RestRequest request);
+ Task> GetAsync(RestRequest request);
+}
diff --git a/Management/Services/WebRequestor.cs b/Management/Services/WebRequestor.cs
new file mode 100644
index 0000000..2a2ea56
--- /dev/null
+++ b/Management/Services/WebRequestor.cs
@@ -0,0 +1,26 @@
+using RestSharp;
+
+public class WebRequestor : IWebRequestor
+{
+ private const string BaseUrl = "https://snow.instructure.com/api/v1/";
+ private string token;
+ private RestClient client;
+ private string courseid { get; }
+ public WebRequestor(RestClient client)
+ {
+ // token = Environment.GetEnvironmentVariable("CANVAS_TOKEN");
+ // client = new RestClient(BaseUrl);
+ // client.AddDefaultHeader("Authorization", $"Bearer {token}");
+
+ this.client = client;
+ courseid = "774898";
+ }
+ public async Task> GetManyAsync(RestRequest request)
+ {
+ return await client.ExecuteGetAsync(request);
+ }
+ public async Task> GetAsync(RestRequest request)
+ {
+ return await client.ExecuteGetAsync(request);
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 66864b3..192ac61 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,6 @@
install specflow template `dotnet new install Specflow.Templates.DotNet`
-view templates with `dotnet new -l`
\ No newline at end of file
+view templates with `dotnet new -l`
+
+find outdated packages `dotnet list package --outdated`
\ No newline at end of file
diff --git a/requests/semester.http b/requests/semester.http
new file mode 100644
index 0000000..0b041cb
--- /dev/null
+++ b/requests/semester.http
@@ -0,0 +1,9 @@
+
+###
+GET https://snow.instructure.com/api/v1/account_calendars
+Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
+
+###
+GET https://snow.instructure.com/api/v1/accounts/10/terms
+Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
+