/// <summary> /// Puts payload in a batch request. /// </summary> /// <typeparam name="T">T must be a PayloadTestDescriptor.</typeparam> /// <param name="originalPayload">Payload to put into batch.</param> /// <param name="verb">HttpVerb associated with payload.</param> /// <param name="random">Use of random makes this method non deterministic.</param> /// <param name="requestManager">Used to construct requests.</param> /// <param name="operationsBefore">Number of operations/changesets to go before payload.</param> /// <param name="operationsAfter">Number of operations/changesets to go after payload.</param> /// <param name="version">Maximum version for extra payloads</param> /// <returns>The test descriptor for the new BatchRequestPayload</returns> public static T InBatchRequest <T>( this T originalPayload, HttpVerb verb, IRandomNumberGenerator random, IODataRequestManager requestManager, int operationsBefore = 0, int operationsAfter = 0, ODataVersion version = ODataVersion.V4 ) where T : PayloadTestDescriptor { ExceptionUtilities.CheckArgumentNotNull(originalPayload, "originalPayload"); ExceptionUtilities.CheckArgumentNotNull(verb, "verb"); ExceptionUtilities.CheckArgumentNotNull(random, "random"); ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager"); var payload = (T)originalPayload.Clone(); var baseUri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc"))); IMimePart[] extraOperations = BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version); // add extraChangesets methods extraOperations.Concat(BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version)); //Work out the operations and changesets to go before the payload var parts = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations)); if (verb != HttpVerb.Get) { extraOperations.ConcatSingle(payload.InRequestOperation(HttpVerb.Get, baseUri, requestManager)); } else { extraOperations.ConcatSingle(payload.InRequestChangeset(verb, random, requestManager, random.NextFromRange(0, 2), random.NextFromRange(0, 2), version)); } parts.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraOperations))); var batchRequest = new BatchRequestPayload(); foreach (var part in parts) { IHttpRequest operation = part as IHttpRequest; if (operation != null) { batchRequest.Add(operation.AsBatchFragment()); } BatchRequestChangeset changeset = part as BatchRequestChangeset; if (changeset != null) { batchRequest.Add(changeset); } } //payload.PayloadEdmModel.Fixup(); payload.PayloadElement = batchRequest; return(payload); }
/// <summary> /// Visits an ODataBatch. /// </summary> /// <param name="batch">The batch to visit.</param> protected override ODataPayloadElement VisitBatch(ODataBatch batch) { List <IMimePart> parts = new List <IMimePart>(); if (batch.Parts != null) { foreach (ODataBatchPart part in batch.Parts) { ODataBatchChangeset changeset = part as ODataBatchChangeset; if (changeset == null) { parts.Add(this.ConvertBatchOperation((ODataBatchOperation)part)); } else { List <IMimePart> changeSetOperations = new List <IMimePart>(); if (changeset.Operations != null) { foreach (ODataBatchOperation batchOperation in changeset.Operations) { changeSetOperations.Add(this.ConvertBatchOperation(batchOperation)); } } // TODO: the ODataBatchReader does not expose boundary strings or encodings; should it? if (this.response) { BatchResponseChangeset responseChangeset = BatchPayloadBuilder.ResponseChangeset(/*boundary*/ null, /*charset*/ null, changeSetOperations.ToArray()); parts.Add(responseChangeset); } else { BatchRequestChangeset requestChangeset = BatchPayloadBuilder.RequestChangeset(/*boundary*/ null, /*charset*/ null, changeSetOperations.ToArray()); parts.Add(requestChangeset); } } } } return(this.response ? (ODataPayloadElement)PayloadBuilder.BatchResponsePayload(parts.ToArray()) : (ODataPayloadElement)PayloadBuilder.BatchRequestPayload(parts.ToArray())); }
/// <summary> /// Compare aspects of batch request changeSets specific to request changeSets /// </summary> /// <param name="expectedBatchChangeset">Expected batch changeSet</param> /// <param name="actualBatchChangeset">Actual batch changeSet</param> private void CompareRequestChangeSets(BatchRequestChangeset expectedBatchChangeset, BatchRequestChangeset actualBatchChangeset) { ExceptionUtilities.CheckArgumentNotNull(actualBatchChangeset, "actualBatchChangeset"); ExceptionUtilities.CheckArgumentNotNull(expectedBatchChangeset, "expectedBatchChangeset"); this.Assert.IsNotNull(actualBatchChangeset.Operations, "actual Operations cannot be null"); this.Assert.IsNotNull(expectedBatchChangeset.Operations, "expected Operations cannot be null"); var actualOperations = actualBatchChangeset.Operations.ToList(); var expectedOperations = expectedBatchChangeset.Operations.ToList(); this.Assert.AreEqual(expectedOperations.Count, actualOperations.Count, "The number of expected and actual operations must match."); for (int i = 0; i < actualOperations.Count; i++) { var actualPart = actualOperations[i]; var expectedPart = expectedOperations[i]; this.CompareRequestParts(expectedPart, actualPart); } }
/// <summary> /// Deserializes the given request's binary payload into a batch payload /// </summary> /// <param name="request">The request to deserialize</param> /// <returns>The deserialized batch request payload</returns> public BatchRequestPayload DeserializeBatchRequest(HttpRequestData request) { var encoding = request.GetEncodingFromHeadersOrDefault(); MultipartMimeData <MimePartData <byte[]> > split; ExceptionUtilities.Assert(TrySplitMimePart(request, encoding, out split), "Failed to split batch response body"); var batchRequest = new BatchRequestPayload(); foreach (var subPart in split.ToList()) { MultipartMimeData <MimePartData <byte[]> > splitChangeset; if (TrySplitMimePart(subPart, encoding, out splitChangeset)) { var changeset = new BatchRequestChangeset(); changeset.Headers.AddRange(splitChangeset.Headers); foreach (var changesetPart in splitChangeset) { if (changesetPart.Body != null) { if (changesetPart.Body.Length > 0) { changeset.Add(this.BuildRequestFromPart(changesetPart, encoding)); } } } batchRequest.Add(changeset); } else { batchRequest.Add(this.BuildRequestFromPart(subPart, encoding)); } } return(batchRequest); }
/// <summary> /// Deserializes the given request's binary payload into a batch payload /// </summary> /// <param name="request">The request to deserialize</param> /// <returns>The deserialized batch request payload</returns> public BatchRequestPayload DeserializeBatchRequest(HttpRequestData request) { var encoding = request.GetEncodingFromHeadersOrDefault(); MultipartMimeData<MimePartData<byte[]>> split; ExceptionUtilities.Assert(TrySplitMimePart(request, encoding, out split), "Failed to split batch response body"); var batchRequest = new BatchRequestPayload(); foreach (var subPart in split.ToList()) { MultipartMimeData<MimePartData<byte[]>> splitChangeset; if (TrySplitMimePart(subPart, encoding, out splitChangeset)) { var changeset = new BatchRequestChangeset(); changeset.Headers.AddRange(splitChangeset.Headers); foreach (var changesetPart in splitChangeset) { if (changesetPart.Body != null) { if (changesetPart.Body.Length > 0) { changeset.Add(this.BuildRequestFromPart(changesetPart, encoding)); } } } batchRequest.Add(changeset); } else { batchRequest.Add(this.BuildRequestFromPart(subPart, encoding)); } } return batchRequest; }