Пример #1
0
        /// <summary>
        /// Ends executing an asynchronous request.
        /// </summary>
        private void InternalEndExecuteRequest(IAsyncResult asyncResult)
        {
            AsyncExecutionState state = (AsyncExecutionState)asyncResult.AsyncState;
            AsyncRequestResult  asyncRequestResult = null;
            bool retried = false;

            try
            {
                asyncRequestResult = new AsyncRequestResult(new Response(
                                                                state.CurrentRequest.EndGetResponse(asyncResult)));
            }
            catch (WebException ex)
            {
                // Returns null if the attempt was retried.
                retried = HandleFailedRequest(state, ex, out asyncRequestResult);
            }
            catch (Exception ex) // Unknown exception.
            {
                asyncRequestResult = new AsyncRequestResult(
                    new GoogleApiRequestException(Service, this, null, ex));
            }
            finally
            {
                // If the async result is null, this indicates that the request was retried.
                // Another handler will be executed to respond to that attempt, so do not
                // call the handler yet.
                if (!retried)
                {
                    state.ResponseHandler(asyncRequestResult);
                }
            }
        }
        private static void _completeGetRequestStream <TResponse>(IAsyncResult ar)
        {
            AsyncExecutionState <TResponse> r = (AsyncExecutionState <TResponse>)ar.AsyncState;

            System.IO.Stream reqstr;
            try
            {
                reqstr = r.request.EndGetRequestStream(ar);
            }
            catch (WebException wex)
            {
                r.handleWebException(wex);
                r.completedWithError(wex);
                r.clear();
                r      = null;
                reqstr = null;
                return;
            }
            catch (Exception ex)
            {
                r.handleException(ex);
                r.completedWithError(ex);
                r.clear();
                r      = null;
                reqstr = null;
                return;
            }

            try
            {
                using (reqstr)
                    reqstr.Write(r.bodyBytes, 0, r.bodyBytes.Length);
            }
            catch (WebException wex)
            {
                r.handleWebException(wex);
                r.completedWithError(wex);
                r.clear();
                r      = null;
                reqstr = null;
                return;
            }
            catch (Exception ex)
            {
                r.handleException(ex);
                r.completedWithError(ex);
                r.clear();
                r      = null;
                reqstr = null;
                return;
            }

            // Start an async operation to get the response:
            r.request.BeginGetResponse(_completeGetResponse <TResponse>, r);
        }
        private static void _completeGetResponse <TResponse>(IAsyncResult ar)
        {
            AsyncExecutionState <TResponse> r = (AsyncExecutionState <TResponse>)ar.AsyncState;

            HttpWebResponse rsp;

            try
            {
                rsp = (HttpWebResponse)r.request.EndGetResponse(ar);
            }
            catch (WebException wex)
            {
                r.handleWebException(wex);
                r.completedWithError(wex);
                r.clear();
                r = null;
                return;
            }
            catch (Exception ex)
            {
                r.handleException(ex);
                r.completedWithError(ex);
                r.clear();
                r = null;
                return;
            }

            try
            {
                using (var rs = rsp.GetResponseStream())
                {
                    Debug.Assert(r.deserializeBody != null);
                    var result = (TResponse)r.deserializeBody(rs, typeof(TResponse));
                    r.handleResponse(result);
                }
            }
            catch (WebException wex)
            {
                r.handleWebException(wex);
                r.completedWithError(wex);
                r.clear();
            }
            catch (Exception ex)
            {
                r.handleException(ex);
                r.completedWithError(ex);
                r.clear();
            }
            finally
            {
                rsp.Close();
                r.clear();
            }
        }
        /// <summary>
        /// Fetches the request asynchronously and calls one of the appropriate handlers when completed (likely on a separate thread).
        /// </summary>
        /// <typeparam name="TResponse">The type to deserialize the response object to</typeparam>
        /// <param name="handleWebException">Called if a WebException is generated</param>
        /// <param name="handleGenericException">Called if an Exception is generated</param>
        /// <param name="completedWithError">Called when either error handler completes</param>
        /// <param name="handleResponse">Called to handle the successful response with the deserialized response object</param>
        public void FetchAsync <TResponse>(
            Action <WebException> handleWebException,
            Action <Exception> handleGenericException,
            Action <Exception> completedWithError,
            Action <TResponse> handleResponse)
        {
            if (handleResponse == null)
            {
                throw new ArgumentNullException("handleResponse");
            }

            var _handleWebException = handleWebException ?? _defaultHandleWebException;
            var _handleException    = handleGenericException ?? _defaultHandleException;
            var _completedWithError = completedWithError ?? _defaultDoNothing;

            try
            {
                _bodyBytes = serializeBody();
                _auth.Authenticate(_request, _bodyBytes);
                _auth = null;

                var _handleResponse = handleResponse;

                var ast = new AsyncExecutionState <TResponse>(_bodyBytes, _request, _handleWebException, _handleException, _completedWithError, _deserializeBody, _handleResponse);

                if (_bodyBytes != null)
                {
                    // Send the body:
                    _request.BeginGetRequestStream(_completeGetRequestStream <TResponse>, ast);
                }
                else
                {
                    _request.BeginGetResponse(_completeGetResponse <TResponse>, ast);
                }
            }
            catch (WebException wex)
            {
                _handleWebException(wex);
                _completedWithError(wex);
            }
            catch (Exception ex)
            {
                _handleException(ex);
                _completedWithError(ex);
            }
        }
