/// <summary> /// Creates an <see cref="ODataBatchOperationRequestMessage"/> for writing an operation of a batch request. /// </summary> /// <param name="method">The Http method to be used for this request operation.</param> /// <param name="uri">The Uri to be used for this request operation.</param> /// <param name="contentId">The (optional) content ID to be included in this request operation.</param> /// <returns>The message that can be used to write the request operation.</returns> public ODataBatchOperationRequestMessage CreateOperationRequestMessage(HttpMethod method, Uri uri, string contentId) { this.ValidateWriterReady(); if (this.writingResponse) { this.ThrowODataException(Strings.ODataBatchWriter_CannotCreateRequestOperationWhenWritingResponse); } if (this.changeSetBoundary == null) { // only allow GET requests for query operations if (method != HttpMethod.Get) { this.ThrowODataException(Strings.ODataBatchWriter_InvalidHttpMethodForQueryOperation(method.ToText())); } // do not allow content-id for query operations if (contentId != null) { this.ThrowODataException(Strings.ODataBatchWriter_ContentIdNotSupportedForQueryOperations(contentId)); } this.InterceptException(this.IncreaseBatchSize); } else { // allow all methods except for GET if (method == HttpMethod.Get) { this.ThrowODataException(Strings.ODataBatchWriter_InvalidHttpMethodForChangeSetRequest(method.ToText())); } this.InterceptException(this.IncreaseChangeSetSize); } ExceptionUtils.CheckArgumentNotNull(uri, "uri"); this.InterceptException(() => uri = ODataBatchWriterUtils.BuildAbsoluteUri(uri, this.settings.BaseUri)); // write pending message data (headers, response line) for a previously unclosed message/request this.WritePendingMessageData(true); // create the new request operation this.CurrentOperationRequestMessage = new ODataBatchOperationRequestMessage(this.outputStream, method, uri, this); this.SetState(BatchWriterState.OperationCreated); // write the operation's start boundary string this.WriteStartBoundaryForOperation(); // write the headers, request line and (optional) Content-ID ODataBatchWriterUtils.WriteRequestPreamble(this.batchWriter, method, uri, contentId); return(this.CurrentOperationRequestMessage); }
/// <summary> /// Writes the start boundary for an operation. This is either the batch or the changeset boundary. /// </summary> private void WriteStartBoundaryForOperation() { if (this.changeSetBoundary == null) { ODataBatchWriterUtils.WriteStartBoundary(this.batchWriter, this.batchBoundary); this.batchStartBoundaryWritten = true; } else { ODataBatchWriterUtils.WriteStartBoundary(this.batchWriter, this.changeSetBoundary); } }
/// <summary> /// Ends an active changeset; this can only be called after WriteStartChangeset and only once for each changeset. /// </summary> public void WriteEndChangeset() { this.ValidateWriterReady(); // write pending message data (headers, response line) for a previously unclosed message/request this.WritePendingMessageData(true); // change the state first so we validate the change set boundary before attempting to write it. string currentChangeSetBoundary = this.changeSetBoundary; this.SetState(BatchWriterState.ChangeSetCompleted); // write the end boundary for the change set ODataBatchWriterUtils.WriteEndBoundary(this.batchWriter, currentChangeSetBoundary); }
/// <summary> /// Ends a batch; can only be called after WriteStartBatch has been called and if no other active changeset or operation exist. /// </summary> public void WriteEndBatch() { this.ValidateWriterReady(); // write the start boundary for the batch if not written if (!this.batchStartBoundaryWritten) { Debug.Assert(this.CurrentOperationMessage == null, "If not batch boundary was written we must not have an active message."); ODataBatchWriterUtils.WriteStartBoundary(this.batchWriter, this.batchBoundary); } // write pending message data (headers, response line) for a previously unclosed message/request this.WritePendingMessageData(true); this.SetState(BatchWriterState.BatchCompleted); // write the end boundary for the batch ODataBatchWriterUtils.WriteEndBoundary(this.batchWriter, this.batchBoundary); }
/// <summary> /// Creates an <see cref="ODataBatchOperationResponseMessage"/> for writing an operation of a batch response. /// </summary> /// <returns>The message that can be used to write the response operation.</returns> public ODataBatchOperationResponseMessage CreateOperationResponseMessage() { this.ValidateWriterReady(); if (!this.writingResponse) { this.ThrowODataException(Strings.ODataBatchWriter_CannotCreateResponseOperationWhenWritingRequest); } this.WritePendingMessageData(true); this.CurrentOperationResponseMessage = new ODataBatchOperationResponseMessage(this.outputStream, this); this.SetState(BatchWriterState.OperationCreated); // write the operation's start boundary string this.WriteStartBoundaryForOperation(); // write the headers, request line and (optional) Content-ID ODataBatchWriterUtils.WriteResponsePreamble(this.batchWriter); return(this.CurrentOperationResponseMessage); }
/// <summary> /// Starts a new changeset; can only be called after WriteStartBatch and if no other active operation or changeset exists. /// </summary> public void WriteStartChangeset() { this.ValidateWriterReady(); // write pending message data (headers, response line) for a previously unclosed message/request this.WritePendingMessageData(true); // important to do this first since it will set up the change set boundary. this.SetState(BatchWriterState.ChangeSetStarted); Debug.Assert(this.changeSetBoundary != null, "this.changeSetBoundary != null"); // reset the size of the current changeset and increase the size of the batch this.ResetChangeSetSize(); this.InterceptException(this.IncreaseBatchSize); // write the boundary string ODataBatchWriterUtils.WriteStartBoundary(this.batchWriter, this.batchBoundary); this.batchStartBoundaryWritten = true; // write the change set headers ODataBatchWriterUtils.WriteChangeSetPreamble(this.batchWriter, this.changeSetBoundary); }
/// <summary> /// Sets a new writer state; verifies that the transition from the current state into new state is valid. /// </summary> /// <param name="newState">The writer state to transition into.</param> private void SetState(BatchWriterState newState) { this.InterceptException(() => this.ValidateTransition(newState)); switch (newState) { case BatchWriterState.BatchStarted: Debug.Assert(!this.batchStartBoundaryWritten, "The batch boundary must not be written before calling WriteStartBatch."); break; case BatchWriterState.ChangeSetStarted: Debug.Assert(this.changeSetBoundary == null, "this.changeSetBoundary == null"); this.changeSetBoundary = ODataBatchWriterUtils.CreateChangeSetBoundary(this.writingResponse); break; case BatchWriterState.ChangeSetCompleted: Debug.Assert(this.changeSetBoundary != null, "this.changeSetBoundary != null"); this.changeSetBoundary = null; break; } this.state = newState; }