MetadataExchangeClient.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Description / MetadataExchangeClient.cs / 1 / MetadataExchangeClient.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Description
{ 
    using System.Collections.Generic;
    using System.ServiceModel; 
    using System.Collections.ObjectModel; 
    using System.Collections.Specialized;
    using System.Xml; 
    using XsdNS = System.Xml.Schema;
    using WsdlNS = System.Web.Services.Description;
    using System.ServiceModel.Configuration;
    using System.ServiceModel.Diagnostics; 
    using System.Collections;
    using System.Diagnostics; 
    using System.Net; 
    using System.Web;
    using System.Security.Cryptography.X509Certificates; 
    using System.ServiceModel.Channels;
    using System.ComponentModel;
    using System.Threading;
    using System.Text; 
    using System.Net.Mime;
    using System.Globalization; 
    using System.IO; 
    using System.Security;
 

    public class MetadataExchangeClient
    {
        ChannelFactory factory; 
        ICredentials webRequestCredentials;
 
        TimeSpan resolveTimeout = TimeSpan.FromMinutes(1); 
        int maximumResolvedReferences = 10;
        bool resolveMetadataReferences = true; 
        long maxMessageSize;

        EndpointAddress ctorEndpointAddress = null;
        Uri ctorUri = null; 

        object thisLock = new object(); 
 
        internal const string MetadataExchangeClientKey = "MetadataExchangeClientKey";
 
        public MetadataExchangeClient()
        {
            this.factory = new ChannelFactory("*");
            this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding); 
        }
        public MetadataExchangeClient(Uri address, MetadataExchangeClientMode mode) 
        { 
            Validate(address, mode);
 
            if (mode == MetadataExchangeClientMode.HttpGet)
            {
                this.ctorUri = address;
            } 
            else
            { 
                this.ctorEndpointAddress = new EndpointAddress(address); 
            }
 
            CreateChannelFactory(address.Scheme);
        }
        public MetadataExchangeClient(EndpointAddress address)
        { 
            if (address == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address"); 
            }
 
            this.ctorEndpointAddress = address;

#pragma warning suppress 56506 //
            CreateChannelFactory(address.Uri.Scheme); 
        }
        public MetadataExchangeClient(string endpointConfigurationName) 
        { 
            if (endpointConfigurationName == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
            }
            this.factory = new ChannelFactory(endpointConfigurationName);
            this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding); 
        }
        public MetadataExchangeClient(Binding mexBinding) 
        { 
            if (mexBinding == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("mexBinding");
            }
            this.factory = new ChannelFactory(mexBinding);
            this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding); 
        }
 
        //Configuration for credentials 
        public ClientCredentials SoapCredentials
        { 
            get { return this.factory.Credentials; }
            set
            {
                if (value == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); 
                } 
                this.factory.Endpoint.Behaviors.RemoveAll();
                this.factory.Endpoint.Behaviors.Add(value); 
            }
        }
        public ICredentials HttpCredentials
        { 
            get { return this.webRequestCredentials; }
            set { this.webRequestCredentials = value; } 
 
        }
 
        // Configuration options for the entire MetadataResolver
        public TimeSpan OperationTimeout
        {
            get { return this.resolveTimeout; } 
            set
            { 
                if (value < TimeSpan.Zero) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, 
                        SR.GetString(SR.SFxTimeoutOutOfRange0)));
                }

                if (TimeoutHelper.IsTooLarge(value)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, 
                        SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 
                }
 
                this.resolveTimeout = value;
            }
        }
        public int MaximumResolvedReferences 
        {
            get { return this.maximumResolvedReferences; } 
            set 
            {
                if (value < 1) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxMaximumResolvedReferencesOutOfRange, value)));
                }
                this.maximumResolvedReferences = value; 
            }
 
        } 
        public bool ResolveMetadataReferences
        { 
            get { return this.resolveMetadataReferences; }
            set { this.resolveMetadataReferences = value; }
        }
 
        internal object ThisLock
        { 
            get { return this.thisLock; } 
        }
        internal long MaxMessageSize 
        {
            get { return this.maxMessageSize; }
            set { this.maxMessageSize = value; }
        } 

        ///  
        ///  Critical - uses ClientSection.UnsafeGetSection to get config in PT 
        ///  Safe - does not leak config object, just calculates a bool
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        bool ClientEndpointExists(string name)
        {
            ClientSection clientSection = ClientSection.UnsafeGetSection(); 

            if (clientSection == null) 
                return false; 

            foreach (ChannelEndpointElement endpoint in clientSection.Endpoints) 
            {
                if (endpoint.Name == name && endpoint.Contract== ServiceMetadataBehavior.MexContractName)
                    return true;
            } 

            return false; 
        } 
        bool IsHttpOrHttps(Uri address)
        { 
            return address.Scheme == Uri.UriSchemeHttp || address.Scheme == Uri.UriSchemeHttps;
        }
        void CreateChannelFactory(string scheme)
        { 
            if (ClientEndpointExists(scheme))
            { 
                this.factory = new ChannelFactory(scheme); 
            }
            else 
            {
                Binding mexBinding = null;
                if (MetadataExchangeBindings.TryGetBindingForScheme(scheme, out mexBinding))
                { 
                    this.factory = new ChannelFactory(mexBinding);
                } 
                else 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("scheme", SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactoryBadScheme, scheme)); 
                }
            }
            this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
        } 
        void Validate(Uri address, MetadataExchangeClientMode mode)
        { 
            if (address == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address"); 
            }

            if (!address.IsAbsoluteUri)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotGetMetadataFromRelativeAddress, address));
            } 
 
            if (mode == MetadataExchangeClientMode.HttpGet && !IsHttpOrHttps(address))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotHttpGetMetadataFromAddress, address));
            }

            MetadataExchangeClientModeHelper.Validate(mode); 
        }
 
        public IAsyncResult BeginGetMetadata(AsyncCallback callback, object asyncState) 
        {
            if (ctorUri != null) 
                return BeginGetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet, callback, asyncState);
            if (ctorEndpointAddress != null)
                return BeginGetMetadata(ctorEndpointAddress, callback, asyncState);
            else 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
        } 
        public IAsyncResult BeginGetMetadata(Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState) 
        {
            Validate(address, mode); 

            if (mode == MetadataExchangeClientMode.HttpGet)
            {
                return this.BeginGetMetadata(new MetadataLocationRetriever(address, this), callback, asyncState); 
            }
            else 
            { 
                return this.BeginGetMetadata(new MetadataReferenceRetriever(new EndpointAddress(address), this), callback, asyncState);
            } 
        }
        public IAsyncResult BeginGetMetadata(EndpointAddress address, AsyncCallback callback, object asyncState)
        {
            if (address == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address"); 
            } 
            return this.BeginGetMetadata(new MetadataReferenceRetriever(address, this), callback, asyncState);
        } 
        IAsyncResult BeginGetMetadata(MetadataRetriever retriever, AsyncCallback callback, object asyncState)
        {
            ResolveCallState state = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this);
            state.StackedRetrievers.Push(retriever); 
            return new AsyncMetadataResolver(state, callback, asyncState);
        } 
 
        public MetadataSet EndGetMetadata(IAsyncResult result)
        { 
            return AsyncMetadataResolver.End(result);
        }

        public MetadataSet GetMetadata() 
        {
            if (ctorUri != null) 
                return GetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet); 
            if (ctorEndpointAddress != null)
                return GetMetadata(ctorEndpointAddress); 
            else
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
        }
        public MetadataSet GetMetadata(Uri address, MetadataExchangeClientMode mode) 
        {
            Validate(address, mode); 
 
            MetadataRetriever retriever;
            if (mode == MetadataExchangeClientMode.HttpGet) 
            {
                retriever = new MetadataLocationRetriever(address, this);
            }
            else 
            {
                retriever = new MetadataReferenceRetriever(new EndpointAddress(address), this); 
            } 
            return GetMetadata(retriever);
        } 
        public MetadataSet GetMetadata(EndpointAddress address)
        {
            if (address == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
            } 
 
            MetadataReferenceRetriever retriever = new MetadataReferenceRetriever(address, this);
            return GetMetadata(retriever); 
        }
        MetadataSet GetMetadata(MetadataRetriever retriever)
        {
            ResolveCallState resolveCallState = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this); 
            resolveCallState.StackedRetrievers.Push(retriever);
            this.ResolveNext(resolveCallState); 
 
            return resolveCallState.MetadataSet;
        } 

        void ResolveNext(ResolveCallState resolveCallState)
        {
            if (resolveCallState.StackedRetrievers.Count > 0) 
            {
                MetadataRetriever retriever = resolveCallState.StackedRetrievers.Pop(); 
 
                if (resolveCallState.HasBeenUsed(retriever))
                { 
                    this.ResolveNext(resolveCallState);
                }
                else
                { 
                    if (resolveCallState.ResolvedMaxResolvedReferences)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences))); 
                    }
 
                    resolveCallState.LogUse(retriever);
                    resolveCallState.HandleSection(retriever.Retrieve(resolveCallState.TimeoutHelper));
                    this.ResolveNext(resolveCallState);
                } 
            }
        } 
 
        protected internal virtual ChannelFactory GetChannelFactory(EndpointAddress metadataAddress, string dialect, string identifier)
        { 
            return this.factory;
        }

        static long GetMaxMessageSize(Binding mexBinding) 
        {
            BindingElementCollection bindingElementCollection = mexBinding.CreateBindingElements(); 
            TransportBindingElement bindingElement = bindingElementCollection.Find(); 
            if (bindingElement == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBindingDoesNotHaveATransportBindingElement)));
            }
            return bindingElement.MaxReceivedMessageSize;
        } 

        protected internal virtual HttpWebRequest GetWebRequest(Uri location, string dialect, string identifier) 
        { 
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
            request.Method = "GET"; 
            request.Credentials = this.HttpCredentials;

            return request;
        } 

        internal static void TraceSendRequest(Uri address) 
        { 
            TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, address.ToString(), MetadataExchangeClientMode.HttpGet.ToString());
        } 
        internal static void TraceSendRequest(EndpointAddress address)
        {
            TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, address.ToString(), MetadataExchangeClientMode.MetadataExchange.ToString());
        } 
        static void TraceSendRequest(TraceCode code, string address, string mode)
        { 
            if (DiagnosticUtility.ShouldTraceInformation) 
            {
                Hashtable h = new Hashtable(2); 
                h.Add("Address", address);
                h.Add("Mode", mode);
                TraceUtility.TraceEvent(TraceEventType.Information, code, new DictionaryTraceRecord(h), null, null);
            } 
        }
        internal static void TraceReceiveReply(string sourceUrl, Type metadataType) 
        { 
            if (DiagnosticUtility.ShouldTraceInformation)
            { 
                Hashtable h = new Hashtable(2);
                h.Add("SourceUrl", sourceUrl);
                h.Add("MetadataType", metadataType.ToString());
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MetadataExchangeClientReceiveReply, new DictionaryTraceRecord(h), null, null); 
            }
        } 
 
        class ResolveCallState
        { 
            Dictionary usedRetrievers;   // to prevent looping when chasing MetadataReferences
            MetadataSet metadataSet;
            int maxResolvedReferences;
            bool resolveMetadataReferences; 
            Stack stackedRetrievers;
            MetadataExchangeClient resolver; 
            TimeoutHelper timeoutHelper; 

            internal ResolveCallState(int maxResolvedReferences, bool resolveMetadataReferences, 
                TimeoutHelper timeoutHelper, MetadataExchangeClient resolver)
            {
                this.maxResolvedReferences = maxResolvedReferences;
                this.resolveMetadataReferences = resolveMetadataReferences; 
                this.resolver = resolver;
                this.timeoutHelper = timeoutHelper; 
                this.metadataSet = new MetadataSet(); 
                this.usedRetrievers = new Dictionary();
                this.stackedRetrievers = new Stack(); 
            }

            internal MetadataSet MetadataSet
            { 
                get { return this.metadataSet; }
            } 
 
            internal Stack StackedRetrievers
            { 
                get { return this.stackedRetrievers; }
            }

            internal bool ResolvedMaxResolvedReferences 
            {
                get { return this.usedRetrievers.Count == this.maxResolvedReferences; } 
            } 

            internal TimeoutHelper TimeoutHelper 
            {
                get { return this.timeoutHelper; }
            }
 
            internal void HandleSection(MetadataSection section)
            { 
                if (section.Metadata is MetadataSet) 
                {
                    foreach (MetadataSection innerSection in ((MetadataSet)section.Metadata).MetadataSections) 
                    {
                        innerSection.SourceUrl = section.SourceUrl;
                        this.HandleSection(innerSection);
                    } 
                }
                else if (section.Metadata is MetadataReference) 
                { 
                    if (this.resolveMetadataReferences)
                    { 

                        EndpointAddress address = ((MetadataReference)section.Metadata).Address;
                        MetadataRetriever retriever = new MetadataReferenceRetriever(address, this.resolver, section.Dialect, section.Identifier);
                        this.stackedRetrievers.Push(retriever); 
                    }
                    else 
                    { 
                        this.metadataSet.MetadataSections.Add(section);
                    } 
                }
                else if (section.Metadata is MetadataLocation)
                {
                    if (this.resolveMetadataReferences) 
                    {
                        string location = ((MetadataLocation)section.Metadata).Location; 
                        MetadataRetriever retriever = new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, location), this.resolver, section.Dialect, section.Identifier); 
                        this.stackedRetrievers.Push(retriever);
                    } 
                    else
                    {
                        this.metadataSet.MetadataSections.Add(section);
                    } 
                }
                else if (section.Metadata is WsdlNS.ServiceDescription) 
                { 
                    if (this.resolveMetadataReferences)
                    { 
                        this.HandleWsdlImports(section);
                    }
                    this.metadataSet.MetadataSections.Add(section);
                } 
                else if (section.Metadata is XsdNS.XmlSchema)
                { 
                    if (this.resolveMetadataReferences) 
                    {
                        this.HandleSchemaImports(section); 
                    }
                    this.metadataSet.MetadataSections.Add(section);
                }
                else 
                {
                    this.metadataSet.MetadataSections.Add(section); 
                } 
            }
 
            private void HandleSchemaImports(MetadataSection section)
            {
                XsdNS.XmlSchema schema = (XsdNS.XmlSchema)section.Metadata;
                foreach (XsdNS.XmlSchemaExternal external in schema.Includes) 
                {
                    if (!String.IsNullOrEmpty(external.SchemaLocation)) 
                    { 
                        EnqueueRetrieverIfShouldResolve(
                            new MetadataLocationRetriever( 
                                this.CreateUri(section.SourceUrl, external.SchemaLocation),
                                this.resolver));
                    }
                } 
            }
 
            private void HandleWsdlImports(MetadataSection section) 
            {
                WsdlNS.ServiceDescription wsdl = (WsdlNS.ServiceDescription)section.Metadata; 
                foreach (WsdlNS.Import import in wsdl.Imports)
                {
                    if (!String.IsNullOrEmpty(import.Location))
                    { 
                        EnqueueRetrieverIfShouldResolve(new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, import.Location), this.resolver));
                    } 
                } 

                foreach (XsdNS.XmlSchema schema in wsdl.Types.Schemas) 
                {
                    MetadataSection schemaSection = new MetadataSection(null, null, schema);
                    schemaSection.SourceUrl = section.SourceUrl;
                    this.HandleSchemaImports(schemaSection); 
                }
            } 
 
            private Uri CreateUri(string baseUri, string relativeUri)
            { 
                return new Uri(new Uri(baseUri), relativeUri);
            }

            private void EnqueueRetrieverIfShouldResolve(MetadataRetriever retriever) 
            {
                if (this.resolveMetadataReferences) 
                { 
                    this.stackedRetrievers.Push(retriever);
                } 
            }

            internal bool HasBeenUsed(MetadataRetriever retriever)
            { 
                return this.usedRetrievers.ContainsKey(retriever);
            } 
 
            internal void LogUse(MetadataRetriever retriever)
            { 
                this.usedRetrievers.Add(retriever, retriever);
            }
        }
 
        abstract class MetadataRetriever
        { 
            protected MetadataExchangeClient resolver; 
            protected string dialect;
            protected string identifier; 

            public MetadataRetriever(MetadataExchangeClient resolver, string dialect, string identifier)
            {
                this.resolver = resolver; 
                this.dialect = dialect;
                this.identifier = identifier; 
            } 

            internal MetadataSection Retrieve(TimeoutHelper timeoutHelper) 
            {
                try
                {
                    using (XmlReader reader = this.DownloadMetadata(timeoutHelper)) 
                    {
                        return MetadataRetriever.CreateMetadataSection(reader, this.SourceUrl); 
                    } 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                        SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e)); 
                } 
            }
 
            internal abstract IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state);
            internal abstract MetadataSection EndRetrieve(IAsyncResult result);

            static internal MetadataSection CreateMetadataSection(XmlReader reader, string sourceUrl) 
            {
                MetadataSection section = null; 
                Type metadataType = null; 

                if (CanReadMetadataSet(reader)) 
                {
                    MetadataSet newSet = MetadataSet.ReadFrom(reader);
                    section = new MetadataSection(MetadataSection.MetadataExchangeDialect, null, newSet);
                    metadataType = typeof(MetadataSet); 
                }
                else if (WsdlNS.ServiceDescription.CanRead(reader)) 
                { 
                    WsdlNS.ServiceDescription wsdl = WsdlNS.ServiceDescription.Read(reader);
                    section = MetadataSection.CreateFromServiceDescription(wsdl); 
                    metadataType = typeof(WsdlNS.ServiceDescription);
                }
                else if (CanReadSchema(reader))
                { 
                    XsdNS.XmlSchema schema = XsdNS.XmlSchema.Read(reader, null);
                    section = MetadataSection.CreateFromSchema(schema); 
                    metadataType = typeof(XsdNS.XmlSchema); 
                }
                else 
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(reader);
                    section = new MetadataSection(null, null, doc.DocumentElement); 
                    metadataType = typeof(XmlElement);
                } 
 
                section.SourceUrl = sourceUrl;
 
                TraceReceiveReply(sourceUrl, metadataType);

                return section;
            } 

            protected abstract XmlReader DownloadMetadata(TimeoutHelper timeoutHelper); 
 
            protected abstract string SourceUrl { get; }
 
            private static bool CanReadSchema(XmlReader reader)
            {
                return reader.LocalName == MetadataStrings.XmlSchema.Schema
                    && reader.NamespaceURI == XsdNS.XmlSchema.Namespace; 
            }
 
            private static bool CanReadMetadataSet(XmlReader reader) 
            {
                return reader.LocalName == MetadataStrings.MetadataExchangeStrings.Metadata 
                    && reader.NamespaceURI == MetadataStrings.MetadataExchangeStrings.Namespace;
            }
        }
 
        class MetadataLocationRetriever : MetadataRetriever
        { 
            Uri location; 
            Uri responseLocation;
 
            internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver)
                : this(location, resolver, null, null)
            {
 
            }
 
            internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver, string dialect, string identifier) 
                : base(resolver, dialect, identifier)
            { 
                ValidateLocation(location);
                this.location = location;
                this.responseLocation = location;
            } 

            internal static void ValidateLocation(Uri location) 
            { 
                if (location == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("location");
                }

                if (location.Scheme != Uri.UriSchemeHttp && location.Scheme != Uri.UriSchemeHttps) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("location", SR.GetString(SR.SFxCannotGetMetadataFromLocation, location.ToString())); 
                } 
            }
 
            public override bool Equals(object obj)
            {
                return obj is MetadataLocationRetriever && ((MetadataLocationRetriever)obj).location == this.location;
            } 

            public override int GetHashCode() 
            { 
                return location.GetHashCode();
            } 

            protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper)
            {
                HttpWebResponse response; 
                HttpWebRequest request;
                try 
                { 
                    request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier);
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
                } 

                TraceSendRequest(this.location);
                request.Timeout = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
                response = (HttpWebResponse)request.GetResponse(); 
                responseLocation = request.Address;
 
                return MetadataLocationRetriever.GetXmlReader(response, this.resolver.MaxMessageSize); 
            }
 
            internal static XmlReader GetXmlReader(HttpWebResponse response, long maxMessageSize)
            {
                XmlReader reader = XmlDictionaryReader.CreateTextReader(
                    new MaxMessageSizeStream(response.GetResponseStream(), maxMessageSize), 
                    EncodingHelper.GetDictionaryReaderEncoding(response.ContentType),
                    EncoderDefaults.ReaderQuotas, 
                    null); 

                reader.Read(); 
                reader.MoveToContent();

                return reader;
            } 

            internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state) 
            { 

                AsyncMetadataLocationRetriever result; 
                try
                {
                    HttpWebRequest request;
                    try 
                    {
                        request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier); 
                    } 
#pragma warning suppress 56500 // covered by FxCOP
                    catch (Exception e) 
                    {
                        if (DiagnosticUtility.IsFatal(e))
                            throw;
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
                    } 
 
                    TraceSendRequest(this.location);
                    result = new AsyncMetadataLocationRetriever(request, this.resolver.MaxMessageSize, timeoutHelper, callback, state); 
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
                } 
                return result;
            }

            internal override MetadataSection EndRetrieve(IAsyncResult result) 
            {
                try 
                { 
                    return AsyncMetadataLocationRetriever.End(result);
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e)); 
                }
            } 

            protected override string SourceUrl
            {
                get { return this.responseLocation.ToString(); } 
            }
 
            class AsyncMetadataLocationRetriever : AsyncResult 
            {
                MetadataSection section; 
                long maxMessageSize;

                internal AsyncMetadataLocationRetriever(WebRequest request, long maxMessageSize, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
                    : base(callback, state) 
                {
                    this.maxMessageSize = maxMessageSize; 
                    IAsyncResult result = request.BeginGetResponse(DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.GetResponseCallback)), request); 

                    //Register a callback to abort the request if we hit the timeout. 
                    ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
                        DiagnosticUtility.Utility.ThunkCallback(new WaitOrTimerCallback(RetrieveTimeout)), request,
                        TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime()), /* executeOnlyOnce */ true);
 
                    if (result.CompletedSynchronously)
                    { 
                        HandleResult(result); 
                        this.Complete(true);
                    } 
                }

                static void RetrieveTimeout(object state, bool timedOut)
                { 
                    if (timedOut)
                    { 
                        HttpWebRequest request = state as HttpWebRequest; 
                        if (request != null)
                        { 
                            request.Abort();
                        }
                    }
                } 

                internal static MetadataSection End(IAsyncResult result) 
                { 
                    AsyncMetadataLocationRetriever retrieverResult = AsyncResult.End(result);
                    return retrieverResult.section; 
                }

                internal void GetResponseCallback(IAsyncResult result)
                { 
                    if (result.CompletedSynchronously)
                        return; 
 
                    Exception exception = null;
                    try 
                    {
                        HandleResult(result);
                    }
#pragma warning suppress 56500 // covered by FxCOP 
                    catch (Exception e)
                    { 
                        if (DiagnosticUtility.IsFatal(e)) 
                            throw;
                        exception = e; 
                    }
                    this.Complete(false, exception);
                }
 
                private void HandleResult(IAsyncResult result)
                { 
                    HttpWebRequest request = (HttpWebRequest)result.AsyncState; 

                    using (XmlReader reader = 
                        MetadataLocationRetriever.GetXmlReader((HttpWebResponse)request.EndGetResponse(result), this.maxMessageSize))
                    {
                        section = MetadataRetriever.CreateMetadataSection(reader, request.Address.ToString());
                    } 
                }
            } 
 

        } 

        class MetadataReferenceRetriever : MetadataRetriever
        {
            EndpointAddress address; 

            public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver) 
                : this(address, resolver, null, null) 
            {
            } 

            public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver, string dialect, string identifier)
                : base(resolver, dialect, identifier)
            { 
                if (address == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address"); 
                }
 
                this.address = address;
            }

            protected override string SourceUrl 
            {
                get { return this.address.Uri.ToString(); } 
            } 

            internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state) 
            {
                try
                {
                    IMetadataExchange metadataClient; 
                    MessageVersion messageVersion;
                    lock (this.resolver.ThisLock) 
                    { 
                        ChannelFactory channelFactory;
                        try 
                        {
                            channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier);
                        }
#pragma warning suppress 56500 // covered by FxCOP 
                        catch (Exception e)
                        { 
                            if (DiagnosticUtility.IsFatal(e)) 
                                throw;
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                                SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e));
                        }
                        metadataClient = channelFactory.CreateChannel(address);
                        messageVersion = channelFactory.Endpoint.Binding.MessageVersion; 
                    }
                    TraceSendRequest(this.address); 
                    return new AsyncMetadataReferenceRetriever(metadataClient, messageVersion, timeoutHelper, callback, state); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                        SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e)); 
                } 
            }
 
            static Message CreateGetMessage(MessageVersion messageVersion)
            {
                return Message.CreateMessage(messageVersion, MetadataStrings.WSTransfer.GetAction);
            } 

            protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper) 
            { 
                IMetadataExchange metadataClient;
                MessageVersion messageVersion; 

                lock (this.resolver.ThisLock)
                {
                    ChannelFactory channelFactory; 
                    try
                    { 
                        channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier); 
                    }
#pragma warning suppress 56500 // covered by FxCOP 
                    catch (Exception e)
                    {
                        if (DiagnosticUtility.IsFatal(e))
                            throw; 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                            SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e)); 
                    } 

                    metadataClient = channelFactory.CreateChannel(address); 
                    messageVersion = channelFactory.Endpoint.Binding.MessageVersion;
                }
                Message response;
 
                TraceSendRequest(this.address);
 
                try 
                {
                    using (Message getMessage = CreateGetMessage(messageVersion)) 
                    {
                        ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime();
                        response = metadataClient.Get(getMessage);
                    } 

                    ((IClientChannel)metadataClient).Close(); 
                } 
                finally
                { 
                    ((IClientChannel)metadataClient).Abort();
                }

                if (response.IsFault) 
                {
                    MessageFault fault = MessageFault.CreateFault(response, 64 * 1024); 
                    StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); 
                    XmlWriter xmlWriter = XmlWriter.Create(stringWriter);
                    fault.WriteTo(xmlWriter, response.Version.Envelope); 
                    xmlWriter.Flush();
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(stringWriter.ToString()));
                }
 
                return response.GetReaderAtBodyContents();
            } 
 
            internal override MetadataSection EndRetrieve(IAsyncResult result)
            { 
                try
                {
                    return AsyncMetadataReferenceRetriever.End(result);
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e) 
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                        SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
                }
            } 

            public override bool Equals(object obj) 
            { 
                return obj is MetadataReferenceRetriever && ((MetadataReferenceRetriever)obj).address == this.address;
            } 

            public override int GetHashCode()
            {
                return address.GetHashCode(); 
            }
 
            class AsyncMetadataReferenceRetriever : AsyncResult 
            {
                MetadataSection section; 
                Message message;
                internal AsyncMetadataReferenceRetriever(IMetadataExchange metadataClient, MessageVersion messageVersion, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
                    : base(callback, state)
                { 

                    message = MetadataReferenceRetriever.CreateGetMessage(messageVersion); 
                    ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime(); 
                    IAsyncResult result = metadataClient.BeginGet(message, DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.RequestCallback)), metadataClient);
 
                    if (result.CompletedSynchronously)
                    {
                        HandleResult(result);
 
                        this.Complete(true);
                    } 
                } 

                internal static MetadataSection End(IAsyncResult result) 
                {
                    AsyncMetadataReferenceRetriever retrieverResult = AsyncResult.End(result);
                    return retrieverResult.section;
                } 

                internal void RequestCallback(IAsyncResult result) 
                { 
                    if (result.CompletedSynchronously)
                        return; 

                    Exception exception = null;
                    try
                    { 
                        HandleResult(result);
                    } 
#pragma warning suppress 56500 // covered by FxCOP 
                    catch (Exception e)
                    { 
                        if (DiagnosticUtility.IsFatal(e))
                            throw;
                        exception = e;
                    } 
                    this.Complete(false, exception);
                } 
 
                void HandleResult(IAsyncResult result)
                { 
                    IMetadataExchange metadataClient = (IMetadataExchange)result.AsyncState;
                    Message response = metadataClient.EndGet(result);

                    using (this.message) 
                    {
                        if (response.IsFault) 
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBadMetadataReference,
                                ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString()))); 
                        }
                        else
                        {
                            using (XmlReader reader = response.GetReaderAtBodyContents()) 
                            {
                                section = MetadataRetriever.CreateMetadataSection(reader, ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString()); 
                            } 
                        }
                    } 
                }
            }

 
        }
 
        class AsyncMetadataResolver : AsyncResult 
        {
            ResolveCallState resolveCallState; 

            internal AsyncMetadataResolver(ResolveCallState resolveCallState, AsyncCallback callerCallback, object callerAsyncState)
                : base(callerCallback, callerAsyncState)
            { 
                if (resolveCallState == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("resolveCallState"); 
                }
 
                this.resolveCallState = resolveCallState;


                Exception exception = null; 
                bool doneResolving = false;
                try 
                { 
                    doneResolving = this.ResolveNext();
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;
                    exception = e; 
                    doneResolving = true; 
                }
 
                if (doneResolving)
                {
                    this.Complete(true, exception);
                } 
            }
 
            bool ResolveNext() 
            {
                bool doneResolving = false; 
                if (this.resolveCallState.StackedRetrievers.Count > 0)
                {
                    MetadataRetriever retriever = this.resolveCallState.StackedRetrievers.Pop();
 
                    if (resolveCallState.HasBeenUsed(retriever))
                    { 
                        doneResolving = this.ResolveNext(); 
                    }
                    else 
                    {
                        if (resolveCallState.ResolvedMaxResolvedReferences)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences))); 
                        }
                        else 
                        { 
                            resolveCallState.LogUse(retriever);
                            IAsyncResult result = retriever.BeginRetrieve(this.resolveCallState.TimeoutHelper, DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.RetrieveCallback)), retriever); 

                            if (result.CompletedSynchronously)
                            {
                                doneResolving = HandleResult(result); 
                            }
                        } 
                    } 
                }
                else 
                {
                    doneResolving = true;
                }
 
                return doneResolving;
            } 
 
            internal static MetadataSet End(IAsyncResult result)
            { 
                AsyncMetadataResolver resolverResult = AsyncResult.End(result);
                return resolverResult.resolveCallState.MetadataSet;
            }
 
            internal void RetrieveCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously) 
                    return;
 
                Exception exception = null;
                bool doneResolving = false;
                try
                { 
                    doneResolving = HandleResult(result);
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw;
                    exception = e;
                    doneResolving = true; 
                }
 
                if (doneResolving) 
                {
                    this.Complete(false, exception); 
                }
            }

            bool HandleResult(IAsyncResult result) 
            {
                MetadataRetriever retriever = (MetadataRetriever)result.AsyncState; 
                MetadataSection section = retriever.EndRetrieve(result); 
                this.resolveCallState.HandleSection(section);
                return this.ResolveNext(); 
            }
        }

 
        internal class EncodingHelper
        { 
            internal const string ApplicationBase = "application"; 

            internal static Encoding GetRfcEncoding(string contentTypeStr) 
            {
                Encoding e = null;
                ContentType contentType = null;
                try 
                {
                    contentType = new ContentType(contentTypeStr); 
                    string charset = contentType == null ? string.Empty : contentType.CharSet; 

                    if (charset != null && charset.Length > 0) 
                        e = Encoding.GetEncoding(charset);
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception ex) 
                {
                    if (DiagnosticUtility.IsFatal(ex)) 
                        throw; 
                }
 
                // default to ASCII encoding per RFC 2376/3023
                if (IsApplication(contentType))
                    return e == null ? new ASCIIEncoding() : e;
                else 
                    return e;
            } 
 
            internal static bool IsApplication(ContentType contentType)
            { 
                return string.Compare(contentType == null ? string.Empty : contentType.MediaType,
                    ApplicationBase, StringComparison.OrdinalIgnoreCase) == 0;
            }
 
            internal static Encoding GetDictionaryReaderEncoding(string contentTypeStr)
            { 
                if (String.IsNullOrEmpty(contentTypeStr)) 
                    return TextEncoderDefaults.Encoding;
 
                Encoding encoding = GetRfcEncoding(contentTypeStr);

                if (encoding == null)
                    return TextEncoderDefaults.Encoding; 

                string charSet = encoding.WebName; 
                Encoding[] supportedEncodings = TextEncoderDefaults.SupportedEncodings; 
                for (int i = 0; i < supportedEncodings.Length; i++)
                { 
                    if (charSet == supportedEncodings[i].WebName)
                        return encoding;
                }
 
                return TextEncoderDefaults.Encoding;
            } 
        } 
    }
 
    public enum MetadataExchangeClientMode
    {
        MetadataExchange,
        HttpGet, 
    }
 
    static class MetadataExchangeClientModeHelper 
    {
        static public bool IsDefined(MetadataExchangeClientMode x) 
        {
            return
                x == MetadataExchangeClientMode.MetadataExchange ||
                x == MetadataExchangeClientMode.HttpGet || 
                false;
        } 
 
        public static void Validate(MetadataExchangeClientMode value)
        { 
            if (!IsDefined(value))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
                    typeof(MetadataExchangeClientMode))); 
            }
        } 
    } 

 
}


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


                        

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