Example #1
0
        /// <summary>
        /// Executes this request.
        /// </summary>
        /// <returns>Service response.</returns>
        internal object InternalExecute()
        {
            IEwsHttpWebRequest  request;
            IEwsHttpWebResponse response = this.ValidateAndEmitRequest(out request);

            return(this.ReadResponse(response));
        }
Example #2
0
        /// <summary>
        /// Reads the response with error handling
        /// </summary>
        /// <param name="response">The response.</param>
        /// <returns>Service response.</returns>
        private object ReadResponse(IEwsHttpWebResponse response)
        {
            object serviceResponse;

            try
            {
                this.Service.ProcessHttpResponseHeaders(TraceFlags.EwsResponseHttpHeaders, response);

                // If tracing is enabled, we read the entire response into a MemoryStream so that we
                // can pass it along to the ITraceListener. Then we parse the response from the
                // MemoryStream.
                if (this.Service.IsTraceEnabledFor(TraceFlags.EwsResponse))
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (Stream serviceResponseStream = ServiceRequestBase.GetResponseStream(response))
                        {
                            // Copy response to in-memory stream and reset position to start.
                            EwsUtilities.CopyStream(serviceResponseStream, memoryStream);
                            memoryStream.Position = 0;
                        }

                        this.TraceResponseXml(response, memoryStream);

                        serviceResponse = this.ReadResponseXml(memoryStream, response.Headers);
                    }
                }
                else
                {
                    using (Stream responseStream = ServiceRequestBase.GetResponseStream(response))
                    {
                        serviceResponse = this.ReadResponseXml(responseStream, response.Headers);
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Response != null)
                {
                    IEwsHttpWebResponse exceptionResponse = this.Service.HttpWebRequestFactory.CreateExceptionResponse(e);
                    this.Service.ProcessHttpResponseHeaders(TraceFlags.EwsResponseHttpHeaders, exceptionResponse);
                }

                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, e.Message), e);
            }
            catch (IOException e)
            {
                // Wrap exception.
                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, e.Message), e);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return(serviceResponse);
        }
Example #3
0
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <param name="readTimeout">read timeout in milliseconds</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response, int readTimeout)
        {
            Stream responseStream = response.GetResponseStream();

            responseStream.ReadTimeout = readTimeout;
            return(WrapStream(responseStream, response.ContentEncoding));
        }
 /// <summary>
 /// Determines whether response is a redirection.
 /// </summary>
 /// <param name="httpWebResponse">The HTTP web response.</param>
 /// <returns>True if redirection response.</returns>
 internal static bool IsRedirectionResponse(IEwsHttpWebResponse httpWebResponse)
 {
     return (httpWebResponse.StatusCode == HttpStatusCode.Redirect) ||
            (httpWebResponse.StatusCode == HttpStatusCode.Moved) ||
            (httpWebResponse.StatusCode == HttpStatusCode.RedirectKeepVerb) ||
            (httpWebResponse.StatusCode == HttpStatusCode.RedirectMethod);
 }
Example #5
0
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response)
        {
            string contentEncoding = response.ContentEncoding;
            Stream responseStream  = response.GetResponseStream();

            return(WrapStream(responseStream, response.ContentEncoding));
        }
        /// <summary>
        /// Processes an HTTP error response
        /// </summary>
        /// <param name="httpWebResponse">The HTTP web response.</param>
        /// <param name="webException">The web exception.</param>
        /// <param name="responseHeadersTraceFlag">The trace flag for response headers.</param>
        /// <param name="responseTraceFlag">The trace flag for responses.</param>
        /// <remarks>
        /// This method doesn't handle 500 ISE errors. This is handled by the caller since
        /// 500 ISE typically indicates that a SOAP fault has occurred and the handling of
        /// a SOAP fault is currently service specific.
        /// </remarks>
        internal void InternalProcessHttpErrorResponse(
            IEwsHttpWebResponse httpWebResponse,
            WebException webException,
            TraceFlags responseHeadersTraceFlag,
            TraceFlags responseTraceFlag)
        {
            EwsUtilities.Assert(
                httpWebResponse.StatusCode != HttpStatusCode.InternalServerError,
                "ExchangeServiceBase.InternalProcessHttpErrorResponse",
                "InternalProcessHttpErrorResponse does not handle 500 ISE errors, the caller is supposed to handle this.");

            this.ProcessHttpResponseHeaders(responseHeadersTraceFlag, httpWebResponse);

            // Deal with new HTTP error code indicating that account is locked.
            // The "unlock" URL is returned as the status description in the response.
            if (httpWebResponse.StatusCode == ExchangeServiceBase.AccountIsLocked)
            {
                string location = httpWebResponse.StatusDescription;

                Uri accountUnlockUrl = null;
                if (Uri.IsWellFormedUriString(location, UriKind.Absolute))
                {
                    accountUnlockUrl = new Uri(location);
                }

                this.TraceMessage(responseTraceFlag, string.Format("Account is locked. Unlock URL is {0}", accountUnlockUrl));

                throw new AccountIsLockedException(
                          string.Format(Strings.AccountIsLocked, accountUnlockUrl),
                          accountUnlockUrl,
                          webException);
            }
        }
 /// <summary>
 /// Determines whether response is a redirection.
 /// </summary>
 /// <param name="httpWebResponse">The HTTP web response.</param>
 /// <returns>True if redirection response.</returns>
 internal static bool IsRedirectionResponse(IEwsHttpWebResponse httpWebResponse)
 {
     return((httpWebResponse.StatusCode == HttpStatusCode.Redirect) ||
            (httpWebResponse.StatusCode == HttpStatusCode.Moved) ||
            (httpWebResponse.StatusCode == HttpStatusCode.RedirectKeepVerb) ||
            (httpWebResponse.StatusCode == HttpStatusCode.RedirectMethod));
 }
        /// <summary>
        /// Executes this request.
        /// </summary>
        /// <returns>Service response.</returns>
        internal async Task <object> InternalExecuteAsync()
        {
            IEwsHttpWebRequest  request;
            IEwsHttpWebResponse response = await this.ValidateAndEmitRequestAsync(out request);

            return(this.ReadResponse(response));
        }
