QueryAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / QueryAsyncResult.cs / 3 / QueryAsyncResult.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// query object
//  
//--------------------------------------------------------------------- 

namespace System.Data.Services.Client 
{
    using System;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.IO; 
#if !ASTORIA_LIGHT // Data.Services http stack 
    using System.Net;
#else 
    using System.Data.Services.Http;
#endif

    ///  
    /// Wrapper HttpWebRequest & HttWebResponse
    ///  
    internal class QueryAsyncResult : BaseAsyncResult 
    {
        /// Originating service request 
        internal readonly DataServiceRequest ServiceRequest;

        /// Originating WebRequest
        internal readonly HttpWebRequest Request; 

        /// reusuable async copy buffer 
        private static byte[] reusableAsyncCopyBuffer; 

        /// content to write to request stream 
        private MemoryStream requestStreamContent;

        /// active web request stream
        private Stream requestStream; 

        /// web response, closed when completed 
        private HttpWebResponse httpWebResponse; 

        /// async response stream, closed when completed 
        private Stream asyncResponseStream;

        /// buffer when copying async stream to response stream cache
        private byte[] asyncStreamCopyBuffer; 

        /// response stream, returned to other parts of the system 
        /// with async, the asyncResponseStream is copied into this stream 
        private Stream responseStream;
 
        /// copy of HttpWebResponse.ContentType
        private string contentType;

        /// copy of HttpWebResponse.ContentLength 
        private long contentLength;
 
        /// copy of HttpWebResponse.StatusCode 
        private HttpStatusCode statusCode;
 
        /// 
        /// does this own the response stream or does the container of this QueryAsyncResult?
        /// 
        private bool responseStreamOwner; 

        ///  
        /// if the BeginRead has been called with asyncStreamCopyBuffer, but EndRead has not. 
        /// do not return the buffer to general pool if any question of it being in use.
        ///  
        private bool usingBuffer;

#if StreamContainsBuffer
        /// does the responseStream contain the asyncStreamCopyBuffer? 
        /// optimize reading in to the async buffer without copying into separate response stream
        private bool responseStreamIsCopyBuffer; 
#endif 

        /// If CompletedSynchronously and asyncCompleteStep didn't increment, then underlying implementation lied. 
        private int asyncCompleteStep;

        /// constructor
        /// source object of async request 
        /// async method name on source object
        /// Originating serviceRequest 
        /// Originating WebRequest 
        /// user callback
        /// user state 
        internal QueryAsyncResult(object source, string method, DataServiceRequest serviceRequest, HttpWebRequest request, AsyncCallback callback, object state)
            : base(source, method, callback, state)
        {
            Debug.Assert(null != request, "null request"); 
            this.ServiceRequest = serviceRequest;
            this.Request = request; 
        } 

        #region HttpResponse wrapper - ContentLength, ContentType, StatusCode 

        /// HttpWebResponse.ContentLength
        internal long ContentLength
        { 
            get { return this.contentLength; }
        } 
 
        /// HttpWebResponse.ContentType
        internal string ContentType 
        {
            get { return this.contentType; }
        }
 
        /// HttpWebResponse.StatusCode
        internal HttpStatusCode StatusCode 
        { 
            get { return this.statusCode; }
        } 

        #endregion

        /// wrapper for HttpWebResponse.GetResponseStream 
        /// stream
        internal Stream GetResponseStream() 
        { 
            return this.responseStream;
        } 

