/// <summary>
        /// Read SOAP body.
        /// </summary>
        /// <param name="reader">EwsXmlReader</param>
        internal AutodiscoverResponse ReadSoapBody(EwsXmlReader reader)
        {
            reader.ReadStartElement(XmlNamespace.Soap, XmlElementNames.SOAPBodyElementName);
            AutodiscoverResponse responses = this.LoadFromXml(reader);

            reader.ReadEndElement(XmlNamespace.Soap, XmlElementNames.SOAPBodyElementName);
            return(responses);
        }
        /// <summary>
        /// Loads responses from XML.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        internal AutodiscoverResponse LoadFromXml(EwsXmlReader reader)
        {
            string elementName = this.GetResponseXmlElementName();

            reader.ReadStartElement(XmlNamespace.Autodiscover, elementName);
            AutodiscoverResponse response = this.CreateServiceResponse();

            response.LoadFromXml(reader, elementName);
            return(response);
        }
        /// <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>
        /// 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);
            }
        }