Example #9
0
        /// <summary>
        /// Exectures the request.
        /// </summary>
        internal void InternalExecute()
        {
            lock (this.lockObject)
            {
                this.response = this.ValidateAndEmitRequest(out this.request);

                this.InternalOnConnect();
            }
        }
Example #10
0
        /// <summary>
        /// Ends executing this async request.
        /// </summary>
        /// <param name="asyncResult">The async result</param>
        /// <returns>Service response object.</returns>
        internal object EndInternalExecute(IAsyncResult asyncResult)
        {
            // We have done enough validation before
            AsyncRequestResult asyncRequestResult = (AsyncRequestResult)asyncResult;

            IEwsHttpWebResponse response = this.EndGetEwsHttpWebResponse(asyncRequestResult.WebRequest, asyncRequestResult.WebAsyncResult);

            return(this.ReadResponse(response));
        }
 /// <summary>
 /// Traces the HTTP response headers.
 /// </summary>
 /// <param name="traceType">Kind of trace entry.</param>
 /// <param name="response">The response.</param>
 private void TraceHttpResponseHeaders(TraceFlags traceType, IEwsHttpWebResponse response)
 {
     if (this.IsTraceEnabledFor(traceType))
     {
         string traceTypeStr    = traceType.ToString();
         string headersAsString = EwsUtilities.FormatHttpResponseHeaders(response);
         string logMessage      = EwsUtilities.FormatLogMessage(traceTypeStr, headersAsString);
         this.TraceListener.Trace(traceTypeStr, logMessage);
     }
 }
        /// <summary>
        /// Exectures the request.
        /// </summary>
        internal void InternalExecute()
        {
            lock (this.lockObject)
            {
                var tuple = this.ValidateAndEmitRequest().Result;
                this.request  = tuple.Item1;
                this.response = tuple.Item2;

                this.InternalOnConnect();
            }
        }
Example #13
0
 /// <summary>
 /// Traces the response.  This should only be used for synchronous requests, or synchronous situations
 /// (such as a WebException on an asynchrounous request).
 /// </summary>
 /// <param name="response">The response.</param>
 /// <param name="memoryStream">The response content in a MemoryStream.</param>
 protected void TraceResponseXml(IEwsHttpWebResponse response, MemoryStream memoryStream)
 {
     if (!string.IsNullOrEmpty(response.ContentType) &&
         (response.ContentType.StartsWith("text/", StringComparison.OrdinalIgnoreCase) ||
          response.ContentType.StartsWith("application/soap", StringComparison.OrdinalIgnoreCase)))
     {
         this.Service.TraceXml(TraceFlags.EwsResponse, memoryStream);
     }
     else
     {
         this.Service.TraceMessage(TraceFlags.EwsResponse, "Non-textual response");
     }
 }
