示例#1
0
        /// <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);
                }
            }
        }
示例#2
0
            public Stream GetStream()
            {
                if (this.cachedRequestStream == null)
                {
                    this.cachedRequestStream = new ContentStream(new MemoryStream(), true /*isKnownMemoryStream*/);
                }

                return(this.cachedRequestStream.Stream);
            }
示例#3
0
        /// <summary>
        /// This starts the next change
        /// </summary>
        internal void CreateNextChange()
        {
            ODataRequestMessageWrapper requestMessage = null;

            do
            {
                IODataResponseMessage responseMsg = null;

                try
                {
                    requestMessage = this.CreateNextRequest();
                    if ((requestMessage != null) || (this.entryIndex < this.ChangedEntries.Count))
                    {
                        if (this.ChangedEntries[this.entryIndex].ContentGeneratedForSave)
                        {
                            Debug.Assert(this.ChangedEntries[this.entryIndex] is LinkDescriptor, "only expected RelatedEnd to presave");
                            Debug.Assert(
                                this.ChangedEntries[this.entryIndex].State == EntityStates.Added ||
                                this.ChangedEntries[this.entryIndex].State == EntityStates.Modified,
                                "only expected added to presave");
                            continue;
                        }

                        ContentStream contentStream = this.CreateNonBatchChangeData(this.entryIndex, requestMessage);
                        if (contentStream != null && contentStream.Stream != null)
                        {
                            requestMessage.SetRequestStream(contentStream);
                        }

                        responseMsg = this.RequestInfo.GetSynchronousResponse(requestMessage, false);

                        this.HandleOperationResponse(responseMsg);
                        this.HandleOperationResponseHeaders((HttpStatusCode)responseMsg.StatusCode, new HeaderCollection(responseMsg));
                        this.HandleOperationResponseData(responseMsg);
                        this.perRequest = null;
                    }
                }
                catch (InvalidOperationException e)
                {
                    e = WebUtil.GetHttpWebResponse(e, ref responseMsg);
                    this.HandleOperationException(e, responseMsg);
                }
                finally
                {
                    WebUtil.DisposeMessage(responseMsg);
                }

                // we have no more pending requests or there has been an error in the previous request and we decided not to continue
                // (When an error occurs and we are not going to continue on error, we call SetCompleted
            }while (this.entryIndex < this.ChangedEntries.Count && !this.IsCompletedInternally);

            Debug.Assert(this.entryIndex < this.ChangedEntries.Count || this.ChangedEntries.All(o => o.ContentGeneratedForSave), "didn't generate content for all entities/links");
        }
示例#4
0
 /// <summary>constructor</summary>
 /// <param name="source">source object of async request</param>
 /// <param name="method">async method name on source object</param>
 /// <param name="serviceRequest">Originating serviceRequest</param>
 /// <param name="request">Originating WebRequest</param>
 /// <param name="requestInfo">The request info of the originating request.</param>
 /// <param name="callback">user callback</param>
 /// <param name="state">user state</param>
 /// <param name="requestContentStream">the stream containing the request data.</param>
 internal QueryResult(object source, string method, DataServiceRequest serviceRequest, ODataRequestMessageWrapper request, RequestInfo requestInfo, AsyncCallback callback, object state, ContentStream requestContentStream)
     : this(source, method, serviceRequest, request, requestInfo, callback, state)
 {
     Debug.Assert(null != requestContentStream, "null requestContentStream");
     this.requestContentStream = requestContentStream;
 }
