/// <summary> /// Constructs an OData request body using the given settings /// </summary> /// <param name="contentType">The content type of the body</param> /// <param name="uri">The request uri</param> /// <param name="rootElement">The root payload element</param> /// <returns>An OData request body</returns> public ODataPayloadBody BuildBody(string contentType, ODataUri uri, ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType"); ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckAllRequiredDependencies(this); string charset = HttpUtilities.GetContentTypeCharsetOrNull(contentType); byte[] serializedBody = null; var batchRequestPayload = rootElement as BatchRequestPayload; if (batchRequestPayload != null) { string boundary; ExceptionUtilities.Assert(HttpUtilities.TryGetContentTypeParameter(contentType, HttpHeaders.Boundary, out boundary), "Could not find boundary in content type for batch payload. Content type was: '{0}'", contentType); serializedBody = this.BatchSerializer.SerializeBatchPayload(batchRequestPayload, boundary, charset); } else { IProtocolFormatStrategy strategy = this.FormatSelector.GetStrategy(contentType, uri); ExceptionUtilities.CheckObjectNotNull(strategy, "Strategy selector did not return a strategy for content type '{0}'", contentType); IPayloadSerializer serializer = strategy.GetSerializer(); ExceptionUtilities.CheckObjectNotNull(serializer, "Strategy returned a null serializer"); serializedBody = serializer.SerializeToBinary(rootElement, charset); } return(new ODataPayloadBody(serializedBody, rootElement)); }
/// <summary> /// Generates the raw test message with mixed encodings defined by the test case, as well as the expected ODataPayloadElement. /// </summary> /// <param name="testCase">The test case defining the structure and encodings of the batch payload.</param> /// <param name="payload">The payload to use for all generated batch operations.</param> /// <param name="payloadUri">The URI to use for all generated batch operations.</param> /// <param name="isRequest">If true, generates a batch request, otherwise a batch response.</param> /// <returns>The test descriptor for this test case/configuration.</returns> private BatchReaderMixedEncodingTestDescriptor CreateTestDescriptor(BatchReaderMixedEncodingTestCase testCase, ODataPayloadElement payload, ODataUri payloadUri, bool isRequest) { ExceptionUtilities.Assert(testCase.BatchEncoding != null, "Batch encoding has not been specified."); string batchBoundary = "batch_" + Guid.NewGuid().ToString(); string payloadUriString = this.UriConverter.ConvertToString(payloadUri); var batchPayload = isRequest ? (ODataPayloadElement) new BatchRequestPayload() : (ODataPayloadElement) new BatchResponsePayload(); batchPayload.AddAnnotation(new BatchBoundaryAnnotation(batchBoundary)); var rawMessage = new List <byte>(); // TODO: Batch reader does not support multi codepoint encodings Encoding unsupportedEncoding = AsUnsupportedEncoding(testCase.BatchEncoding); foreach (var changeset in testCase.Changesets) { string changesetBoundary = "change_" + Guid.NewGuid().ToString(); Encoding changesetEncoding = changeset.ChangesetEncoding ?? testCase.BatchEncoding; // TODO: Batch reader does not support multi codepoint encodings unsupportedEncoding = unsupportedEncoding ?? AsUnsupportedEncoding(changesetEncoding); string changesetContentType = HttpUtilities.BuildContentType( MimeTypes.MultipartMixed, changeset.ChangesetEncoding == null ? string.Empty : changeset.ChangesetEncoding.WebName, changesetBoundary); rawMessage.AddRange( WriteMessagePart( testCase.BatchEncoding, (writer) => { writer.Write("--"); writer.WriteLine(batchBoundary); writer.WriteLine(HttpHeaders.ContentType + ": " + changesetContentType); writer.WriteLine(); })); var mimeParts = new List <IMimePart>(); int contentId = 0; foreach (var operation in changeset.Operations) { ExceptionUtilities.Assert(operation.PayloadFormat == ODataFormat.Atom || operation.PayloadFormat == ODataFormat.Json, "Payload format must be ATOM or JSON."); string formatType = MimeTypes.ApplicationAtomXml + ";type=entry"; Encoding payloadEncoding = operation.OperationEncoding ?? changesetEncoding; string payloadContentType = HttpUtilities.BuildContentType( formatType, operation.OperationEncoding == null ? string.Empty : operation.OperationEncoding.WebName, string.Empty); string httpStatus = isRequest ? "POST " + payloadUriString + " HTTP/1.1" : "HTTP/1.1 201 Created"; rawMessage.AddRange( WriteMessagePart( changesetEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.WriteLine(changesetBoundary); writer.WriteLine(HttpHeaders.ContentType + ": application/http"); writer.WriteLine(HttpHeaders.ContentTransferEncoding + ": binary"); writer.WriteLine(HttpHeaders.ContentId + ": " + (++contentId).ToString()); writer.WriteLine(); writer.WriteLine(httpStatus); writer.WriteLine(HttpHeaders.ContentType + ": " + payloadContentType); writer.WriteLine(); })); IPayloadSerializer payloadSerializer = operation.PayloadFormat == ODataFormat.Atom ? (IPayloadSerializer) new XmlPayloadSerializer(this.PayloadElementToXmlConverter) : (IPayloadSerializer) new JsonPayloadSerializer(this.PayloadElementToJsonConverter.ConvertToJson); byte[] payloadBytes = payloadSerializer.SerializeToBinary(payload, payloadEncoding.WebName); rawMessage.AddRange(payloadBytes.Skip(payloadEncoding.GetPreamble().Length)); if (isRequest) { var request = this.RequestManager.BuildRequest(payloadUri, HttpVerb.Post, new Dictionary <string, string> { { HttpHeaders.ContentType, payloadContentType } }); request.Body = new ODataPayloadBody(payloadBytes, payload); mimeParts.Add(request); } else { var httpResponseData = new HttpResponseData { StatusCode = HttpStatusCode.Created, }; httpResponseData.Headers.Add(HttpHeaders.ContentType, payloadContentType); var response = new ODataResponse(httpResponseData) { Body = payloadBytes, RootElement = payload }; mimeParts.Add(response); } } rawMessage.AddRange( WriteMessagePart( changesetEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.Write(changesetBoundary); writer.WriteLine("--"); })); if (isRequest) { ((BatchRequestPayload)batchPayload).Add(BatchPayloadBuilder.RequestChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray())); } else { ((BatchResponsePayload)batchPayload).Add(BatchPayloadBuilder.ResponseChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray())); } } rawMessage.AddRange( WriteMessagePart( testCase.BatchEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.Write(batchBoundary); writer.WriteLine("--"); })); return(new BatchReaderMixedEncodingTestDescriptor(this.PayloadReaderSettings) { BatchContentTypeHeader = HttpUtilities.BuildContentType(MimeTypes.MultipartMixed, testCase.BatchEncoding.WebName, batchBoundary), RawMessage = rawMessage.ToArray(), PayloadElement = batchPayload, ExpectedException = unsupportedEncoding == null ? null : ODataExpectedExceptions.ODataException("ODataBatchReaderStream_MultiByteEncodingsNotSupported", unsupportedEncoding.WebName) }); }
/// <summary> /// Serializes the given payload element into a form ready to be sent over HTTP using the default encoding. /// </summary> /// <param name="serializer">The serializer to extend</param> /// <param name="rootElement">The root payload element to serialize</param> /// <returns>The binary representation of the payload for this format, ready to be sent over HTTP</returns> public static byte[] SerializeToBinary(this IPayloadSerializer serializer, ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(serializer, "serializer"); return(serializer.SerializeToBinary(rootElement, null)); }