/// <summary>Asynchronously returns an <see cref="T:Microsoft.OData.ODataBatchOperationResponseMessage" /> for reading the content of a batch operation.</summary> /// <returns>A task that when completed returns a response message for reading the content of a batch operation.</returns> public Task <ODataBatchOperationResponseMessage> CreateOperationResponseMessageAsync() { this.VerifyCanCreateOperationResponseMessage(/*synchronousCall*/ false); return(TaskUtils.GetTaskForSynchronousOperation <ODataBatchOperationResponseMessage>( this.CreateOperationResponseMessageImplementation) .FollowOnFaultWith(t => this.State = ODataBatchReaderState.Exception)); }
/// <summary> /// Verify the json array of the batch payload. /// </summary> /// <returns>The batch reader's Operation state.</returns> private ODataBatchReaderState StartReadingBatchArray() { this.batchStream.JsonReader.ReadStartArray(); ODataBatchReaderState nextState = ODataBatchReaderState.Operation; return(nextState); }
/// <summary> /// Asynchronously verify the JSON array of the batch payload. /// </summary> /// <returns> /// A task that represents the asynchronous read operation. /// The value of the TResult parameter contains the batch reader's Operation state. /// </returns> private async Task <ODataBatchReaderState> StartReadingBatchArrayAsync() { await this.batchStream.JsonReader.ReadStartArrayAsync() .ConfigureAwait(false); ODataBatchReaderState nextState = ODataBatchReaderState.Operation; return(nextState); }
/// <summary> /// Catch any exception thrown by the action passed in; in the exception case move the writer into /// state Exception and then rethrow the exception. /// </summary> /// <typeparam name="T">The type of the result returned from the <paramref name="action"/>.</typeparam> /// <param name="action">The action to execute.</param> /// <returns>The result of the <paramref name="action"/>.</returns> private T InterceptException <T>(Func <T> action) { try { return(action()); } catch (Exception e) { if (ExceptionUtils.IsCatchableExceptionType(e)) { this.State = ODataBatchReaderState.Exception; } throw; } }
private bool ReadImplementation() { switch (this.State) { case ODataBatchReaderState.Initial: this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Operation: if (this.operationState == OperationState.None) { throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation); } this.operationState = OperationState.None; if (this.contentIdToAddOnNextRead != null) { this.urlResolver.AddContentId(this.contentIdToAddOnNextRead); this.contentIdToAddOnNextRead = null; } this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetStart: this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetEnd: this.ResetChangeSetSize(); this.batchStream.ResetChangeSetBoundary(); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Completed: case ODataBatchReaderState.Exception: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); } return((this.batchReaderState != ODataBatchReaderState.Completed) && (this.batchReaderState != ODataBatchReaderState.Exception)); }
/// <summary> /// Examine changeset states for the current message and setup reader state accordingly if /// changeset related state transition is detected. /// </summary> /// <param name="messagePropertiesCache">Current message properties.</param> /// <returns>The next state for the reader.</returns> private ODataBatchReaderState DetectChangesetStates(ODataJsonLightBatchPayloadItemPropertiesCache messagePropertiesCache) { // Validate message Id. string valueId = (string)messagePropertiesCache.GetPropertyValue( ODataJsonLightBatchPayloadItemPropertiesCache.PropertyNameId); string currentGroup = (string)messagePropertiesCache.GetPropertyValue( ODataJsonLightBatchPayloadItemPropertiesCache.PropertyNameAtomicityGroup); // ChangesetEnd check first; If not, check for changesetStart. bool changesetEnd = this.atomicGroups.IsChangesetEnd(currentGroup); bool changesetStart = false; if (!changesetEnd) { if (currentGroup != null) { // Add message Id to atomic group (create new group if needed). // Also detect changeset start. changesetStart = this.atomicGroups.AddMessageIdAndGroupId(valueId, currentGroup); } } // If we have changeset state change detected, set the state here. ODataBatchReaderState nextState = ODataBatchReaderState.Operation; if (changesetEnd) { nextState = ODataBatchReaderState.ChangesetEnd; } else if (changesetStart) { nextState = ODataBatchReaderState.ChangesetStart; } return(nextState); }
/// <summary> /// Sets the 'Exception' state and then throws an ODataException with the specified error message. /// </summary> /// <param name="errorMessage">The error message for the exception.</param> private void ThrowODataException(string errorMessage) { this.State = ODataBatchReaderState.Exception; throw new ODataException(errorMessage); }
/// <summary> /// Continues reading from the batch message payload. /// </summary> /// <returns>true if more items were read; otherwise false.</returns> private bool ReadImplementation() { Debug.Assert(this.operationState != OperationState.StreamRequested, "Should have verified that no operation stream is still active."); switch (this.State) { case ODataBatchReaderState.Initial: // The stream should be positioned at the beginning of the batch content, // that is before the first boundary (or the preamble if there is one). this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Operation: // When reaching this state we already read the MIME headers of the operation. // Clients MUST call CreateOperationRequestMessage // or CreateOperationResponseMessage to read at least the headers of the operation. // This is important since we need to read the ContentId header (if present) and // add it to the URL resolver. if (this.operationState == OperationState.None) { // No message was created; fail throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation); } // Reset the operation state; the operation state only // tracks the state of a batch operation while in state Operation. this.operationState = OperationState.None; // Also add a pending ContentId header to the URL resolver now. We ensured above // that a message has been created for this operation and thus the headers (incl. // a potential content ID header) have been read. if (this.contentIdToAddOnNextRead != null) { this.payloadUriConverter.AddContentId(this.contentIdToAddOnNextRead); this.contentIdToAddOnNextRead = null; } // When we are done with an operation, we have to skip ahead to the next part // when Read is called again. Note that if the operation stream was never requested // and the content of the operation has not been read, we'll skip it here. Debug.Assert(this.operationState == OperationState.None, "Operation state must be 'None' at the end of the operation."); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetStart: // When at the start of a changeset, skip ahead to the first operation in the // changeset (or the end boundary of the changeset). Debug.Assert(this.batchStream.ChangeSetBoundary != null, "Changeset boundary must have been set by now."); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetEnd: // When at the end of a changeset, reset the changeset boundary and the // changeset size and then skip to the next part. this.ResetChangeSetSize(); this.batchStream.ResetChangeSetBoundary(); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Exception: // fall through case ODataBatchReaderState.Completed: Debug.Assert(false, "Should have checked in VerifyCanRead that we are not in one of these states."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); default: Debug.Assert(false, "Unsupported reader state " + this.State + " detected."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); } return(this.batchReaderState != ODataBatchReaderState.Completed && this.batchReaderState != ODataBatchReaderState.Exception); }
/// <summary>Asynchronously reads the next part from the batch message payload.</summary> /// <returns>A task that when completed indicates whether more items were read.</returns> public Task <bool> ReadAsync() { this.VerifyCanRead(false); return(this.ReadAsynchronously().FollowOnFaultWith(t => this.State = ODataBatchReaderState.Exception)); }