示例#5
0
        internal void BeginCreateNextChange()
        {
            Debug.Assert(!this.IsCompletedInternally, "why being called if already completed?");

            // create the memory stream required to cache the responses as we read async from the underlying http web response
            this.inMemoryResponseStream = new MemoryStream();

            // SaveCallback can't chain synchronously completed responses, caller will loop the to next change
            PerRequest   pereq       = null;
            IAsyncResult asyncResult = null;

            do
            {
                IODataResponseMessage      responseMsg    = null;
                ODataRequestMessageWrapper requestMessage = null;
                try
                {
                    if (this.perRequest != null)
                    {
                        this.SetCompleted();
                        Error.ThrowInternalError(InternalError.InvalidBeginNextChange);
                    }

                    requestMessage = this.CreateNextRequest();

                    // Keeping the old behavior (V1/V2) where the abortable was set to null,
                    // if CreateNextRequest returned null.
                    if (requestMessage == null)
                    {
                        this.Abortable = null;
                    }

                    if ((requestMessage != null) || (this.entryIndex < this.ChangedEntries.Count))
                    {
                        if (this.ChangedEntries[this.entryIndex].ContentGeneratedForSave)
                        {
                            Debug.Assert(this.ChangedEntries[this.entryIndex] is LinkDescriptor, "only expected RelatedEnd to presave");
                            Debug.Assert(
                                this.ChangedEntries[this.entryIndex].State == EntityStates.Added ||
                                this.ChangedEntries[this.entryIndex].State == EntityStates.Modified,
                                "only expected added to presave");
                            continue;
                        }

                        this.Abortable = requestMessage;
                        ContentStream contentStream = this.CreateNonBatchChangeData(this.entryIndex, requestMessage);
                        this.perRequest = pereq = new PerRequest();
                        pereq.Request   = requestMessage;

                        AsyncStateBag asyncStateBag = new AsyncStateBag(pereq);

                        if (contentStream == null || contentStream.Stream == null)
                        {
                            asyncResult = BaseAsyncResult.InvokeAsync(requestMessage.BeginGetResponse, this.AsyncEndGetResponse, asyncStateBag);
                        }
                        else
                        {
                            if (contentStream.IsKnownMemoryStream)
                            {
                                requestMessage.SetContentLengthHeader();
                            }

                            pereq.RequestContentStream = contentStream;
                            asyncResult = BaseAsyncResult.InvokeAsync(requestMessage.BeginGetRequestStream, this.AsyncEndGetRequestStream, asyncStateBag);
                        }

                        pereq.SetRequestCompletedSynchronously(asyncResult.CompletedSynchronously);
                        this.SetCompletedSynchronously(pereq.RequestCompletedSynchronously);
                    }
                    else
                    {
                        this.SetCompleted();

                        if (this.CompletedSynchronously)
                        {
                            this.HandleCompleted(pereq);
                        }
                    }
                }
                catch (InvalidOperationException e)
                {
                    e = WebUtil.GetHttpWebResponse(e, ref responseMsg);
                    this.HandleOperationException(e, responseMsg);
                    this.HandleCompleted(pereq);
                }
                finally
                {
                    WebUtil.DisposeMessage(responseMsg);
                }

                // If the current request is completed synchronously, we need to call FinishCurrentChange() to process the response payload.
                // FinishCurrentChange() will not call BeginCreateNextChange() when the request is synchronous.
                // If the current request is completed asynchronously, an async thread will call FinishCurrentChange() to process the response payload.
                // FinishCurrentchange() will then call BeginCreateNextChange() from the async thread and we need to exit this loop.
                // If requestMessage = this.CreateNextRequest() returns null, we would have called this.SetCompleted() above and this.IsCompletedInternally
                // would be true. This means we are done processing all changed entries and we should not call this.FinishCurrentChange().
                if (pereq != null && pereq.RequestCompleted && pereq.RequestCompletedSynchronously && !this.IsCompletedInternally)
                {
                    Debug.Assert(requestMessage != null, "httpWebRequest != null");
                    this.FinishCurrentChange(pereq);
                }

                // In the condition for the do-while loop we must test for pereq.RequestCompletedSynchronously and not asyncResult.CompletedSynchronously.
                // pereq.RequestCompletedSynchronously is true only if all async calls completed synchronously.  If we don't exit this loop when
                // pereq.RequestCompletedSynchronously is false, the current thread and an async thread will both re-enter BeginCreateNextChange()
                // and we will fail.  We can only process one request at a given time.
            }while (((pereq == null) || (pereq.RequestCompleted && pereq.RequestCompletedSynchronously)) && !this.IsCompletedInternally);
            Debug.Assert((this.CompletedSynchronously && this.IsCompleted) || !this.CompletedSynchronously, "sync without complete");
            Debug.Assert(this.entryIndex < this.ChangedEntries.Count || this.ChangedEntries.All(o => o.ContentGeneratedForSave), "didn't generate content for all entities/links");
        }