        /// start the asynchronous request
        /// content stream to send asynchronously in the request
        internal void BeginExecute(MemoryStream requestContent) 
        {
            try 
            { 
                int step = ++this.asyncCompleteStep;
 
                IAsyncResult asyncResult;
                if ((null != requestContent) && (0 < requestContent.Length))
                {
                    requestContent.Position = 0; 
                    this.requestStreamContent = requestContent;
                    this.Request.ContentLength = requestContent.Length; 
                    asyncResult = this.Request.BeginGetRequestStream(QueryAsyncResult.AsyncEndGetRequestStream, this); 
                }
                else 
                {
                    asyncResult = this.Request.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, this);
                }
 
                this.CompletedSynchronously &= asyncResult.CompletedSynchronously && (step < this.asyncCompleteStep);
            } 
            catch (Exception e) 
            {
                this.HandleFailure(e); 
                throw;
            }
            finally
            { 
                this.HandleCompleted();
            } 
 
            Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted");
        } 

#if !ASTORIA_LIGHT
        /// Synchronous web request
        /// content stream to send in the request 
        internal void Execute(MemoryStream requestContent)
        { 
            try 
            {
                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);
                    }
                }
 
                HttpWebResponse response = null;
                try 
                { 
                    response = (HttpWebResponse)this.Request.GetResponse();
                } 
                catch (WebException ex)
                {
                    response = (HttpWebResponse)ex.Response;
                } 

                this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse)); 
 
                if (HttpStatusCode.NoContent != this.StatusCode)
                { 
                    using (Stream stream = this.httpWebResponse.GetResponseStream())
                    {
                        if (null != stream)
                        { 
                            Stream copy = this.GetAsyncResponseStreamCopy();
                            this.responseStream = copy; 
 
                            Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer();
 
                            long copied = WebUtil.CopyStream(stream, copy, ref buffer);
                            if (this.responseStreamOwner)
                            {
                                if (0 == copied) 
                                {
                                    this.responseStream = 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);
                        } 
                    } 
                }
            } 
            finally
            {
                this.IsCompleted = true;
                this.CompletedRequest(); 
            }
 
            if (null != this.Failure) 
            {
                throw this.Failure; 
            }
        }