Example #14
0
        private async Task <IEwsHttpWebResponse> ValidateAndEmitRequestInternalAsync(IEwsHttpWebRequest request)
        {
            DateTime startTime = DateTime.UtcNow;

            IEwsHttpWebResponse response = null;

            try
            {
                response = await this.GetEwsHttpWebResponseAsync(request);
            }
            finally
            {
                if (this.service.SendClientLatencies)
                {
                    int    clientSideLatency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                    string requestId         = string.Empty;
                    string soapAction        = this.GetType().Name.Replace("Request", string.Empty);

                    if (response != null && response.Headers != null)
                    {
                        foreach (string requestIdHeader in ServiceRequestBase.RequestIdResponseHeaders)
                        {
                            string requestIdValue = response.Headers.Get(requestIdHeader);
                            if (!string.IsNullOrEmpty(requestIdValue))
                            {
                                requestId = requestIdValue;
                                break;
                            }
                        }
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.Append("MessageId=");
                    sb.Append(requestId);
                    sb.Append(",ResponseTime=");
                    sb.Append(clientSideLatency);
                    sb.Append(",SoapAction=");
                    sb.Append(soapAction);
                    sb.Append(";");

                    lock (clientStatisticsCache)
                    {
                        clientStatisticsCache.Add(sb.ToString());
                    }
                }
            }

            return(response);
        }
        /// <summary>
        /// Processes the web exception.
        /// </summary>
        /// <param name="webException">The web exception.</param>
        private void ProcessWebException(WebException webException)
        {
            if (webException.Response != null)
            {
                IEwsHttpWebResponse httpWebResponse = this.Service.HttpWebRequestFactory.CreateExceptionResponse(webException);
                SoapFaultDetails    soapFaultDetails;

                if (httpWebResponse.StatusCode == HttpStatusCode.InternalServerError)
                {
                    // If tracing is enabled, we read the entire response into a MemoryStream so that we
                    // can pass it along to the ITraceListener. Then we parse the response from the
                    // MemoryStream.
                    if (this.Service.IsTraceEnabledFor(TraceFlags.AutodiscoverRequest))
                    {
                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            using (Stream serviceResponseStream = AutodiscoverRequest.GetResponseStream(httpWebResponse))
                            {
                                // Copy response to in-memory stream and reset position to start.
                                EwsUtilities.CopyStream(serviceResponseStream, memoryStream);
                                memoryStream.Position = 0;
                            }

                            this.Service.TraceResponse(httpWebResponse, memoryStream);

                            EwsXmlReader reader = new EwsXmlReader(memoryStream);
                            soapFaultDetails = this.ReadSoapFault(reader);
                        }
                    }
                    else
                    {
                        using (Stream stream = AutodiscoverRequest.GetResponseStream(httpWebResponse))
                        {
                            EwsXmlReader reader = new EwsXmlReader(stream);
                            soapFaultDetails = this.ReadSoapFault(reader);
                        }
                    }

                    if (soapFaultDetails != null)
                    {
                        throw new ServiceResponseException(new ServiceResponse(soapFaultDetails));
                    }
                }
                else
                {
                    this.Service.ProcessHttpErrorResponse(httpWebResponse, webException);
                }
            }
        }
        /// <summary>
        /// Traces the response.  This should only be used for synchronous requests, or synchronous situations
        /// (such as a WebException on an asynchrounous request).
        /// </summary>
        /// <param name="response">The response.</param>
        /// <param name="memoryStream">The response content in a MemoryStream.</param>
        protected void TraceResponseJson(IEwsHttpWebResponse response, MemoryStream memoryStream)
        {
            JsonObject jsonResponse = new JsonParser(memoryStream).Parse();

            using (MemoryStream responseStream = new MemoryStream())
            {
                jsonResponse.SerializeToJson(responseStream, this.Service.TraceEnablePrettyPrinting);

                responseStream.Position = 0;

                using (StreamReader responseReader = new StreamReader(responseStream))
                {
                    this.Service.TraceMessage(TraceFlags.EwsResponse, responseReader.ReadToEnd());
                }
            }

            memoryStream.Seek(0, SeekOrigin.Begin);
        }
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response)
        {
            string contentEncoding = response.ContentEncoding;
            Stream responseStream  = response.GetResponseStream();

            if (contentEncoding.ToLowerInvariant().Contains("gzip"))
            {
                return(new GZipStream(responseStream, CompressionMode.Decompress));
            }
            else if (contentEncoding.ToLowerInvariant().Contains("deflate"))
            {
                return(new DeflateStream(responseStream, CompressionMode.Decompress));
            }
            else
            {
                return(responseStream);
            }
        }
        /// <summary>
        /// Create a redirection response.
        /// </summary>
        /// <param name="httpWebResponse">The HTTP web response.</param>
        private AutodiscoverResponse CreateRedirectionResponse(IEwsHttpWebResponse httpWebResponse)
        {
            string location = httpWebResponse.Headers[HttpResponseHeader.Location];

            if (!string.IsNullOrEmpty(location))
            {
                try
                {
                    Uri redirectionUri = new Uri(this.Url, location);
                    if ((redirectionUri.Scheme == /*Uri.UriSchemeHttp*/ "http") || (redirectionUri.Scheme == /*Uri.UriSchemeHttps*/ "https"))
                    {
                        AutodiscoverResponse response = this.CreateServiceResponse();
                        response.ErrorCode      = AutodiscoverErrorCode.RedirectUrl;
                        response.RedirectionUrl = redirectionUri;
                        return(response);
                    }

                    this.Service.TraceMessage(
                        TraceFlags.AutodiscoverConfiguration,
                        string.Format("Invalid redirection URL '{0}' returned by Autodiscover service.", redirectionUri));
                }
                catch (UriFormatException)
                {
                    this.Service.TraceMessage(
                        TraceFlags.AutodiscoverConfiguration,
                        string.Format("Invalid redirection location '{0}' returned by Autodiscover service.", location));
                }
            }
            else
            {
                this.Service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    "Redirection response returned by Autodiscover service without redirection location.");
            }

            return(null);
        }
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response)
        {
            string contentEncoding = response.ContentEncoding;
            Stream responseStream = response.GetResponseStream();

            if (contentEncoding.ToLowerInvariant().Contains("gzip"))
            {
                return new GZipStream(responseStream, CompressionMode.Decompress);
            }
            else if (contentEncoding.ToLowerInvariant().Contains("deflate"))
            {
                return new DeflateStream(responseStream, CompressionMode.Decompress);
            }
            else
            {
                return responseStream;
            }
        }
