/// <summary> /// Sets the request stream. /// </summary> /// <param name="requestStreamContent">The content stream to copy into the request stream.</param> internal void SetRequestStream(ContentStream requestStreamContent) { if (requestStreamContent.IsKnownMemoryStream) { this.SetContentLengthHeader(); } #if DEBUG this.ValidateHeaders(); #endif using (Stream requestStream = this.requestMessage.GetStream()) { if (requestStreamContent.IsKnownMemoryStream) { MemoryStream bufferableStream = (MemoryStream)requestStreamContent.Stream; Debug.Assert(bufferableStream.Position == 0, "Cached/buffered stream position should be 0"); byte[] buffer = bufferableStream.GetBuffer(); int bufferOffset = checked ((int)bufferableStream.Position); int bufferLength = checked ((int)bufferableStream.Length) - bufferOffset; // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); requestStream.Write(buffer, bufferOffset, bufferLength); } else { byte[] buffer = new byte[WebUtil.DefaultBufferSizeForStreamCopy]; WebUtil.CopyStream(requestStreamContent.Stream, requestStream, ref buffer); } } }
/// <summary> /// copy the response data /// </summary> /// <param name="response">response object</param> private void HandleOperationResponseData(IODataResponseMessage response) { Debug.Assert(response != null, "response != null"); using (Stream stream = response.GetStream()) { if (stream != null) { // we need to check for whether the incoming stream was data or not. Hence we need to copy it to a temporary memory stream using (MemoryStream memoryStream = new MemoryStream()) { if (WebUtil.CopyStream(stream, memoryStream, ref this.buildBatchBuffer) != 0) { // set the memory stream position to zero again. memoryStream.Position = 0; this.HandleOperationResponseData(response, memoryStream); } else { this.HandleOperationResponseData(response, null); } } } } }
/// <summary> /// Processed the operation response reported by the batch reader. /// This is a side-effecting method that is tied deeply to how it is used in the batch processing pipeline. /// </summary> /// <param name="batchReader">The batch reader to get the operation response from.</param> /// <param name="isChangesetOperation">True if the current operation is inside a changeset (implying CUD, not query)</param> /// <returns>An exception if the operation response is an error response, null for success response.</returns> private Exception ProcessCurrentOperationResponse(ODataBatchReader batchReader, bool isChangesetOperation) { Debug.Assert(batchReader != null, "batchReader != null"); Debug.Assert(batchReader.State == ODataBatchReaderState.Operation, "This method requires the batch reader to be on an operation."); ODataBatchOperationResponseMessage operationResponseMessage = batchReader.CreateOperationResponseMessage(); Descriptor descriptor = null; if (isChangesetOperation) { // We need to peek at the content-Id before handing the response to the user, so we can expose the Descriptor them. // We're OK with this exception to our general rule of not using them before ReceivingResponse event is fired. this.entryIndex = this.ValidateContentID(operationResponseMessage.ContentId); descriptor = this.ChangedEntries[entryIndex]; } // If we hit en error inside a batch, we will never expose a descriptor since we don't know which one to return. // The descriptor we fetched above based on the content-ID is bogus because the server returns an errounous content-id when // it hits an error inside batch. if (!WebUtil.SuccessStatusCode((HttpStatusCode)operationResponseMessage.StatusCode)) { descriptor = null; } this.RequestInfo.Context.FireReceivingResponseEvent(new ReceivingResponseEventArgs(operationResponseMessage, descriptor, true)); // We need to know if the content of the operation response is empty or not. // We also need to cache the entire content, since in case of GET response the response itself will be parsed // lazily and so it can happen that we will move the batch reader after this operation before we actually read // the content of the operation. Stream originalOperationResponseContentStream = operationResponseMessage.GetStream(); if (originalOperationResponseContentStream == null) { Error.ThrowBatchExpectedResponse(InternalError.NullResponseStream); } MemoryStream operationResponseContentStream; try { operationResponseContentStream = new MemoryStream(); WebUtil.CopyStream(originalOperationResponseContentStream, operationResponseContentStream, ref this.streamCopyBuffer); operationResponseContentStream.Position = 0; } finally { originalOperationResponseContentStream.Dispose(); } this.currentOperationResponse = new CurrentOperationResponse( (HttpStatusCode)operationResponseMessage.StatusCode, operationResponseMessage.Headers, operationResponseContentStream); Version responseVersion; string headerName = XmlConstants.HttpODataVersion; return(BaseSaveResult.HandleResponse( this.RequestInfo, this.currentOperationResponse.StatusCode, this.currentOperationResponse.Headers.GetHeader(headerName), () => this.currentOperationResponse.ContentStream, false, out responseVersion)); }
internal void ExecuteQuery() { try { if (this.requestContentStream != null && this.requestContentStream.Stream != null) { this.Request.SetRequestStream(this.requestContentStream); } #if false if ((null != requestContent) && (0 < requestContent.Length)) { using (System.IO.Stream stream = Util.NullCheck(this.Request.GetRequestStream(), InternalError.InvalidGetRequestStream)) { byte[] buffer = requestContent.GetBuffer(); int bufferOffset = checked ((int)requestContent.Position); int bufferLength = checked ((int)requestContent.Length) - bufferOffset; // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); stream.Write(buffer, bufferOffset, bufferLength); } } #endif IODataResponseMessage response = null; response = this.RequestInfo.GetSyncronousResponse(this.Request, true); this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse)); if (HttpStatusCode.NoContent != this.StatusCode) { using (Stream stream = this.responseMessage.GetStream()) { if (null != stream) { Stream copy = this.GetAsyncResponseStreamCopy(); this.outputResponseStream = copy; Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer(); long copied = WebUtil.CopyStream(stream, copy, ref buffer); if (this.responseStreamOwner) { if (0 == copied) { this.outputResponseStream = null; } else if (copy.Position < copy.Length) { // In Silverlight, generally 3 bytes less than advertised by ContentLength are read ((MemoryStream)copy).SetLength(copy.Position); } } this.PutAsyncResponseStreamCopyBuffer(buffer); } } } } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.SetCompleted(); this.CompletedRequest(); } if (null != this.Failure) { throw this.Failure; } }