#endif
 
        /// 
        /// Returns the response for the request. 
        ///  
        /// materialized results for the request.
        /// element type of the results. 
        /// returns the instance of QueryOperationResponse containing the response.
        internal QueryOperationResponse GetResponse(IEnumerable results, Type elementType)
        {
            if (this.httpWebResponse != null) 
            {
                Dictionary headers = WebUtil.WrapResponseHeaders(this.httpWebResponse); 
                QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results); 
                response.StatusCode = (int)this.httpWebResponse.StatusCode;
                return response; 
            }

            return null;
        } 

        /// cleanup work to do once the request has completed 
        protected override void CompletedRequest() 
        {
            Util.Dispose(ref this.asyncResponseStream); 
            Util.Dispose(ref this.requestStream);
            Util.Dispose(ref this.requestStreamContent);

            byte[] buffer = this.asyncStreamCopyBuffer; 
            this.asyncStreamCopyBuffer = null;
#if StreamContainsBuffer 
            if (!this.responseStreamIsCopyBuffer) 
#endif
            if ((null != buffer) && !this.usingBuffer) 
            {
                this.PutAsyncResponseStreamCopyBuffer(buffer);
            }
 
            if (this.responseStreamOwner)
            { 
                if (null != this.responseStream) 
                {
                    this.responseStream.Position = 0; 
                }
            }

            // we've cached off what we need, headers still accessible after close 
            this.httpWebResponse.Close();
 
            Exception ex = DataServiceContext.HandleResponse(this.StatusCode, this.httpWebResponse.Headers[XmlConstants.HttpDataServiceVersion], this.GetResponseStream, false); 
            if (null != ex)
            { 
                this.HandleFailure(ex);
            }
        }
 
        /// get stream which of copy buffer (via response stream) will be copied into
        /// writtable stream, happens before GetAsyncResponseStreamCopyBuffer 
        protected virtual Stream GetAsyncResponseStreamCopy() 
        {
            this.responseStreamOwner = true; 

            long length = this.contentLength;
            if ((0 < length) && (length <= Int32.MaxValue))
            { 
                Debug.Assert(null == this.asyncStreamCopyBuffer, "not expecting buffer");
 
                byte[] buffer = new byte[(int)length]; 
#if StreamContainsBuffer
                if (length < UInt16.MaxValue) 
                {   // larger than this appears to cause trouble, specifically tested with 2619442
                    responseStreamIsCopyBuffer = true;
                    this.asyncStreamCopyBuffer = buffer;
                } 
#endif
                return new MemoryStream(buffer, 0, buffer.Length, true, true); 
            } 

            return new MemoryStream(); 
        }

        /// get buffer which response stream will be copied into
        /// writtable stream 
        protected virtual byte[] GetAsyncResponseStreamCopyBuffer()
        {   // consider having a cache of these buffers since they will be pinned 
            Debug.Assert(null == this.asyncStreamCopyBuffer, "non-null this.asyncStreamCopyBuffer"); 
            return System.Threading.Interlocked.Exchange(ref reusableAsyncCopyBuffer, null) ?? new byte[8000];
        } 

        /// returning a buffer after being done with it
        /// buffer to return
        protected virtual void PutAsyncResponseStreamCopyBuffer(byte[] buffer) 
        {
            reusableAsyncCopyBuffer = buffer; 
        } 

        /// set the http web response 
        /// response object
        protected virtual void SetHttpWebResponse(HttpWebResponse response)
        {
            this.httpWebResponse = response; 
            this.statusCode = response.StatusCode;
            this.contentLength = response.ContentLength; 
            this.contentType = response.ContentType; 
        }
 
        /// handle request.BeginGetRequestStream with request.EndGetRquestStream and then write out request stream
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetRequestStream(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; 
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndGetRequestCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetRequestStream

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetRequestStreamRequest);
 
                Stream stream = Util.NullCheck(httpWebRequest.EndGetRequestStream(asyncResult), InternalError.InvalidEndGetRequestStreamStream);
                state.requestStream = stream; 
 
                MemoryStream memoryStream = Util.NullCheck(state.requestStreamContent, InternalError.InvalidEndGetRequestStreamContent);
                byte[] buffer = memoryStream.GetBuffer(); 
                int bufferOffset = checked((int)memoryStream.Position);
                int bufferLength = checked((int)memoryStream.Length) - bufferOffset;
                if ((null == buffer) || (0 == bufferLength))
                { 
                    Error.ThrowInternalError(InternalError.InvalidEndGetRequestStreamContentLength);
                } 
 
                // the following is useful in the debugging Immediate Window
                // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); 
                asyncResult = stream.BeginWrite(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndWrite, state);

                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginWrite 
            }
            catch (Exception e) 
            { 
                if (state.HandleFailure(e))
                { 
                    throw;
                }
            }
            finally 
            {
                state.HandleCompleted(); 
            } 
        }
 
        /// handle reqestStream.BeginWrite with requestStream.EndWrite then BeginGetResponse
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndWrite(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; 
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndWriteCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginWrite

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndWriteRequest);
 
                Stream stream = Util.NullCheck(state.requestStream, InternalError.InvalidEndWriteStream);
                stream.EndWrite(asyncResult); 
 
                state.requestStream = null;
                stream.Dispose(); 

                stream = state.requestStreamContent;
                if (null != stream)
                { 
                    state.requestStreamContent = null;
                    stream.Dispose(); 
                } 

                asyncResult = httpWebRequest.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, state); 

                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginGetResponse
            } 
            catch (Exception e)
            { 
                if (state.HandleFailure(e)) 
                {
                    throw; 
                }
            }
            finally
            { 
                state.HandleCompleted();
            } 
        } 

        /// handle request.BeginGetResponse with request.EndGetResponse and then copy response stream 
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetResponse(IAsyncResult asyncResult)
        { 
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            try 
            { 
                int step = CompleteCheck(state, InternalError.InvalidEndGetResponseCompleted);
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetResponse 

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetResponseRequest);

                // the httpWebResponse is kept for batching, discarded by non-batch 
                HttpWebResponse response = null;
                try 
                { 
                    response = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult);
                } 
                catch (WebException e)
                {
                    response = (HttpWebResponse)e.Response;
                    if (null == response) 
                    {
                        throw; 
                    } 
                }
 
                state.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidEndGetResponseResponse));
                Debug.Assert(null == state.asyncResponseStream, "non-null asyncResponseStream");

                Stream stream = null; 
                if (HttpStatusCode.NoContent != response.StatusCode)
                { 
                    stream = response.GetResponseStream(); 
                    state.asyncResponseStream = stream;
                } 

                if ((null != stream) && stream.CanRead)
                {
                    if (null == state.responseStream) 
                    {   // this is the stream we copy the reponse to
                        state.responseStream = Util.NullCheck(state.GetAsyncResponseStreamCopy(), InternalError.InvalidAsyncResponseStreamCopy); 
                    } 

                    byte[] buffer = state.asyncStreamCopyBuffer; 
                    if (null == state.asyncStreamCopyBuffer)
                    {   // this is the buffer we read into and copy out of
                        state.asyncStreamCopyBuffer = buffer = Util.NullCheck(state.GetAsyncResponseStreamCopyBuffer(), InternalError.InvalidAsyncResponseStreamCopyBuffer);
                    } 

                    bool reallyCompletedSynchronously = false; 
                    do 
                    {
                        int bufferOffset, bufferLength; 
#if StreamContainsBuffer
                        if (state.responseStreamIsCopyBuffer)
                        {   // we may have asked for, but not received the entire stream
                            bufferOffset = checked((int)state.responseStream.Position); 
                            bufferLength = buffer.Length - bufferOffset;
                        } 
                        else 
#endif
                        { 
                            bufferOffset = 0;
                            bufferLength = buffer.Length;
                        }
 
                        state.usingBuffer = true;
                        asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); 
 
                        reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                        state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead 
                    }
                    while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead);

                    Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndGetResponse !IsCompleted"); 
                }
                else 
                { 
                    state.IsCompleted = true;
                } 
            }
            catch (Exception e)
            {
                if (state.HandleFailure(e)) 
                {
                    throw; 
                } 
            }
            finally 
            {
                state.HandleCompleted();
            }
        } 

        /// handle responseStream.BeginRead with responseStream.EndRead 
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndRead(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            int count = 0;
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndReadCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead 

                Stream stream = Util.NullCheck(state.asyncResponseStream, InternalError.InvalidEndReadStream); 
                Stream outputResponse = Util.NullCheck(state.responseStream, InternalError.InvalidEndReadCopy);
                byte[] buffer = Util.NullCheck(state.asyncStreamCopyBuffer, InternalError.InvalidEndReadBuffer);
                int bufferOffset = 0, bufferLength = 0;
 
                count = stream.EndRead(asyncResult);
                state.usingBuffer = false; 
                if (0 < count) 
                {
#if StreamContainsBuffer 
                    if (state.responseStreamIsCopyBuffer)
                    {   // we may have asked for, but not received the entire stream
                        outputResponse.Position = outputResponse.Position + count;
                        bufferOffset = checked((int)outputResponse.Position); 
                        bufferLength = buffer.Length - bufferOffset;
                    } 
                    else 
#endif
                    { 
                        outputResponse.Write(buffer, 0, count);
                        bufferOffset = 0;
                        bufferLength = buffer.Length;
                    } 
                }
 
                if ((0 < bufferLength) && stream.CanRead) 
                {
                    if (!asyncResult.CompletedSynchronously) 
                    {   // if CompletedSynchronously then caller will call and we reduce risk of stack overflow
                        bool reallyCompletedSynchronously = false;
                        do
                        { 
                            state.usingBuffer = true;
                            asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); 
 
                            reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                            state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead 
                        }
                        while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead);

                        Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndRead !IsCompleted"); 
                    }
                } 
                else 
                {
#if StreamContainsBuffer 
                    Debug.Assert(!state.responseStreamIsCopyBuffer || (outputResponse.Position == outputResponse.Length), "didn't read expected count");
#endif
                    Debug.Assert(state.ContentLength < 0 || outputResponse.Length == state.ContentLength, "didn't read expected ContentLength");
                    if (outputResponse.Position < outputResponse.Length) 
                    {
                        // In Silverlight, generally 3 bytes less than advertised by ContentLength are read 
                        ((MemoryStream)outputResponse).SetLength(outputResponse.Position); 
                    }
 
                    state.IsCompleted = true;
                }
            }
            catch (Exception e) 
            {
                if (state.HandleFailure(e)) 
                { 
                    throw;
                } 
            }
            finally
            {
                state.HandleCompleted(); 
            }
        } 
 
        /// verify non-null and not completed
        /// async result 
        /// error code if null or completed
        /// the next step to validate CompletedSyncronously
        private static int CompleteCheck(QueryAsyncResult pereq, InternalError errorcode)
        { 
            if ((null == pereq) || pereq.IsCompleted)
            { 
                Error.ThrowInternalError(errorcode); 
            }
 
            return ++pereq.asyncCompleteStep;
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// query object
//  
//--------------------------------------------------------------------- 

namespace System.Data.Services.Client 
{
    using System;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.IO; 
#if !ASTORIA_LIGHT // Data.Services http stack 
    using System.Net;
#else 
    using System.Data.Services.Http;
#endif

    ///  
    /// Wrapper HttpWebRequest & HttWebResponse
    ///  
    internal class QueryAsyncResult : BaseAsyncResult 
    {
        /// Originating service request 
        internal readonly DataServiceRequest ServiceRequest;

        /// Originating WebRequest
        internal readonly HttpWebRequest Request; 

        /// reusuable async copy buffer 
        private static byte[] reusableAsyncCopyBuffer; 

        /// content to write to request stream 
        private MemoryStream requestStreamContent;

        /// active web request stream
        private Stream requestStream; 

        /// web response, closed when completed 
        private HttpWebResponse httpWebResponse; 

        /// async response stream, closed when completed 
        private Stream asyncResponseStream;

        /// buffer when copying async stream to response stream cache
        private byte[] asyncStreamCopyBuffer; 

        /// response stream, returned to other parts of the system 
        /// with async, the asyncResponseStream is copied into this stream 
        private Stream responseStream;
 
        /// copy of HttpWebResponse.ContentType
        private string contentType;

        /// copy of HttpWebResponse.ContentLength 
        private long contentLength;
 
        /// copy of HttpWebResponse.StatusCode 
        private HttpStatusCode statusCode;
 
        /// 
        /// does this own the response stream or does the container of this QueryAsyncResult?
        /// 
        private bool responseStreamOwner; 

        ///  
        /// if the BeginRead has been called with asyncStreamCopyBuffer, but EndRead has not. 
        /// do not return the buffer to general pool if any question of it being in use.
        ///  
        private bool usingBuffer;

#if StreamContainsBuffer
        /// does the responseStream contain the asyncStreamCopyBuffer? 
        /// optimize reading in to the async buffer without copying into separate response stream
        private bool responseStreamIsCopyBuffer; 
#endif 

        /// If CompletedSynchronously and asyncCompleteStep didn't increment, then underlying implementation lied. 
        private int asyncCompleteStep;

        /// constructor
        /// source object of async request 
        /// async method name on source object
        /// Originating serviceRequest 
        /// Originating WebRequest 
        /// user callback
        /// user state 
        internal QueryAsyncResult(object source, string method, DataServiceRequest serviceRequest, HttpWebRequest request, AsyncCallback callback, object state)
            : base(source, method, callback, state)
        {
            Debug.Assert(null != request, "null request"); 
            this.ServiceRequest = serviceRequest;
            this.Request = request; 
        } 

        #region HttpResponse wrapper - ContentLength, ContentType, StatusCode 

        /// HttpWebResponse.ContentLength
        internal long ContentLength
        { 
            get { return this.contentLength; }
        } 
 
        /// HttpWebResponse.ContentType
        internal string ContentType 
        {
            get { return this.contentType; }
        }
 
        /// HttpWebResponse.StatusCode
        internal HttpStatusCode StatusCode 
        { 
            get { return this.statusCode; }
        } 

        #endregion

        /// wrapper for HttpWebResponse.GetResponseStream 
        /// stream
        internal Stream GetResponseStream() 
        { 
            return this.responseStream;
        } 

        /// start the asynchronous request
        /// content stream to send asynchronously in the request
        internal void BeginExecute(MemoryStream requestContent) 
        {
            try 
            { 
                int step = ++this.asyncCompleteStep;
 
                IAsyncResult asyncResult;
                if ((null != requestContent) && (0 < requestContent.Length))
                {
                    requestContent.Position = 0; 
                    this.requestStreamContent = requestContent;
                    this.Request.ContentLength = requestContent.Length; 
                    asyncResult = this.Request.BeginGetRequestStream(QueryAsyncResult.AsyncEndGetRequestStream, this); 
                }
                else 
                {
                    asyncResult = this.Request.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, this);
                }
 
                this.CompletedSynchronously &= asyncResult.CompletedSynchronously && (step < this.asyncCompleteStep);
            } 
            catch (Exception e) 
            {
                this.HandleFailure(e); 
                throw;
            }
            finally
            { 
                this.HandleCompleted();
            } 
 
            Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted");
        } 

#if !ASTORIA_LIGHT
        /// Synchronous web request
        /// content stream to send in the request 
        internal void Execute(MemoryStream requestContent)
        { 
            try 
            {
                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);
                    }
                }
 
                HttpWebResponse response = null;
                try 
                { 
                    response = (HttpWebResponse)this.Request.GetResponse();
                } 
                catch (WebException ex)
                {
                    response = (HttpWebResponse)ex.Response;
                } 

                this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse)); 
 
                if (HttpStatusCode.NoContent != this.StatusCode)
                { 
                    using (Stream stream = this.httpWebResponse.GetResponseStream())
                    {
                        if (null != stream)
                        { 
                            Stream copy = this.GetAsyncResponseStreamCopy();
                            this.responseStream = copy; 
 
                            Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer();
 
                            long copied = WebUtil.CopyStream(stream, copy, ref buffer);
                            if (this.responseStreamOwner)
                            {
                                if (0 == copied) 
                                {
                                    this.responseStream = 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);
                        } 
                    } 
                }
            } 
            finally
            {
                this.IsCompleted = true;
                this.CompletedRequest(); 
            }
 
            if (null != this.Failure) 
            {
                throw this.Failure; 
            }
        }
