private static async Task <SectionValues> GetV3SectionValuesAsync( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, SectionLookupKey lookupKey, short schoolYearFromRoute) { // Get the referenced section by natural key var response = await invoker.Get( typeof(V3Section), headers, new[] { new KeyValuePair <string, string>("localCourseCode", lookupKey.LocalCourseCode), new KeyValuePair <string, string>("schoolId", lookupKey.SchoolId.ToString()), new KeyValuePair <string, string>("schoolYear", lookupKey.SchoolYear.ToString()), new KeyValuePair <string, string>("sectionIdentifier", lookupKey.SectionIdentifier), new KeyValuePair <string, string>("sessionName", lookupKey.SessionName), }, schoolYearFromRoute) .ConfigureAwait(false); StreamReader sr = new StreamReader(response.ResponseStream); string responseContent = await sr.ReadToEndAsync().ConfigureAwait(false); if (response.Status == HttpStatusCode.OK) { // Get the Section-derived members var v3Section = JsonConvert.DeserializeObject <V3Section[]>(responseContent, _serializerSettings).SingleOrDefault(); if (v3Section == null) { throw new Exception($"Unable to find referenced Section using the following values: {JsonConvert.SerializeObject(lookupKey, Formatting.Indented)}"); } // Invasive defensive validation against "invalid" data for V2 if (lookupKey.SchoolId != v3Section.LocationReference.SchoolId) { throw new Exception($"Unable to convert the SectionReference from host (v3.1) to client (v2.5) because the LocationReference contains a School that differs from the containing Section, which is not supported under v2.5."); } // TODO: Validate presence of V2 required values, or ensure that V3 requires them (i.e. via required collections) var sectionValues = new SectionValues( classPeriodName: v3Section.SectionClassPeriods.FirstOrDefault()?.ClassPeriodReference.ClassPeriodName ?? "Undefined", classroomIdentificationCode: v3Section.LocationReference.ClassroomIdentificationCode ?? "Undefined", sectionIdentifier: v3Section.SectionIdentifier, sequenceOfCourse: v3Section.SequenceOfCourse ?? -1, retrievedDateTime: DateTime.Now); return(sectionValues); } throw new Exception($"Error obtaining V3 Section resource during mapping of V2 SectionReference: {response.Status} - {responseContent}"); }
private static async Task ApplyPropertiesFromV3SectionAsync( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, V3SectionReference source, V2SectionReference destination, short schoolYearFromRoute) { var sectionLookupKey = new SectionLookupKey(source.LocalCourseCode, source.SchoolId, source.SchoolYear, source.SectionIdentifier, source.SessionName); await Task.Run(() => { var values = _sectionValuesByNaturalKey.GetOrAdd(sectionLookupKey, k => GetV3SectionValuesAsync(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); // Are the retrieved values stale? if ((DateTime.Now - values.RetrievedDateTime).TotalSeconds > _cacheDurationSeconds.Value) { // Refresh the values SectionValues ignored; _sectionValuesByNaturalKey.TryRemove(sectionLookupKey, out ignored); values = _sectionValuesByNaturalKey.GetOrAdd(sectionLookupKey, k => GetV3SectionValuesAsync(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); } // Straight mappings from source destination.LocalCourseCode = source.LocalCourseCode; destination.SchoolId = source.SchoolId; destination.SchoolYear = source.SchoolYear; // Mappings from upstream host's Section destination.ClassPeriodName = values.ClassPeriodName; destination.ClassroomIdentificationCode = values.ClassroomIdentificationCode; destination.SequenceOfCourse = values.SequenceOfCourse; // NOTE: Assumes UniqueSectionCode is unique enough to use as the SectionIdentifier. destination.UniqueSectionCode = values.SectionIdentifier; }) .ConfigureAwait(false); }