Example #20
0
        /// <summary>
        /// Processes the web exception.
        /// </summary>
        /// <param name="webException">The web exception.</param>
        private void ProcessWebException(WebException webException)
        {
            if (webException.Response != null)
            {
                IEwsHttpWebResponse httpWebResponse  = this.Service.HttpWebRequestFactory.CreateExceptionResponse(webException);
                SoapFaultDetails    soapFaultDetails = null;

                if (httpWebResponse.StatusCode == HttpStatusCode.InternalServerError)
                {
                    this.Service.ProcessHttpResponseHeaders(TraceFlags.EwsResponseHttpHeaders, httpWebResponse);

                    // If tracing is enabled, we read the entire response into a MemoryStream so that we
                    // can pass it along to the ITraceListener. Then we parse the response from the
                    // MemoryStream.
                    if (this.Service.IsTraceEnabledFor(TraceFlags.EwsResponse))
                    {
                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            using (Stream serviceResponseStream = ServiceRequestBase.GetResponseStream(httpWebResponse))
                            {
                                // Copy response to in-memory stream and reset position to start.
                                EwsUtilities.CopyStream(serviceResponseStream, memoryStream);
                                memoryStream.Position = 0;
                            }

                            this.TraceResponseXml(httpWebResponse, memoryStream);

                            EwsServiceXmlReader reader = new EwsServiceXmlReader(memoryStream, this.Service);
                            soapFaultDetails = this.ReadSoapFault(reader);
                        }
                    }
                    else
                    {
                        using (Stream stream = ServiceRequestBase.GetResponseStream(httpWebResponse))
                        {
                            EwsServiceXmlReader reader = new EwsServiceXmlReader(stream, this.Service);
                            soapFaultDetails = this.ReadSoapFault(reader);
                        }
                    }

                    if (soapFaultDetails != null)
                    {
                        switch (soapFaultDetails.ResponseCode)
                        {
                        case ServiceError.ErrorInvalidServerVersion:
                            throw new ServiceVersionException(Strings.ServerVersionNotSupported);

                        case ServiceError.ErrorSchemaValidation:
                            // If we're talking to an E12 server (8.00.xxxx.xxx), a schema validation error is the same as a version mismatch error.
                            // (Which only will happen if we send a request that's not valid for E12).
                            if ((this.Service.ServerInfo != null) &&
                                (this.Service.ServerInfo.MajorVersion == 8) && (this.Service.ServerInfo.MinorVersion == 0))
                            {
                                throw new ServiceVersionException(Strings.ServerVersionNotSupported);
                            }

                            break;

                        case ServiceError.ErrorIncorrectSchemaVersion:
                            // This shouldn't happen. It indicates that a request wasn't valid for the version that was specified.
                            EwsUtilities.Assert(
                                false,
                                "ServiceRequestBase.ProcessWebException",
                                "Exchange server supports requested version but request was invalid for that version");
                            break;

                        case ServiceError.ErrorServerBusy:
                            throw new ServerBusyException(new ServiceResponse(soapFaultDetails));

                        default:
                            // Other error codes will be reported as remote error
                            break;
                        }

                        // General fall-through case: throw a ServiceResponseException
                        throw new ServiceResponseException(new ServiceResponse(soapFaultDetails));
                    }
                }
                else
                {
                    this.Service.ProcessHttpErrorResponse(httpWebResponse, webException);
                }
            }
        }
