// ------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ namespace Microsoft.Graph { using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; /// /// Handles batch request responses. /// public class BatchResponseContent { private JObject jBatchResponseObject; private HttpResponseMessage batchResponseMessage; /// /// Gets a serializer for serializing and deserializing JSON objects. /// public ISerializer Serializer { get; private set; } /// /// Constructs a new /// /// A of a batch request execution. /// A serializer for serializing and deserializing JSON objects. public BatchResponseContent(HttpResponseMessage httpResponseMessage, ISerializer serializer = null) { this.batchResponseMessage = httpResponseMessage ?? throw new ClientException(new Error { Code = ErrorConstants.Codes.InvalidArgument, Message = string.Format(ErrorConstants.Messages.NullParameter, nameof(httpResponseMessage)) }); this.Serializer = serializer ?? new Serializer(); } /// /// Gets all batch responses . /// All in the dictionary MUST be disposed since they implement . /// /// A Dictionary of id and representing batch responses. public async Task> GetResponsesAsync() { Dictionary responseMessages = new Dictionary(); jBatchResponseObject = jBatchResponseObject ?? await GetBatchResponseContentAsync(); if (jBatchResponseObject == null) return responseMessages; if(jBatchResponseObject.TryGetValue(CoreConstants.BatchRequest.Responses, out JToken jResponses)) { foreach (JObject jResponseItem in jResponses) responseMessages.Add(jResponseItem.GetValue(CoreConstants.BatchRequest.Id).ToString(), GetResponseMessageFromJObject(jResponseItem)); } return responseMessages; } /// /// Gets a batch response as for the specified batch request id. /// The returned MUST be disposed since it implements an . /// /// A batch request id. /// A response object for a batch request. public async Task GetResponseByIdAsync(string requestId) { jBatchResponseObject = jBatchResponseObject ?? await GetBatchResponseContentAsync(); if (jBatchResponseObject == null) return null; JObject jResponseItem = null; if (jBatchResponseObject.TryGetValue(CoreConstants.BatchRequest.Responses, out JToken jResponses)) { jResponseItem = jResponses.FirstOrDefault((jtoken) => jtoken.Value(CoreConstants.BatchRequest.Id).Equals(requestId)) as JObject; } return GetResponseMessageFromJObject(jResponseItem); } /// /// Gets a batch response as a requested type for the specified batch request id. /// /// A batch request id. /// A deserialized object of type T. public async Task GetResponseByIdAsync(string requestId) { using (var httpResponseMessage = await GetResponseByIdAsync(requestId)) { var responseHandler = new ResponseHandler(new Serializer()); if (!httpResponseMessage.IsSuccessStatusCode) { Error error; string rawResponseBody = null; //deserialize into an ErrorResponse as the result is not a success. ErrorResponse errorResponse = await responseHandler.HandleResponse(httpResponseMessage); if (errorResponse?.Error == null) { if (httpResponseMessage.StatusCode == HttpStatusCode.NotFound) { error = new Error { Code = ErrorConstants.Codes.ItemNotFound }; } else { error = new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Messages.UnexpectedExceptionResponse }; } } else { error = errorResponse.Error; } if (httpResponseMessage.Content?.Headers.ContentType.MediaType == "application/json") { rawResponseBody = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); } throw new ServiceException(error, httpResponseMessage.Headers, httpResponseMessage.StatusCode, rawResponseBody); } // return the deserialized object return await responseHandler.HandleResponse(httpResponseMessage); } } /// /// Gets the @NextLink of a batch response. /// /// public async Task GetNextLinkAsync() { jBatchResponseObject = jBatchResponseObject ?? await GetBatchResponseContentAsync(); if (jBatchResponseObject == null) return null; return jBatchResponseObject.GetValue(CoreConstants.Serialization.ODataNextLink)?.ToString(); } /// /// Gets a from representing a batch response item. /// /// A single batch response item of type . /// A single batch response as a . private HttpResponseMessage GetResponseMessageFromJObject(JObject jResponseItem) { if (jResponseItem == null) return null; HttpResponseMessage responseMessage = new HttpResponseMessage(); if (jResponseItem.TryGetValue(CoreConstants.BatchRequest.Status, out JToken status)) { responseMessage.StatusCode = (HttpStatusCode)int.Parse(status.ToString()); } if (jResponseItem.TryGetValue(CoreConstants.BatchRequest.Body, out JToken body)) { responseMessage.Content = new StringContent(body.ToString(), Encoding.UTF8, CoreConstants.MimeTypeNames.Application.Json); } if (jResponseItem.TryGetValue(CoreConstants.BatchRequest.Headers, out JToken headers)) { foreach (KeyValuePair headerKeyValue in headers.ToObject>()) { responseMessage.Headers.TryAddWithoutValidation(headerKeyValue.Key, headerKeyValue.Value); } } return responseMessage; } /// /// Gets the of a batch response as . /// /// A batch response content as . private async Task GetBatchResponseContentAsync() { if (this.batchResponseMessage.Content == null) return null; try { using (Stream streamContent = await this.batchResponseMessage.Content.ReadAsStreamAsync()) { return Serializer.DeserializeObject(streamContent); } } catch (Exception ex) { throw new ClientException(new Error { Code = ErrorConstants.Codes.InvalidRequest, Message = ErrorConstants.Messages.UnableToDeserializexContent }, ex); } } } }