// ------------------------------------------------------------------------------
// 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);
}
}
}
}