How can I batch Photo requests using BatchRequestContent in Microsoft.Graph? Calling the Photos endpoint for each staff member takes too long so I need to batch the requests together. I have successfully used batching for other requests but not for Photos Stream.
My code throws an exception when calling await batchResponse.GetResponseByIdAsync<Stream>(id.Value)
Exception: Error parsing comment. Expected: *, got 9. Path '', line 1, position 1.
Full code:
private async Task QueryStaffPhotos(GraphServiceClient client, IList<StaffMember> staffMembers)
{
BatchRequestContent content = new BatchRequestContent();
int count = 0, currentBatch = 0;
IDictionary<string, string> batchResponseIds = new Dictionary<string, string>();
int total = staffMembers.Count(c => c.HasPhoto);
foreach (StaffMember member in staffMembers.Where(c => c.HasPhoto).ToList())
{
IProfilePhotoContentRequest request = client.Users[member.ObjectID].Photos["96x96"].Content.Request();
batchResponseIds.Add(member.ObjectID, content.AddBatchRequestStep(request));
count++;
currentBatch++;
if (currentBatch >= MaxBatchCount || count == total) // Max 20 requests per batch
{
BatchResponseContent batchResponse = await client.Batch.Request().PostAsync(content);
foreach (KeyValuePair<string, string> id in batchResponseIds)
{
StaffMember temp = staffMembers.Single(c => c.ObjectID == id.Key);
temp.PhotoBase64 = "data:image/png;base64,";
using (Stream stream = await batchResponse.GetResponseByIdAsync<Stream>(id.Value))
{
int bytesRead;
byte[] buffer = new byte[3072]; // Base64 uses 4 ascii characters to encode 24-bits (3 bytes) of data
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
temp.PhotoBase64 += Convert.ToBase64String(buffer, 0, bytesRead);
}
}
}
content = new BatchRequestContent();
batchResponseIds.Clear();
currentBatch = 0;
}
}
}
Stack Trace:
at Newtonsoft.Json.JsonTextReader.ParseComment(Boolean setToken)
at Newtonsoft.Json.JsonTextReader.ParseValue()
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Microsoft.Graph.Serializer.DeserializeObject[T](String inputString)
at Microsoft.Graph.ResponseHandler.<HandleResponse>d__2`1.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Graph.BatchResponseContent.<GetResponseByIdAsync>d__9`1.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyApp.AppWeb.Controllers.StaffController.<QueryStaffPhotosBatchAsync>d__30.MoveNext() in C:\TFS\MyApp\MyApp.AppWeb\Controllers\StaffController.cs:line 259
Update 09-23-2020
There is an issue logged on github here for msgraph-sdk-dotnet-core to add support for non-json bodies in Batch content (thanks DCCoder).