Пример #5
0
        /// <summary>
        /// Executes the request asynchronously, and calls the specified delegate once done.
        /// </summary>
        /// <param name="responseHandler">The method to call once a response has been received.</param>
        public void ExecuteRequestAsync(Action <IAsyncRequestResult> responseHandler)
        {
            // Validate the input.
            var validator = new MethodValidator(Method, Parameters);

            if (validator.ValidateAllParameters() == false)
            {
                throw new InvalidOperationException("Request parameter validation failed for [" + this + "]");
            }

            // Begin a new request and when it is completed being assembled, execute it asynchronously.
            CreateWebRequest((request) =>
            {
                // When the request is completed constructing, execute it.
                var state = new AsyncExecutionState()
                {
                    ResponseHandler = responseHandler,
                    Try             = 1,
                    WaitTime        = RetryInitialWaitTime,
                    CurrentRequest  = request
                };
                InternalBeginExecuteRequest(state);
            });
        }
Пример #6
0
 /// <summary>
 /// Begins executing a request based upon the current execution state.
 /// </summary>
 /// <remarks>Does not check preconditions.</remarks>
 private void InternalBeginExecuteRequest(AsyncExecutionState state)
 {
     state.CurrentRequest.BeginGetResponse(InternalEndExecuteRequest, state);
 }
Пример #7
0
        /// <summary>
        /// Handles a failed request, and tries to fix it if possible.
        /// </summary>
        /// <remarks>
        /// Can not throw an exception.
        /// </remarks>
        /// <returns>
        /// Returns true if the request was handled and is being retried.
        /// Returns false if the request could not be retried.
        /// </returns>
        private bool HandleFailedRequest(AsyncExecutionState state,
            WebException exception, out AsyncRequestResult asyncRequestResult)
        {
            try
            {
                RequestError error = null;
                // Try to get an error response object.
                if (exception.Response != null)
                {
                    IResponse errorResponse = new Response(exception.Response);
                    error = Service.DeserializeError(errorResponse);
                }

                // Try to handle the response somehow.
                if (SupportsRetry && state.Try < MaximumRetries)
                {
                    // Wait some time before sending another request.
                    Thread.Sleep((int)state.WaitTime);
                    state.WaitTime *= RetryWaitTimeIncreaseFactor;
                    state.Try++;

                    foreach (IErrorResponseHandler handler in GetErrorResponseHandlers())
                    {
                        if (handler.CanHandleErrorResponse(exception, error))
                        {
                            state.CurrentRequest = CreateWebRequest();
                            // The provided handler was able to handle this error. Retry sending the request.
                            handler.HandleErrorResponse(exception, error, state.CurrentRequest);
                            logger.Warning("Retrying request [{0}]", this);
                            InternalBeginExecuteRequest(state);
                            // Signal that this begin/end request pair has no result because it has been retried.
                            asyncRequestResult = null;
                            return true;
                        }
                    }
                }

                // Retrieve additional information about the http response (if applicable).
                HttpStatusCode status = 0;
                HttpWebResponse httpResponse = exception.Response as HttpWebResponse;
                if (httpResponse != null)
                {
                    status = httpResponse.StatusCode;
                }

                // We were unable to handle the exception. Throw it wrapped in a GoogleApiRequestException.
                asyncRequestResult = new AsyncRequestResult(
                    new GoogleApiRequestException(Service, this, error, exception) { HttpStatusCode = status });
            }
            catch (Exception ex)
            {
                asyncRequestResult = new AsyncRequestResult(
                    new GoogleApiRequestException(Service, this, null, ex));
            }
            return false;
        }