Example #21
0
        /// <summary>
        /// Validates request parameters, and emits the request to the server.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The response returned by the server.</returns>
        protected IEwsHttpWebResponse ValidateAndEmitRequest(out IEwsHttpWebRequest request)
        {
            this.Validate();

            request = this.BuildEwsHttpWebRequest();

            if (this.service.SendClientLatencies)
            {
                string clientStatisticsToAdd = null;

                lock (clientStatisticsCache)
                {
                    if (clientStatisticsCache.Count > 0)
                    {
                        clientStatisticsToAdd = clientStatisticsCache[0];
                        clientStatisticsCache.RemoveAt(0);
                    }
                }

                if (!string.IsNullOrEmpty(clientStatisticsToAdd))
                {
                    if (request.Headers[ClientStatisticsRequestHeader] != null)
                    {
                        request.Headers[ClientStatisticsRequestHeader] =
                            request.Headers[ClientStatisticsRequestHeader]
                            + clientStatisticsToAdd;
                    }
                    else
                    {
                        request.Headers.Add(
                            ClientStatisticsRequestHeader,
                            clientStatisticsToAdd);
                    }
                }
            }

            DateTime            startTime = DateTime.UtcNow;
            IEwsHttpWebResponse response  = null;

            try
            {
                response = this.GetEwsHttpWebResponse(request);
            }
            finally
            {
                if (this.service.SendClientLatencies)
                {
                    int    clientSideLatency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                    string requestId         = string.Empty;
                    string soapAction        = this.GetType().Name.Replace("Request", string.Empty);

                    if (response != null && response.Headers != null)
                    {
                        foreach (string requestIdHeader in ServiceRequestBase.RequestIdResponseHeaders)
                        {
                            string requestIdValue = response.Headers.Get(requestIdHeader);
                            if (!string.IsNullOrEmpty(requestIdValue))
                            {
                                requestId = requestIdValue;
                                break;
                            }
                        }
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.Append("MessageId=");
                    sb.Append(requestId);
                    sb.Append(",ResponseTime=");
                    sb.Append(clientSideLatency);
                    sb.Append(",SoapAction=");
                    sb.Append(soapAction);
                    sb.Append(";");

                    lock (clientStatisticsCache)
                    {
                        clientStatisticsCache.Add(sb.ToString());
                    }
                }
            }

            return(response);
        }
        /// <summary>
        /// Processes an HTTP error response
        /// </summary>
        /// <param name="httpWebResponse">The HTTP web response.</param>
        /// <param name="webException">The web exception.</param>
        /// <param name="responseHeadersTraceFlag">The trace flag for response headers.</param>
        /// <param name="responseTraceFlag">The trace flag for responses.</param>
        /// <remarks>
        /// This method doesn't handle 500 ISE errors. This is handled by the caller since
        /// 500 ISE typically indicates that a SOAP fault has occurred and the handling of
        /// a SOAP fault is currently service specific.
        /// </remarks>
        internal void InternalProcessHttpErrorResponse(
                            IEwsHttpWebResponse httpWebResponse,
                            WebException webException,
                            TraceFlags responseHeadersTraceFlag,
                            TraceFlags responseTraceFlag)
        {
            EwsUtilities.Assert(
                httpWebResponse.StatusCode != HttpStatusCode.InternalServerError,
                "ExchangeServiceBase.InternalProcessHttpErrorResponse",
                "InternalProcessHttpErrorResponse does not handle 500 ISE errors, the caller is supposed to handle this.");

            this.ProcessHttpResponseHeaders(responseHeadersTraceFlag, httpWebResponse);

            // Deal with new HTTP error code indicating that account is locked.
            // The "unlock" URL is returned as the status description in the response.
            if (httpWebResponse.StatusCode == ExchangeServiceBase.AccountIsLocked)
            {
                string location = httpWebResponse.StatusDescription;

                Uri accountUnlockUrl = null;
                if (Uri.IsWellFormedUriString(location, UriKind.Absolute))
                {
                    accountUnlockUrl = new Uri(location);
                }

                this.TraceMessage(responseTraceFlag, string.Format("Account is locked. Unlock URL is {0}", accountUnlockUrl));

                throw new AccountIsLockedException(
                    string.Format(Strings.AccountIsLocked, accountUnlockUrl),
                    accountUnlockUrl,
                    webException);
            }
        }
 /// <summary>
 /// Processes an HTTP error response.
 /// </summary>
 /// <param name="httpWebResponse">The HTTP web response.</param>
 /// <param name="webException">The web exception.</param>
 internal abstract void ProcessHttpErrorResponse(IEwsHttpWebResponse httpWebResponse, WebException webException);
        /// <summary>
        /// Traces the HTTP response headers.
        /// </summary>
        /// <param name="traceType">Kind of trace entry.</param>
        /// <param name="response">The response.</param>
        internal void ProcessHttpResponseHeaders(TraceFlags traceType, IEwsHttpWebResponse response)
        {
            this.TraceHttpResponseHeaders(traceType, response);

            this.SaveHttpResponseHeaders(response.Headers);
        }
        /// <summary>
        /// Traces the HTTP response headers.
        /// </summary>
        /// <param name="traceType">Kind of trace entry.</param>
        /// <param name="response">The response.</param>
        internal void ProcessHttpResponseHeaders(TraceFlags traceType, IEwsHttpWebResponse response)
        {
            this.TraceHttpResponseHeaders(traceType, response);

            this.SaveHttpResponseHeaders(response.Headers);
        }
        /// <summary>
        /// Create a redirection response.
        /// </summary>
        /// <param name="httpWebResponse">The HTTP web response.</param>
        private AutodiscoverResponse CreateRedirectionResponse(IEwsHttpWebResponse httpWebResponse)
        {
            string location = httpWebResponse.Headers[HttpResponseHeader.Location];
            if (!string.IsNullOrEmpty(location))
            {
                try
                {
                    Uri redirectionUri = new Uri(this.Url, location);
                    if ((redirectionUri.Scheme == Uri.UriSchemeHttp) || (redirectionUri.Scheme == Uri.UriSchemeHttps))
                    {
                        AutodiscoverResponse response = this.CreateServiceResponse();
                        response.ErrorCode = AutodiscoverErrorCode.RedirectUrl;
                        response.RedirectionUrl = redirectionUri;
                        return response;
                    }

                    this.Service.TraceMessage(
                        TraceFlags.AutodiscoverConfiguration,
                        string.Format("Invalid redirection URL '{0}' returned by Autodiscover service.", redirectionUri));
                }
                catch (UriFormatException)
                {
                    this.Service.TraceMessage(
                        TraceFlags.AutodiscoverConfiguration,
                        string.Format("Invalid redirection location '{0}' returned by Autodiscover service.", location));
                }
            }
            else
            {
                this.Service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    "Redirection response returned by Autodiscover service without redirection location.");
            }

            return null;
        }
        /// <summary>
        /// Exectures the request.
        /// </summary>
        internal void InternalExecute()
        {
            lock (this.lockObject)
            {
                this.response = this.ValidateAndEmitRequest(out this.request);

                this.InternalOnConnect();
            }
        }
 /// <summary>
 /// Traces the response.  This should only be used for synchronous requests, or synchronous situations
 /// (such as a WebException on an asynchrounous request).
 /// </summary>
 /// <param name="response">The response.</param>
 /// <param name="memoryStream">The response content in a MemoryStream.</param>
 protected void TraceResponseXml(IEwsHttpWebResponse response, MemoryStream memoryStream)
 {
     if (!string.IsNullOrEmpty(response.ContentType) &&
         (response.ContentType.StartsWith("text/", StringComparison.OrdinalIgnoreCase) ||
          response.ContentType.StartsWith("application/soap", StringComparison.OrdinalIgnoreCase)))
     {
         this.Service.TraceXml(TraceFlags.EwsResponse, memoryStream);
     }
     else
     {
         this.Service.TraceMessage(TraceFlags.EwsResponse, "Non-textual response");
     }
 }
        /// <summary>
        /// Reads the response with error handling
        /// </summary>
        /// <param name="response">The response.</param>
        /// <returns>Service response.</returns>
        private object ReadResponse(IEwsHttpWebResponse response)
        {
            object serviceResponse;

            try
            {
                this.Service.ProcessHttpResponseHeaders(TraceFlags.EwsResponseHttpHeaders, response);

                // If tracing is enabled, we read the entire response into a MemoryStream so that we
                // can pass it along to the ITraceListener. Then we parse the response from the 
                // MemoryStream.
                if (this.Service.IsTraceEnabledFor(TraceFlags.EwsResponse))
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (Stream serviceResponseStream = ServiceRequestBase.GetResponseStream(response))
                        {
                            // Copy response to in-memory stream and reset position to start.
                            EwsUtilities.CopyStream(serviceResponseStream, memoryStream);
                            memoryStream.Position = 0;
                        }

                        this.TraceResponseXml(response, memoryStream);

                        serviceResponse = this.ReadResponseXml(memoryStream, response.Headers);
                    }
                }
                else
                {
                    using (Stream responseStream = ServiceRequestBase.GetResponseStream(response))
                    {
                        serviceResponse = this.ReadResponseXml(responseStream, response.Headers);
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Response != null)
                {
                    IEwsHttpWebResponse exceptionResponse = this.Service.HttpWebRequestFactory.CreateExceptionResponse(e);
                    this.Service.ProcessHttpResponseHeaders(TraceFlags.EwsResponseHttpHeaders, exceptionResponse);
                }

                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, e.Message), e);
            }
            catch (IOException e)
            {
                // Wrap exception.
                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, e.Message), e);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return serviceResponse;
        }
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <param name="readTimeout">read timeout in milliseconds</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response, int readTimeout)
        {
            Stream responseStream = response.GetResponseStream();

            responseStream.ReadTimeout = readTimeout;
            return WrapStream(responseStream, response.ContentEncoding);
        }
        /// <summary>
        /// Executes this instance.
        /// </summary>
        /// <returns></returns>
        internal AutodiscoverResponse InternalExecute()
        {
            this.Validate();

            try
            {
                IEwsHttpWebRequest request = this.Service.PrepareHttpWebRequestForUrl(this.Url);

                this.Service.TraceHttpRequestHeaders(TraceFlags.AutodiscoverRequestHttpHeaders, request);

                bool needSignature = this.Service.Credentials != null && this.Service.Credentials.NeedSignature;
                bool needTrace     = this.Service.IsTraceEnabledFor(TraceFlags.AutodiscoverRequest);

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (EwsServiceXmlWriter writer = new EwsServiceXmlWriter(this.Service, memoryStream))
                    {
                        writer.RequireWSSecurityUtilityNamespace = needSignature;
                        this.WriteSoapRequest(
                            this.Url,
                            writer);
                    }

                    if (needSignature)
                    {
                        this.service.Credentials.Sign(memoryStream);
                    }

                    if (needTrace)
                    {
                        memoryStream.Position = 0;
                        this.Service.TraceXml(TraceFlags.AutodiscoverRequest, memoryStream);
                    }

                    request.SetRequestStream(memoryStream);
                }


                using (IEwsHttpWebResponse webResponse = request.GetResponse())
                {
                    if (AutodiscoverRequest.IsRedirectionResponse(webResponse))
                    {
                        AutodiscoverResponse response = this.CreateRedirectionResponse(webResponse);
                        if (response != null)
                        {
                            return(response);
                        }
                        else
                        {
                            throw new ServiceRemoteException(Strings.InvalidRedirectionResponseReturned);
                        }
                    }

                    using (Stream responseStream = AutodiscoverRequest.GetResponseStream(webResponse))
                    {
                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            // Copy response stream to in-memory stream and reset to start
                            EwsUtilities.CopyStream(responseStream, memoryStream);
                            memoryStream.Position = 0;

                            this.Service.TraceResponse(webResponse, memoryStream);

                            EwsXmlReader ewsXmlReader = new EwsXmlReader(memoryStream);

                            // WCF may not generate an XML declaration.
                            ewsXmlReader.Read();
                            if (ewsXmlReader.NodeType == XmlNodeType.XmlDeclaration)
                            {
                                ewsXmlReader.ReadStartElement(XmlNamespace.Soap, XmlElementNames.SOAPEnvelopeElementName);
                            }
                            else if ((ewsXmlReader.NodeType != XmlNodeType.Element) || (ewsXmlReader.LocalName != XmlElementNames.SOAPEnvelopeElementName) || (ewsXmlReader.NamespaceUri != EwsUtilities.GetNamespaceUri(XmlNamespace.Soap)))
                            {
                                throw new ServiceXmlDeserializationException(Strings.InvalidAutodiscoverServiceResponse);
                            }

                            this.ReadSoapHeaders(ewsXmlReader);

                            AutodiscoverResponse response = this.ReadSoapBody(ewsXmlReader);

                            ewsXmlReader.ReadEndElement(XmlNamespace.Soap, XmlElementNames.SOAPEnvelopeElementName);

                            if (response.ErrorCode == AutodiscoverErrorCode.NoError)
                            {
                                return(response);
                            }
                            else
                            {
                                throw new AutodiscoverResponseException(response.ErrorCode, response.ErrorMessage);
                            }
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
                {
                    IEwsHttpWebResponse httpWebResponse = this.Service.HttpWebRequestFactory.CreateExceptionResponse(ex);

                    if (AutodiscoverRequest.IsRedirectionResponse(httpWebResponse))
                    {
                        this.Service.ProcessHttpResponseHeaders(
                            TraceFlags.AutodiscoverResponseHttpHeaders,
                            httpWebResponse);

                        AutodiscoverResponse response = this.CreateRedirectionResponse(httpWebResponse);
                        if (response != null)
                        {
                            return(response);
                        }
                    }
                    else
                    {
                        this.ProcessWebException(ex);
                    }
                }

                // Wrap exception if the above code block didn't throw
                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, ex.Message), ex);
            }
            catch (XmlException ex)
            {
                this.Service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    string.Format("XML parsing error: {0}", ex.Message));

                // Wrap exception
                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, ex.Message), ex);
            }
            catch (IOException ex)
            {
                this.Service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    string.Format("I/O error: {0}", ex.Message));

                // Wrap exception
                throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, ex.Message), ex);
            }
        }
 /// <summary>
 /// Processes an HTTP error response.
 /// </summary>
 /// <param name="httpWebResponse">The HTTP web response.</param>
 /// <param name="webException">The web exception.</param>
 internal abstract void ProcessHttpErrorResponse(IEwsHttpWebResponse httpWebResponse, WebException webException);
