SoapClientProtocol.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Web / System / Web / Services / Protocols / SoapClientProtocol.cs / 1407647 / SoapClientProtocol.cs

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

namespace System.Web.Services.Protocols { 
    using System; 
    using System.Text;
    using System.Collections; 
    using System.IO;
    using System.Reflection;
    using System.Xml.Serialization;
    using System.Xml; 
    using System.Diagnostics;
    using System.Xml.Schema; 
    using System.Web.Services.Description; 
    using System.Web.Services.Discovery;
    using System.Web.Services.Configuration; 
    using System.Net;
    using System.Security.Permissions;
    using System.Threading;
    using System.ComponentModel; 
    using System.Runtime.InteropServices;
    using System.Web.Services.Diagnostics; 
 
    internal class SoapClientType {
        Hashtable methods = new Hashtable(); 
        WebServiceBindingAttribute binding;

        internal SoapReflectedExtension[] HighPriExtensions;
        internal SoapReflectedExtension[] LowPriExtensions; 
        internal object[] HighPriExtensionInitializers;
        internal object[] LowPriExtensionInitializers; 
 
        internal string serviceNamespace;
        internal bool serviceDefaultIsEncoded; 

        internal SoapClientType(Type type) {
            this.binding = WebServiceBindingReflector.GetAttribute(type);
            if (this.binding == null) throw new InvalidOperationException(Res.GetString(Res.WebClientBindingAttributeRequired)); 
            // Note: Service namespace is taken from WebserviceBindingAttribute and not WebserviceAttribute because
            // the generated proxy does not have a WebServiceAttribute; however all have a WebServiceBindingAttribute. 
            serviceNamespace = binding.Namespace; 
            serviceDefaultIsEncoded = SoapReflector.ServiceDefaultIsEncoded(type);
            ArrayList soapMethodList = new ArrayList(); 
            ArrayList mappings = new ArrayList();
            GenerateXmlMappings(type, soapMethodList, serviceNamespace, serviceDefaultIsEncoded, mappings);
            XmlMapping[] xmlMappings = (XmlMapping[])mappings.ToArray(typeof(XmlMapping));
 
            TraceMethod caller = Tracing.On ? new TraceMethod(this, ".ctor", type) : null;
            if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceCreateSerializer), caller, new TraceMethod(typeof(XmlSerializer), "FromMappings", xmlMappings, type)); 
            XmlSerializer[] serializers = XmlSerializer.FromMappings(xmlMappings, type); 
            if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceCreateSerializer), caller);
 
            SoapExtensionTypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionTypes;
            ArrayList highPri = new ArrayList();
            ArrayList lowPri = new ArrayList();
            for (int i = 0; i < extensionTypes.Count; i++) { 
                SoapExtensionTypeElement element = extensionTypes[i];
                SoapReflectedExtension extension = new SoapReflectedExtension(extensionTypes[i].Type, null, extensionTypes[i].Priority); 
                if (extensionTypes[i].Group == PriorityGroup.High) 
                    highPri.Add(extension);
                else 
                    lowPri.Add(extension);
            }

            HighPriExtensions = (SoapReflectedExtension[]) highPri.ToArray(typeof(SoapReflectedExtension)); 
            LowPriExtensions = (SoapReflectedExtension[]) lowPri.ToArray(typeof(SoapReflectedExtension));
            Array.Sort(HighPriExtensions); 
            Array.Sort(LowPriExtensions); 
            HighPriExtensionInitializers = SoapReflectedExtension.GetInitializers(type, HighPriExtensions);
            LowPriExtensionInitializers = SoapReflectedExtension.GetInitializers(type, LowPriExtensions); 

            int count = 0;
            for (int i = 0; i < soapMethodList.Count; i++) {
                SoapReflectedMethod soapMethod = (SoapReflectedMethod)soapMethodList[i]; 
                SoapClientMethod clientMethod = new SoapClientMethod();
                clientMethod.parameterSerializer = serializers[count++]; 
                if (soapMethod.responseMappings != null) clientMethod.returnSerializer = serializers[count++]; 
                clientMethod.inHeaderSerializer = serializers[count++];
                if (soapMethod.outHeaderMappings != null) clientMethod.outHeaderSerializer = serializers[count++]; 
                clientMethod.action = soapMethod.action;
                clientMethod.oneWay = soapMethod.oneWay;
                clientMethod.rpc = soapMethod.rpc;
                clientMethod.use = soapMethod.use; 
                clientMethod.paramStyle = soapMethod.paramStyle;
                clientMethod.methodInfo = soapMethod.methodInfo; 
                clientMethod.extensions = soapMethod.extensions; 
                clientMethod.extensionInitializers = SoapReflectedExtension.GetInitializers(clientMethod.methodInfo, soapMethod.extensions);
                ArrayList inHeaders = new ArrayList(); 
                ArrayList outHeaders = new ArrayList();
                for (int j = 0; j < soapMethod.headers.Length; j++) {
                    SoapHeaderMapping mapping = new SoapHeaderMapping();
                    SoapReflectedHeader soapHeader = soapMethod.headers[j]; 
                    mapping.memberInfo = soapHeader.memberInfo;
                    mapping.repeats = soapHeader.repeats; 
                    mapping.custom = soapHeader.custom; 
                    mapping.direction = soapHeader.direction;
                    mapping.headerType = soapHeader.headerType; 
                    if ((mapping.direction & SoapHeaderDirection.In) != 0)
                        inHeaders.Add(mapping);
                    if ((mapping.direction & (SoapHeaderDirection.Out | SoapHeaderDirection.Fault)) != 0)
                        outHeaders.Add(mapping); 
                }
                clientMethod.inHeaderMappings = (SoapHeaderMapping[])inHeaders.ToArray(typeof(SoapHeaderMapping)); 
                if (clientMethod.outHeaderSerializer != null) 
                    clientMethod.outHeaderMappings = (SoapHeaderMapping[])outHeaders.ToArray(typeof(SoapHeaderMapping));
                methods.Add(soapMethod.name, clientMethod); 
            }
        }

        internal static void GenerateXmlMappings(Type type, ArrayList soapMethodList, string serviceNamespace, bool serviceDefaultIsEncoded, ArrayList mappings) { 
            LogicalMethodInfo[] methodInfos = LogicalMethodInfo.Create(type.GetMethods(BindingFlags.Public | BindingFlags.Instance), LogicalMethodTypes.[....]);
 
            SoapReflectionImporter soapImporter = SoapReflector.CreateSoapImporter(serviceNamespace, serviceDefaultIsEncoded); 
            XmlReflectionImporter xmlImporter = SoapReflector.CreateXmlImporter(serviceNamespace, serviceDefaultIsEncoded);
            WebMethodReflector.IncludeTypes(methodInfos, xmlImporter); 
            SoapReflector.IncludeTypes(methodInfos, soapImporter);


            for (int i = 0; i < methodInfos.Length; i++) { 
                LogicalMethodInfo methodInfo = methodInfos[i];
                SoapReflectedMethod soapMethod = SoapReflector.ReflectMethod(methodInfo, true, xmlImporter, soapImporter, serviceNamespace); 
                if (soapMethod == null) continue; 
                soapMethodList.Add(soapMethod);
                mappings.Add(soapMethod.requestMappings); 
                if (soapMethod.responseMappings != null) mappings.Add(soapMethod.responseMappings);
                mappings.Add(soapMethod.inHeaderMappings);
                if (soapMethod.outHeaderMappings != null) mappings.Add(soapMethod.outHeaderMappings);
            } 
        }
 
        internal SoapClientMethod GetMethod(string name) { 
            return (SoapClientMethod)methods[name];
        } 

        internal WebServiceBindingAttribute Binding {
            get { return binding; }
        } 
    }
 
    internal class SoapClientMethod { 
        internal XmlSerializer returnSerializer;
        internal XmlSerializer parameterSerializer; 
        internal XmlSerializer inHeaderSerializer;
        internal XmlSerializer outHeaderSerializer;
        internal string action;
        internal LogicalMethodInfo methodInfo; 
        internal SoapHeaderMapping[] inHeaderMappings;
        internal SoapHeaderMapping[] outHeaderMappings; 
        internal SoapReflectedExtension[] extensions; 
        internal object[] extensionInitializers;
        internal bool oneWay; 
        internal bool rpc;
        internal SoapBindingUse use;
        internal SoapParameterStyle paramStyle;
    } 

    ///  
    ///  
    ///    
    ///       Specifies most of the implementation for communicating with a SOAP web service over HTTP. 
    ///    
    /// 
    [ComVisible(true)]
    public class SoapHttpClientProtocol : HttpWebClientProtocol { 
        SoapClientType clientType;
        SoapProtocolVersion version = SoapProtocolVersion.Default; 
 
        /// 
        ///  
        ///    
        ///       Initializes a new instance of the  class.
        ///    
        ///  
        public SoapHttpClientProtocol()
            : base() { 
            Type type = this.GetType(); 
            clientType = (SoapClientType)GetFromCache(type);
            if (clientType == null) { 
                lock (InternalSyncObject) {
                    clientType = (SoapClientType)GetFromCache(type);
                    if (clientType == null) {
                        clientType = new SoapClientType(type); 
                        AddToCache(type, clientType);
                    } 
                } 
            }
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        public void Discover() { 
            if (clientType.Binding == null) 
                throw new InvalidOperationException(Res.GetString(Res.DiscoveryIsNotPossibleBecauseTypeIsMissing1, this.GetType().FullName));
            DiscoveryClientProtocol disco = new DiscoveryClientProtocol(this); 
            DiscoveryDocument doc = disco.Discover(Url);
            foreach (object item in doc.References) {
                System.Web.Services.Discovery.SoapBinding soapBinding = item as System.Web.Services.Discovery.SoapBinding;
                if (soapBinding != null) { 
                    if (clientType.Binding.Name == soapBinding.Binding.Name &&
                        clientType.Binding.Namespace == soapBinding.Binding.Namespace) { 
                        Url = soapBinding.Address; 
                        return;
                    } 
                }
            }
            throw new InvalidOperationException(Res.GetString(Res.TheBindingNamedFromNamespaceWasNotFoundIn3, clientType.Binding.Name, clientType.Binding.Namespace, Url));
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override WebRequest GetWebRequest(Uri uri) {
            WebRequest request = base.GetWebRequest(uri);
            return request;
        } 

        ///  
        [DefaultValue(SoapProtocolVersion.Default), WebServicesDescription(Res.ClientProtocolSoapVersion), ComVisible(false)] 
        public SoapProtocolVersion SoapVersion {
            get { return version; } 
            set { version = value; }
        }

        ///  
        /// 
        ///     
        ///       Allows to intercept XmlWriter creation. 
        ///    
        ///  
        [PermissionSet(SecurityAction.LinkDemand | SecurityAction.InheritanceDemand, Name="FullTrust")]
        protected virtual XmlWriter GetWriterForMessage(SoapClientMessage message, int bufferSize) {
            if (bufferSize < 512)
                bufferSize = 512; 
            XmlTextWriter writer = new XmlTextWriter(new StreamWriter(message.Stream, RequestEncoding != null ? RequestEncoding : new UTF8Encoding(false), bufferSize));
            /* 
            if (RequestEncoding != null && RequestEncoding.GetType() != typeof(UTF8Encoding)) { 
                writer = new XmlTextWriter(new StreamWriter(message.Stream, RequestEncoding, bufferSize));
            } 
            else {
                XmlWriterSettings ws = new XmlWriterSettings();
                ws.Encoding = new UTF8Encoding(false);
                ws.Indent = false; 
                ws.NewLineHandling = NewLineHandling.None;
                writer = XmlWriter.Create(message.Stream, ws); 
            } 
            */
            return writer; 
        }

        /// 
        ///  
        ///    
        ///       Allows to intercept XmlReader creation. 
        ///     
        /// 
 
        [PermissionSet(SecurityAction.LinkDemand | SecurityAction.InheritanceDemand, Name="FullTrust")]
        protected virtual XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize) {
            Encoding enc = message.SoapVersion == SoapProtocolVersion.Soap12 ? RequestResponseUtils.GetEncoding2(message.ContentType) : RequestResponseUtils.GetEncoding(message.ContentType);
            if (bufferSize < 512) 
                bufferSize = 512;
            XmlTextReader reader; 
            if (enc != null) 
                reader = new XmlTextReader(new StreamReader(message.Stream, enc, true, bufferSize));
            else 
                //
                reader = new XmlTextReader(message.Stream);

            reader.DtdProcessing = DtdProcessing.Prohibit; 
            reader.Normalization = true;
            reader.XmlResolver = null; 
 
            return reader;
        } 

        /// 
        /// 
        ///     
        ///       Invokes a method of a SOAP web service.
        ///     
        ///  
        protected object[] Invoke(string methodName, object[] parameters) {
            WebResponse response = null; 
            WebRequest request = null;
            try {
                request = GetWebRequest(Uri);
                NotifyClientCallOut(request); 
                //
                PendingSyncRequest = request; 
                SoapClientMessage message = BeforeSerialize(request, methodName, parameters); 
                Stream requestStream = request.GetRequestStream();
                try { 
                    message.SetStream(requestStream);
                    Serialize(message);
                }
                finally { 
                    requestStream.Close();
                } 
 
                response = GetWebResponse(request);
                Stream responseStream = null; 
                try {
                    responseStream = response.GetResponseStream();
                    return ReadResponse(message, response, responseStream, false);
                } 
                catch (XmlException e) {
                    throw new InvalidOperationException(Res.GetString(Res.WebResponseBadXml), e); 
                } 
                finally {
                    if (responseStream != null) 
                        responseStream.Close();
                }
            }
            finally { 
                if (request == PendingSyncRequest)
                    PendingSyncRequest = null; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Starts an asynchronous invocation of a method of a SOAP web 
        ///       service.
        ///     
        ///  
        protected IAsyncResult BeginInvoke(string methodName, object[] parameters, AsyncCallback callback, object asyncState) {
            InvokeAsyncState invokeState = new InvokeAsyncState(methodName, parameters); 
            WebClientAsyncResult asyncResult = new WebClientAsyncResult(this, invokeState, null, callback, asyncState);
            return BeginSend(Uri, asyncResult, true);
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        internal override void InitializeAsyncRequest(WebRequest request, object internalAsyncState) { 
            InvokeAsyncState invokeState = (InvokeAsyncState)internalAsyncState;
            invokeState.Message = BeforeSerialize(request, invokeState.MethodName, invokeState.Parameters);
        }
 
        internal override void AsyncBufferedSerialize(WebRequest request, Stream requestStream, object internalAsyncState) {
            InvokeAsyncState invokeState = (InvokeAsyncState)internalAsyncState; 
            SoapClientMessage message = invokeState.Message; 
            message.SetStream(requestStream);
            Serialize(invokeState.Message); 
        }

        class InvokeAsyncState {
            public string MethodName; 
            public object[] Parameters;
            public SoapClientMessage Message; 
 
            public InvokeAsyncState(string methodName, object[] parameters) {
                this.MethodName = methodName; 
                this.Parameters = parameters;
            }
        }
 
        /// 
        ///  
        ///     
        ///       Ends an asynchronous invocation of a method of a remote SOAP web service.
        ///     
        /// 
        protected object[] EndInvoke(IAsyncResult asyncResult) {
            object o = null;
            Stream responseStream = null; 
            try {
                WebResponse response = EndSend(asyncResult, ref o, ref responseStream); 
                InvokeAsyncState invokeState = (InvokeAsyncState)o; 
                return ReadResponse(invokeState.Message, response, responseStream, true);
            } 
            catch (XmlException e) {
                throw new InvalidOperationException(Res.GetString(Res.WebResponseBadXml), e);
            }
            finally { 
                if (responseStream != null)
                    responseStream.Close(); 
            } 
        }
 
        private void InvokeAsyncCallback(IAsyncResult result) {
            object[] parameters = null;
            Exception exception = null;
 
            WebClientAsyncResult asyncResult = (WebClientAsyncResult)result;
            if (asyncResult.Request != null) { 
                object o = null; 
                Stream responseStream = null;
                try { 
                    WebResponse response = EndSend(asyncResult, ref o, ref responseStream);
                    InvokeAsyncState invokeState = (InvokeAsyncState)o;
                    parameters = ReadResponse(invokeState.Message, response, responseStream, true);
                } 
                catch (XmlException e) {
                    if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "InvokeAsyncCallback", e); 
                    exception = new InvalidOperationException(Res.GetString(Res.WebResponseBadXml), e); 
                }
                catch (Exception e) { 
                    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                        throw;
                    if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "InvokeAsyncCallback", e);
                    exception = e; 
                }
                finally { 
                    if (responseStream != null) 
                        responseStream.Close();
                } 
            }
            AsyncOperation asyncOp = (AsyncOperation)result.AsyncState;
            UserToken token = (UserToken)asyncOp.UserSuppliedState;
            OperationCompleted(token.UserState, parameters, exception, false); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected void InvokeAsync(string methodName, object[] parameters, SendOrPostCallback callback) {
            InvokeAsync(methodName, parameters, callback, null);
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected void InvokeAsync(string methodName, object[] parameters, SendOrPostCallback callback, object userState) {
            if (userState == null)
                userState = NullToken;
            InvokeAsyncState invokeState = new InvokeAsyncState(methodName, parameters); 
            AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(new UserToken(callback, userState));
            WebClientAsyncResult asyncResult = new WebClientAsyncResult(this, invokeState, null, new AsyncCallback(InvokeAsyncCallback), asyncOp); 
            try { 
                AsyncInvokes.Add(userState, asyncResult);
            } 
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                    throw;
                if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "InvokeAsync", e); 
                Exception exception = new ArgumentException(Res.GetString(Res.AsyncDuplicateUserState), e);
                InvokeCompletedEventArgs eventArgs = new InvokeCompletedEventArgs(new object[] { null }, exception, false, userState); 
                asyncOp.PostOperationCompleted(callback, eventArgs); 
                return;
            } 
            try {
                BeginSend(Uri, asyncResult, true);
            }
            catch (Exception e) { 
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                    throw; 
                if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "InvokeAsync", e); 
                OperationCompleted(userState, new object[] { null }, e, false);
            } 
        }

        private static Array CombineExtensionsHelper(Array array1, Array array2, Array array3, Type elementType) {
            int length = array1.Length + array2.Length + array3.Length; 
            if (length == 0)
                return null; 
            Array result = null; 
            if (elementType == typeof(SoapReflectedExtension))
                result = new SoapReflectedExtension[length]; 
            else if (elementType == typeof(object))
                result  = new object[length];
            else
                throw new ArgumentException(Res.GetString(Res.ElementTypeMustBeObjectOrSoapReflectedException),"elementType"); 

            int pos = 0; 
            Array.Copy(array1, 0, result, pos, array1.Length); 
            pos += array1.Length;
            Array.Copy(array2, 0, result, pos, array2.Length); 
            pos += array2.Length;
            Array.Copy(array3, 0, result, pos, array3.Length);
            return result;
        } 

        private string EnvelopeNs { 
            get { 
                return this.version == SoapProtocolVersion.Soap12 ? Soap12.Namespace : Soap.Namespace;
            } 
        }

        private string EncodingNs {
            get { 
                return this.version == SoapProtocolVersion.Soap12 ? Soap12.Encoding : Soap.Encoding;
            } 
        } 

        private string HttpContentType { 
            get {
                return this.version == SoapProtocolVersion.Soap12 ? ContentType.ApplicationSoap : ContentType.TextXml;
            }
        } 

        SoapClientMessage BeforeSerialize(WebRequest request, string methodName, object[] parameters) { 
            if (parameters == null) throw new ArgumentNullException("parameters"); 
            SoapClientMethod method = clientType.GetMethod(methodName);
            if (method == null) throw new ArgumentException(Res.GetString(Res.WebInvalidMethodName, methodName)); 

            // Run BeforeSerialize extension pass. Extensions are not allowed
            // to write into the stream during this pass.
            SoapReflectedExtension[] allExtensions = (SoapReflectedExtension[])CombineExtensionsHelper(clientType.HighPriExtensions, method.extensions, clientType.LowPriExtensions, typeof(SoapReflectedExtension)); 
            object[] allExtensionInitializers = (object[])CombineExtensionsHelper(clientType.HighPriExtensionInitializers, method.extensionInitializers, clientType.LowPriExtensionInitializers, typeof(object));
            SoapExtension[] initializedExtensions = SoapMessage.InitializeExtensions(allExtensions, allExtensionInitializers); 
            SoapClientMessage message = new SoapClientMessage(this, method, Url); 
            message.initializedExtensions = initializedExtensions;
            if (initializedExtensions != null) 
                message.SetExtensionStream(new SoapExtensionStream());
            message.InitExtensionStreamChain(message.initializedExtensions);

            string soapAction = UrlEncoder.EscapeString(method.action, Encoding.UTF8); 
            message.SetStage(SoapMessageStage.BeforeSerialize);
            if (this.version == SoapProtocolVersion.Soap12) 
                message.ContentType = ContentType.Compose(ContentType.ApplicationSoap, RequestEncoding != null ? RequestEncoding : Encoding.UTF8, soapAction); 
            else
                message.ContentType = ContentType.Compose(ContentType.TextXml, RequestEncoding != null ? RequestEncoding : Encoding.UTF8); 
            message.SetParameterValues(parameters);
            SoapHeaderHandling.GetHeaderMembers(message.Headers, this, method.inHeaderMappings, SoapHeaderDirection.In, true);
            message.RunExtensions(message.initializedExtensions, true);
 
            // Last chance to set request headers
            request.ContentType = message.ContentType; 
            if (message.ContentEncoding != null && message.ContentEncoding.Length > 0) 
                request.Headers[ContentType.ContentEncoding] = message.ContentEncoding;
 
            request.Method = "POST";
            if (this.version != SoapProtocolVersion.Soap12 && request.Headers[Soap.Action] == null) {
                StringBuilder actionStringBuilder = new StringBuilder(soapAction.Length + 2);
                actionStringBuilder.Append('"'); 
                actionStringBuilder.Append(soapAction);
                actionStringBuilder.Append('"'); 
                request.Headers.Add(Soap.Action, actionStringBuilder.ToString()); 
            }
 
            return message;
        }

        void Serialize(SoapClientMessage message) { 
            Stream stream = message.Stream;
            SoapClientMethod method = message.Method; 
            bool isEncoded = method.use == SoapBindingUse.Encoded; 

            // Serialize the message. 
            string envelopeNs = EnvelopeNs;
            string encodingNs = EncodingNs;

            XmlWriter writer = GetWriterForMessage(message, 1024); 
            if (writer == null)
                throw new InvalidOperationException(Res.GetString(Res.WebNullWriterForMessage)); 
 
            writer.WriteStartDocument();
            writer.WriteStartElement(Soap.Prefix, Soap.Element.Envelope, envelopeNs); 
            writer.WriteAttributeString("xmlns", Soap.Prefix, null, envelopeNs);
            if (isEncoded) {
                writer.WriteAttributeString("xmlns", "soapenc", null, encodingNs);
                writer.WriteAttributeString("xmlns", "tns", null, clientType.serviceNamespace); 
                writer.WriteAttributeString("xmlns", "types", null, SoapReflector.GetEncodedNamespace(clientType.serviceNamespace, clientType.serviceDefaultIsEncoded));
            } 
            writer.WriteAttributeString("xmlns", "xsi", null, XmlSchema.InstanceNamespace); 
            writer.WriteAttributeString("xmlns", "xsd", null, XmlSchema.Namespace);
            SoapHeaderHandling.WriteHeaders(writer, method.inHeaderSerializer, message.Headers, method.inHeaderMappings, SoapHeaderDirection.In, isEncoded, clientType.serviceNamespace, clientType.serviceDefaultIsEncoded, envelopeNs); 
            writer.WriteStartElement(Soap.Element.Body, envelopeNs);
            if (isEncoded && version != SoapProtocolVersion.Soap12) // don't write encodingStyle on soap:Body for soap 1.2
                writer.WriteAttributeString("soap", Soap.Attribute.EncodingStyle, null, encodingNs);
 
            object[] parameters = message.GetParameterValues();
            TraceMethod caller = Tracing.On ? new TraceMethod(this, "Serialize") : null; 
 
            if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceWriteRequest), caller, new TraceMethod(method.parameterSerializer, "Serialize", writer, parameters, null, isEncoded ? encodingNs : null));
            method.parameterSerializer.Serialize(writer, parameters, null, isEncoded ? encodingNs : null); 
            if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceWriteRequest), caller);

            writer.WriteEndElement();
            writer.WriteEndElement(); 
            writer.Flush();
 
            // run the after serialize extension pass. 
            message.SetStage(SoapMessageStage.AfterSerialize);
            message.RunExtensions(message.initializedExtensions, true); 
        }

        object[] ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, bool asyncCall) {
            SoapClientMethod method = message.Method; 

            // 
 

            HttpWebResponse httpResponse = response as HttpWebResponse; 
            int statusCode = httpResponse != null ? (int)httpResponse.StatusCode : -1;
            if (statusCode >= 300 && statusCode != 500 && statusCode != 400)
                throw new WebException(RequestResponseUtils.CreateResponseExceptionString(httpResponse, responseStream), null,
                    WebExceptionStatus.ProtocolError, httpResponse); 

            message.Headers.Clear(); 
            message.SetStream(responseStream); 
            message.InitExtensionStreamChain(message.initializedExtensions);
 
            message.SetStage(SoapMessageStage.BeforeDeserialize);
            message.ContentType = response.ContentType;
            message.ContentEncoding = response.Headers[ContentType.ContentEncoding];
            message.RunExtensions(message.initializedExtensions, false); 

            if (method.oneWay && (httpResponse == null || (int)httpResponse.StatusCode != 500)) { 
                return new object[0]; 
            }
 
            // this statusCode check is just so we don't repeat the contentType check we did above
            bool isSoap = ContentType.IsSoap(message.ContentType);
            if (!isSoap || (isSoap && (httpResponse != null) && (httpResponse.ContentLength == 0))) {
                // special-case 400 since we exempted it above on the off-chance it might be a soap 1.2 sender fault. 
                // based on the content-type, it looks like it's probably just a regular old 400
                if (statusCode == 400) 
                    throw new WebException(RequestResponseUtils.CreateResponseExceptionString(httpResponse, responseStream), null, 
                        WebExceptionStatus.ProtocolError, httpResponse);
                else 
                    throw new InvalidOperationException(Res.GetString(Res.WebResponseContent, message.ContentType, HttpContentType) +
                                    Environment.NewLine +
                                    RequestResponseUtils.CreateResponseExceptionString(response, responseStream));
            } 
            if (message.Exception != null) {
                throw message.Exception; 
            } 

            // perf fix: changed buffer size passed to StreamReader 
            int bufferSize;
            if (asyncCall || httpResponse == null)
                bufferSize = 512;
            else { 
                bufferSize = RequestResponseUtils.GetBufferSize((int)httpResponse.ContentLength);
            } 
            XmlReader reader = GetReaderForMessage(message, bufferSize); 
            if (reader == null)
                throw new InvalidOperationException(Res.GetString(Res.WebNullReaderForMessage)); 

            reader.MoveToContent();
            int depth = reader.Depth;
 
            // should be able to handle no ns, soap 1.1 ns, or soap 1.2 ns
            string encodingNs = EncodingNs; 
            string envelopeNs = reader.NamespaceURI; 

            if (envelopeNs == null || envelopeNs.Length == 0) 
                // ok to omit namespace -- assume correct version
                reader.ReadStartElement(Soap.Element.Envelope);
            else if (reader.NamespaceURI == Soap.Namespace)
                reader.ReadStartElement(Soap.Element.Envelope, Soap.Namespace); 
            else if (reader.NamespaceURI == Soap12.Namespace)
                reader.ReadStartElement(Soap.Element.Envelope, Soap12.Namespace); 
            else 
                throw new SoapException(Res.GetString(Res.WebInvalidEnvelopeNamespace, envelopeNs, EnvelopeNs), SoapException.VersionMismatchFaultCode);
 
            reader.MoveToContent();
            SoapHeaderHandling headerHandler = new SoapHeaderHandling();
            headerHandler.ReadHeaders(reader, method.outHeaderSerializer, message.Headers, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, envelopeNs, method.use == SoapBindingUse.Encoded ? encodingNs : null, false);
            reader.MoveToContent(); 
            reader.ReadStartElement(Soap.Element.Body, envelopeNs);
            reader.MoveToContent(); 
            if (reader.IsStartElement(Soap.Element.Fault, envelopeNs)) { 
                message.Exception = ReadSoapException(reader);
            } 
            else {
                if (method.oneWay) {
                    reader.Skip();
                    message.SetParameterValues(new object[0]); 
                }
                else { 
                    TraceMethod caller = Tracing.On ? new TraceMethod(this, "ReadResponse") : null; 
                    bool isEncodedSoap = method.use == SoapBindingUse.Encoded;
                    if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceReadResponse), caller, new TraceMethod(method.returnSerializer, "Deserialize", reader, isEncodedSoap ? encodingNs : null)); 

                    bool useDeserializationEvents = !isEncodedSoap && (WebServicesSection.Current.SoapEnvelopeProcessing.IsStrict || Tracing.On);
                    if (useDeserializationEvents) {
                        XmlDeserializationEvents events = Tracing.On ? Tracing.GetDeserializationEvents() : RuntimeUtils.GetDeserializationEvents(); 
                        message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, null, events));
                    } 
                    else { 
                        message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, isEncodedSoap ? encodingNs : null));
                    } 

                    if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceReadResponse), caller);
                }
            } 

            // Consume soap:Body and soap:Envelope closing tags 
            while (depth < reader.Depth && reader.Read()) { 
                // Nothing, just read on
            } 
            // consume end tag
            if (reader.NodeType == XmlNodeType.EndElement) {
                reader.Read();
            } 

            message.SetStage(SoapMessageStage.AfterDeserialize); 
            message.RunExtensions(message.initializedExtensions, false); 
            SoapHeaderHandling.SetHeaderMembers(message.Headers, this, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, true);
 
            if (message.Exception != null) throw message.Exception;
            return message.GetParameterValues();
        }
 
        SoapException ReadSoapException(XmlReader reader) {
            XmlQualifiedName faultCode = XmlQualifiedName.Empty; 
            string faultString = null; 
            string faultActor = null;
            string faultRole = null; 
            XmlNode detail = null;
            SoapFaultSubCode subcode = null;
            string lang = null;
            bool soap12 = (reader.NamespaceURI == Soap12.Namespace); 
            if (reader.IsEmptyElement) {
                reader.Skip(); 
            } 
            else {
                reader.ReadStartElement(); 
                reader.MoveToContent();
                int depth = reader.Depth;
                while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.None) {
                    if (reader.NamespaceURI == Soap.Namespace || reader.NamespaceURI == Soap12.Namespace || reader.NamespaceURI == null || reader.NamespaceURI.Length == 0) { 
                        if (reader.LocalName == Soap.Element.FaultCode || reader.LocalName == Soap12.Element.FaultCode) {
                            if (soap12) 
                                faultCode = ReadSoap12FaultCode(reader, out subcode); 
                            else
                                faultCode = ReadFaultCode(reader); 
                        }
                        else if (reader.LocalName == Soap.Element.FaultString) {
                            lang = reader.GetAttribute(Soap.Attribute.Lang, Soap.XmlNamespace);
                            reader.MoveToElement(); 
                            faultString = reader.ReadElementString();
                        } 
                        else if (reader.LocalName == Soap12.Element.FaultReason) { 
                            if (reader.IsEmptyElement)
                                reader.Skip(); 
                            else {
                                reader.ReadStartElement(); // consume Reason element to get to Text child
                                reader.MoveToContent();
                                while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.None) { 
                                    if (reader.LocalName == Soap12.Element.FaultReasonText && reader.NamespaceURI == Soap12.Namespace) {
                                        faultString = reader.ReadElementString(); 
                                    } 
                                    else {
                                        reader.Skip(); 
                                    }
                                    reader.MoveToContent();
                                }
                                while (reader.NodeType == XmlNodeType.Whitespace) reader.Skip(); 
                                if (reader.NodeType == XmlNodeType.None) reader.Skip();
                                else reader.ReadEndElement(); 
                            } 
                        }
                        else if (reader.LocalName == Soap.Element.FaultActor || reader.LocalName == Soap12.Element.FaultNode) { 
                            faultActor = reader.ReadElementString();
                        }
                        else if (reader.LocalName == Soap.Element.FaultDetail || reader.LocalName == Soap12.Element.FaultDetail) {
                            detail = new XmlDocument().ReadNode(reader); 
                        }
                        else if (reader.LocalName == Soap12.Element.FaultRole) { 
                            faultRole = reader.ReadElementString(); 
                        }
                        else { 
                            reader.Skip();
                        }
                    }
                    else { 
                        reader.Skip();
                    } 
                    reader.MoveToContent(); 
                }
                // Consume soap:Body and soap:Envelope closing tags 
                while (reader.Read() && depth < reader.Depth) {
                    // Nothing, just read on
                }
                // consume end tag 
                if (reader.NodeType == XmlNodeType.EndElement) {
                    reader.Read(); 
                } 
            }
            if (detail != null || soap12) // with soap 1.2, can't tell if fault is for header 
                return new SoapException(faultString, faultCode, faultActor, faultRole, lang, detail, subcode, null);
            else
                return new SoapHeaderException(faultString, faultCode, faultActor, faultRole, lang, subcode, null);
        } 

        private XmlQualifiedName ReadSoap12FaultCode(XmlReader reader, out SoapFaultSubCode subcode) { 
            SoapFaultSubCode code = ReadSoap12FaultCodesRecursive(reader, 0); 
            if (code == null) {
                subcode = null; 
                return null;
            }
            else {
                subcode = code.SubCode; 
                return code.Code;
            } 
        } 

        private SoapFaultSubCode ReadSoap12FaultCodesRecursive(XmlReader reader, int depth) { 
            if (depth > 100) return null;
            if (reader.IsEmptyElement) {
                reader.Skip();
                return null; 
            }
            XmlQualifiedName code = null; 
            SoapFaultSubCode subcode = null; 
            int faultDepth = reader.Depth;
            reader.ReadStartElement(); 
            reader.MoveToContent();
            while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.None) {
                if (reader.NamespaceURI == Soap12.Namespace || reader.NamespaceURI == null || reader.NamespaceURI.Length == 0) {
                    if (reader.LocalName == Soap12.Element.FaultCodeValue) { 
                        code = ReadFaultCode(reader);
                    } 
                    else if (reader.LocalName == Soap12.Element.FaultSubcode) { 
                        subcode = ReadSoap12FaultCodesRecursive(reader, depth + 1);
                    } 
                    else {
                        reader.Skip();
                    }
                } 
                else {
                    reader.Skip(); 
                } 
                reader.MoveToContent();
            } 
            // Consume closing tag
            while (faultDepth < reader.Depth && reader.Read()) {
                // Nothing, just read on
            } 
            // consume end tag
            if (reader.NodeType == XmlNodeType.EndElement) { 
                reader.Read(); 
            }
 
            return new SoapFaultSubCode(code, subcode);
        }

        private XmlQualifiedName ReadFaultCode(XmlReader reader) { 
            if (reader.IsEmptyElement) {
                reader.Skip(); 
                return null; 
            }
            reader.ReadStartElement(); 
            string qnameValue = reader.ReadString();
            int colon = qnameValue.IndexOf(":", StringComparison.Ordinal);
            string ns = reader.NamespaceURI;
            if (colon >= 0) { 
                string prefix = qnameValue.Substring(0, colon);
                ns = reader.LookupNamespace(prefix); 
                if (ns == null) 
                    throw new InvalidOperationException(Res.GetString(Res.WebQNamePrefixUndefined, prefix));
            } 
            reader.ReadEndElement();

            return new XmlQualifiedName(qnameValue.Substring(colon+1), ns);
        } 
    }
} 
 


// 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