Пример #8
0
        /// <summary>
        /// Handles a failed request, and tries to fix it if possible.
        /// </summary>
        /// <remarks>
        /// Can not throw an exception.
        /// </remarks>
        /// <returns>
        /// Returns true if the request was handled and is being retried.
        /// Returns false if the request could not be retried.
        /// </returns>
        private bool HandleFailedRequest(AsyncExecutionState state,
                                         WebException exception, out AsyncRequestResult asyncRequestResult)
        {
            try
            {
                RequestError error = null;
                // Try to get an error response object.
                if (exception.Response != null)
                {
                    IResponse errorResponse = new Response(exception.Response);
                    error = Service.DeserializeError(errorResponse);
                }

                // Try to handle the response somehow.
                if (SupportsRetry && state.Try < MaximumRetries)
                {
                    // Wait some time before sending another request.
                    Thread.Sleep((int)state.WaitTime);
                    state.WaitTime *= RetryWaitTimeIncreaseFactor;
                    state.Try++;

                    foreach (IErrorResponseHandler handler in GetErrorResponseHandlers())
                    {
                        if (handler.CanHandleErrorResponse(exception, error))
                        {
                            // The provided handler was able to handle this error. Retry sending the request.
                            handler.HandleErrorResponse(exception, error, state.CurrentRequest);
                            logger.Warning("Retrying request [{0}]", this);

                            // Begin a new request and when it is completed being assembled, execute it
                            // asynchronously.
                            state.CurrentRequest = CreateWebRequest((request) =>
                            {
                                InternalBeginExecuteRequest(state);
                            });
                            // Signal that this begin/end request pair has no result because it has been retried.
                            asyncRequestResult = null;
                            return(true);
                        }
                    }
                }

                // Retrieve additional information about the http response (if applicable).
                HttpStatusCode  status       = 0;
                HttpWebResponse httpResponse = exception.Response as HttpWebResponse;
                if (httpResponse != null)
                {
                    status = httpResponse.StatusCode;
                }

                // We were unable to handle the exception. Throw it wrapped in a GoogleApiRequestException.
                asyncRequestResult = new AsyncRequestResult(
                    new GoogleApiRequestException(Service, this, error, exception)
                {
                    HttpStatusCode = status
                });
            }
            catch (Exception)
            {
                asyncRequestResult = new AsyncRequestResult(
                    new GoogleApiRequestException(Service, this, null, exception));
            }
            return(false);
        }
Пример #9
0
 /// <summary>
 /// Begins executing a request based upon the current execution state.
 /// </summary>
 /// <remarks>Does not check preconditions.</remarks>
 private void InternalBeginExecuteRequest(AsyncExecutionState state)
 {
     state.CurrentRequest.BeginGetResponse(InternalEndExecuteRequest, state);
 }
Пример #10
0
        /// <summary>
        /// Executes the request asynchronously, and calls the specified delegate once done.
        /// </summary>
        /// <param name="responseHandler">The method to call once a response has been received.</param>
        public void ExecuteRequestAsync(Action<IAsyncRequestResult> responseHandler)
        {
            // Validate the input.
            var validator = new MethodValidator(Method, Parameters);
            if (validator.ValidateAllParameters() == false)
            {
                throw new InvalidOperationException("Request parameter validation failed for [" + this + "]");
            }

            // Begin a new request and when it is completed being assembled, execute it asynchronously.
            CreateWebRequest((request) =>
            {
                // When the request is completed constructing, execute it.
                var state = new AsyncExecutionState()
                {
                    ResponseHandler = responseHandler,
                    Try = 1,
                    WaitTime = RetryInitialWaitTime,
                    CurrentRequest = request
                };
                InternalBeginExecuteRequest(state);
            });
        }