Example #33
0
        /// <summary>
        /// Validates request parameters, and emits the request to the server.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The response returned by the server.</returns>
        protected async Task <Tuple <IEwsHttpWebRequest, IEwsHttpWebResponse> > ValidateAndEmitRequest(CancellationToken token)
        {
            this.Validate();

            var request = await this.BuildEwsHttpWebRequest().ConfigureAwait(false);

            try
            {
                if (this.service.config.sendClientLatencies)
                {
                    string clientStatisticsToAdd = null;

                    lock (clientStatisticsCache)
                    {
                        if (clientStatisticsCache.Count > 0)
                        {
                            clientStatisticsToAdd = clientStatisticsCache[0];
                            clientStatisticsCache.RemoveAt(0);
                        }
                    }

                    if (!string.IsNullOrEmpty(clientStatisticsToAdd))
                    {
                        request.AdditionalMessageHeaders.Add(new KeyValuePair <string, IEnumerable <string> >(ClientStatisticsRequestHeader, new string[] { clientStatisticsToAdd }));
                    }
                }

                DateTime            startTime = DateTime.UtcNow;
                IEwsHttpWebResponse response  = null;

                try
                {
                    response = await this.GetEwsHttpWebResponse(request, token).ConfigureAwait(false);
                }
                finally
                {
                    if (this.service.config.sendClientLatencies)
                    {
                        int    clientSideLatency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                        string requestId         = string.Empty;
                        string soapAction        = this.GetType().Name.Replace("Request", string.Empty);

                        if (response != null && response.Headers != null)
                        {
                            foreach (string requestIdHeader in ServiceRequestBase.RequestIdResponseHeaders)
                            {
                                if (response.Headers.TryGetValues(requestIdHeader, out IEnumerable <string> values))
                                {
                                    requestId = values.First();
                                    break;
                                }
                            }
                        }

                        StringBuilder sb = new StringBuilder();
                        sb.Append("MessageId=");
                        sb.Append(requestId);
                        sb.Append(",ResponseTime=");
                        sb.Append(clientSideLatency);
                        sb.Append(",SoapAction=");
                        sb.Append(soapAction);
                        sb.Append(";");

                        lock (clientStatisticsCache)
                        {
                            clientStatisticsCache.Add(sb.ToString());
                        }
                    }
                }

                return(Tuple.Create(request, response));
            }
            catch (Exception)
            {
                request.Dispose();
                throw;
            }
        }
        /// <summary>
        /// Gets the response stream (may be wrapped with GZip/Deflate stream to decompress content)
        /// </summary>
        /// <param name="response">HttpWebResponse.</param>
        /// <returns>ResponseStream</returns>
        protected static Stream GetResponseStream(IEwsHttpWebResponse response)
        {
            string contentEncoding = response.ContentEncoding;
            Stream responseStream = response.GetResponseStream();

            return WrapStream(responseStream, response.ContentEncoding);
        }
 /// <summary>
 /// Traces the HTTP response headers.
 /// </summary>
 /// <param name="traceType">Kind of trace entry.</param>
 /// <param name="response">The response.</param>
 private void TraceHttpResponseHeaders(TraceFlags traceType, IEwsHttpWebResponse response)
 {
     if (this.IsTraceEnabledFor(traceType))
     {
         string traceTypeStr = traceType.ToString();
         string headersAsString = EwsUtilities.FormatHttpResponseHeaders(response);
         string logMessage = EwsUtilities.FormatLogMessage(traceTypeStr, headersAsString);
         this.TraceListener.Trace(traceTypeStr, logMessage);
     }
 }