#endif
 
        /// 
        /// Returns the response for the request. 
        ///  
        /// materialized results for the request.
        /// element type of the results. 
        /// returns the instance of QueryOperationResponse containing the response.
        internal QueryOperationResponse GetResponse(IEnumerable results, Type elementType)
        {
            if (this.httpWebResponse != null) 
            {
                Dictionary headers = WebUtil.WrapResponseHeaders(this.httpWebResponse); 
                QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results); 
                response.StatusCode = (int)this.httpWebResponse.StatusCode;
                return response; 
            }

            return null;
        } 

        /// cleanup work to do once the request has completed 
        protected override void CompletedRequest() 
        {
            Util.Dispose(ref this.asyncResponseStream); 
            Util.Dispose(ref this.requestStream);
            Util.Dispose(ref this.requestStreamContent);

            byte[] buffer = this.asyncStreamCopyBuffer; 
            this.asyncStreamCopyBuffer = null;
#if StreamContainsBuffer 
            if (!this.responseStreamIsCopyBuffer) 
#endif
            if ((null != buffer) && !this.usingBuffer) 
            {
                this.PutAsyncResponseStreamCopyBuffer(buffer);
            }
 
            if (this.responseStreamOwner)
            { 
                if (null != this.responseStream) 
                {
                    this.responseStream.Position = 0; 
                }
            }

            // we've cached off what we need, headers still accessible after close 
            this.httpWebResponse.Close();
 
            Exception ex = DataServiceContext.HandleResponse(this.StatusCode, this.httpWebResponse.Headers[XmlConstants.HttpDataServiceVersion], this.GetResponseStream, false); 
            if (null != ex)
            { 
                this.HandleFailure(ex);
            }
        }
 
        /// get stream which of copy buffer (via response stream) will be copied into
        /// writtable stream, happens before GetAsyncResponseStreamCopyBuffer 
        protected virtual Stream GetAsyncResponseStreamCopy() 
        {
            this.responseStreamOwner = true; 

            long length = this.contentLength;
            if ((0 < length) && (length <= Int32.MaxValue))
            { 
                Debug.Assert(null == this.asyncStreamCopyBuffer, "not expecting buffer");
 
                byte[] buffer = new byte[(int)length]; 
#if StreamContainsBuffer
                if (length < UInt16.MaxValue) 
                {   // larger than this appears to cause trouble, specifically tested with 2619442
                    responseStreamIsCopyBuffer = true;
                    this.asyncStreamCopyBuffer = buffer;
                } 
#endif
                return new MemoryStream(buffer, 0, buffer.Length, true, true); 
            } 

            return new MemoryStream(); 
        }

        /// get buffer which response stream will be copied into
        /// writtable stream 
        protected virtual byte[] GetAsyncResponseStreamCopyBuffer()
        {   // consider having a cache of these buffers since they will be pinned 
            Debug.Assert(null == this.asyncStreamCopyBuffer, "non-null this.asyncStreamCopyBuffer"); 
            return System.Threading.Interlocked.Exchange(ref reusableAsyncCopyBuffer, null) ?? new byte[8000];
        } 

        /// returning a buffer after being done with it
        /// buffer to return
        protected virtual void PutAsyncResponseStreamCopyBuffer(byte[] buffer) 
        {
            reusableAsyncCopyBuffer = buffer; 
        } 

        /// set the http web response 
        /// response object
        protected virtual void SetHttpWebResponse(HttpWebResponse response)
        {
            this.httpWebResponse = response; 
            this.statusCode = response.StatusCode;
            this.contentLength = response.ContentLength; 
            this.contentType = response.ContentType; 
        }
 
        /// handle request.BeginGetRequestStream with request.EndGetRquestStream and then write out request stream
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetRequestStream(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; 
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndGetRequestCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetRequestStream

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetRequestStreamRequest);
 
                Stream stream = Util.NullCheck(httpWebRequest.EndGetRequestStream(asyncResult), InternalError.InvalidEndGetRequestStreamStream);
                state.requestStream = stream; 
 
                MemoryStream memoryStream = Util.NullCheck(state.requestStreamContent, InternalError.InvalidEndGetRequestStreamContent);
                byte[] buffer = memoryStream.GetBuffer(); 
                int bufferOffset = checked((int)memoryStream.Position);
                int bufferLength = checked((int)memoryStream.Length) - bufferOffset;
                if ((null == buffer) || (0 == bufferLength))
                { 
                    Error.ThrowInternalError(InternalError.InvalidEndGetRequestStreamContentLength);
                } 
 
                // the following is useful in the debugging Immediate Window
                // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); 
                asyncResult = stream.BeginWrite(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndWrite, state);

                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginWrite 
            }
            catch (Exception e) 
            { 
                if (state.HandleFailure(e))
                { 
                    throw;
                }
            }
            finally 
            {
                state.HandleCompleted(); 
            } 
        }
 
        /// handle reqestStream.BeginWrite with requestStream.EndWrite then BeginGetResponse
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndWrite(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; 
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndWriteCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginWrite

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndWriteRequest);
 
                Stream stream = Util.NullCheck(state.requestStream, InternalError.InvalidEndWriteStream);
                stream.EndWrite(asyncResult); 
 
                state.requestStream = null;
                stream.Dispose(); 

                stream = state.requestStreamContent;
                if (null != stream)
                { 
                    state.requestStreamContent = null;
                    stream.Dispose(); 
                } 

                asyncResult = httpWebRequest.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, state); 

                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginGetResponse
            } 
            catch (Exception e)
            { 
                if (state.HandleFailure(e)) 
                {
                    throw; 
                }
            }
            finally
            { 
                state.HandleCompleted();
            } 
        } 

        /// handle request.BeginGetResponse with request.EndGetResponse and then copy response stream 
        /// async result
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetResponse(IAsyncResult asyncResult)
        { 
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            try 
            { 
                int step = CompleteCheck(state, InternalError.InvalidEndGetResponseCompleted);
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetResponse 

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetResponseRequest);

                // the httpWebResponse is kept for batching, discarded by non-batch 
                HttpWebResponse response = null;
                try 
                { 
                    response = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult);
                } 
                catch (WebException e)
                {
                    response = (HttpWebResponse)e.Response;
                    if (null == response) 
                    {
                        throw; 
                    } 
                }
 
                state.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidEndGetResponseResponse));
                Debug.Assert(null == state.asyncResponseStream, "non-null asyncResponseStream");

                Stream stream = null; 
                if (HttpStatusCode.NoContent != response.StatusCode)
                { 
                    stream = response.GetResponseStream(); 
                    state.asyncResponseStream = stream;
                } 

                if ((null != stream) && stream.CanRead)
                {
                    if (null == state.responseStream) 
                    {   // this is the stream we copy the reponse to
                        state.responseStream = Util.NullCheck(state.GetAsyncResponseStreamCopy(), InternalError.InvalidAsyncResponseStreamCopy); 
                    } 

                    byte[] buffer = state.asyncStreamCopyBuffer; 
                    if (null == state.asyncStreamCopyBuffer)
                    {   // this is the buffer we read into and copy out of
                        state.asyncStreamCopyBuffer = buffer = Util.NullCheck(state.GetAsyncResponseStreamCopyBuffer(), InternalError.InvalidAsyncResponseStreamCopyBuffer);
                    } 

                    bool reallyCompletedSynchronously = false; 
                    do 
                    {
                        int bufferOffset, bufferLength; 
#if StreamContainsBuffer
                        if (state.responseStreamIsCopyBuffer)
                        {   // we may have asked for, but not received the entire stream
                            bufferOffset = checked((int)state.responseStream.Position); 
                            bufferLength = buffer.Length - bufferOffset;
                        } 
                        else 
#endif
                        { 
                            bufferOffset = 0;
                            bufferLength = buffer.Length;
                        }
 
                        state.usingBuffer = true;
                        asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); 
 
                        reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                        state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead 
                    }
                    while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead);

                    Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndGetResponse !IsCompleted"); 
                }
                else 
                { 
                    state.IsCompleted = true;
                } 
            }
            catch (Exception e)
            {
                if (state.HandleFailure(e)) 
                {
                    throw; 
                } 
            }
            finally 
            {
                state.HandleCompleted();
            }
        } 

        /// handle responseStream.BeginRead with responseStream.EndRead 
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndRead(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            int count = 0;
            try 
            {
                int step = CompleteCheck(state, InternalError.InvalidEndReadCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead 

                Stream stream = Util.NullCheck(state.asyncResponseStream, InternalError.InvalidEndReadStream); 
                Stream outputResponse = Util.NullCheck(state.responseStream, InternalError.InvalidEndReadCopy);
                byte[] buffer = Util.NullCheck(state.asyncStreamCopyBuffer, InternalError.InvalidEndReadBuffer);
                int bufferOffset = 0, bufferLength = 0;
 
                count = stream.EndRead(asyncResult);
                state.usingBuffer = false; 
                if (0 < count) 
                {
#if StreamContainsBuffer 
                    if (state.responseStreamIsCopyBuffer)
                    {   // we may have asked for, but not received the entire stream
                        outputResponse.Position = outputResponse.Position + count;
                        bufferOffset = checked((int)outputResponse.Position); 
                        bufferLength = buffer.Length - bufferOffset;
                    } 
                    else 
#endif
                    { 
                        outputResponse.Write(buffer, 0, count);
                        bufferOffset = 0;
                        bufferLength = buffer.Length;
                    } 
                }
 
                if ((0 < bufferLength) && stream.CanRead) 
                {
                    if (!asyncResult.CompletedSynchronously) 
                    {   // if CompletedSynchronously then caller will call and we reduce risk of stack overflow
                        bool reallyCompletedSynchronously = false;
                        do
                        { 
                            state.usingBuffer = true;
                            asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); 
 
                            reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                            state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead 
                        }
                        while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead);

                        Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndRead !IsCompleted"); 
                    }
                } 
                else 
                {
#if StreamContainsBuffer 
                    Debug.Assert(!state.responseStreamIsCopyBuffer || (outputResponse.Position == outputResponse.Length), "didn't read expected count");
#endif
                    Debug.Assert(state.ContentLength < 0 || outputResponse.Length == state.ContentLength, "didn't read expected ContentLength");
                    if (outputResponse.Position < outputResponse.Length) 
                    {
                        // In Silverlight, generally 3 bytes less than advertised by ContentLength are read 
                        ((MemoryStream)outputResponse).SetLength(outputResponse.Position); 
                    }
 
                    state.IsCompleted = true;
                }
            }
            catch (Exception e) 
            {
                if (state.HandleFailure(e)) 
                { 
                    throw;
                } 
            }
            finally
            {
                state.HandleCompleted(); 
            }
        } 
 
        /// verify non-null and not completed
        /// async result 
        /// error code if null or completed
        /// the next step to validate CompletedSyncronously
        private static int CompleteCheck(QueryAsyncResult pereq, InternalError errorcode)
        { 
            if ((null == pereq) || pereq.IsCompleted)
            { 
                Error.ThrowInternalError(errorcode); 
            }
 
            return ++pereq.asyncCompleteStep;
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK