WsdlImporter.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 / WsdlImporter.cs / 2 / WsdlImporter.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Description
{ 
    using System.Diagnostics;
    using System.Xml; 
    using System.ServiceModel.Channels; 
    using System.ServiceModel;
    using System.Xml.Schema; 
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization; 
    using WsdlNS = System.Web.Services.Description;
    using WsdlConfigNS = System.Web.Services.Configuration; 
    using ConfigNS = System.ServiceModel.Configuration; 
    using System.Text;
    using System.IO; 
    using System.Security;

    public class WsdlImporter : MetadataImporter
    { 
        readonly Dictionary importErrors = new Dictionary();
        bool isFaulted = false; 
 
        readonly Dictionary importedPortTypes = new Dictionary();
        readonly Dictionary importedBindings = new Dictionary(); 
        readonly Dictionary importedPorts = new Dictionary();

        readonly KeyedByTypeCollection wsdlExtensions;
 
        readonly WsdlNS.ServiceDescriptionCollection wsdlDocuments = new WsdlNS.ServiceDescriptionCollection();
        readonly XmlSchemaSet xmlSchemas = WsdlExporter.GetEmptySchemaSet(); 
        readonly Dictionary policyDocuments = new Dictionary(); 
        readonly Dictionary warnings = new Dictionary();
        WsdlPolicyReader wsdlPolicyReader; 

        bool beforeImportCalled = false;

        public WsdlImporter(MetadataSet metadata) 
            : this(metadata, null, null, MetadataImporterQuotas.Defaults)
        { 
        } 

        public WsdlImporter(MetadataSet metadata, IEnumerable policyImportExtensions, 
            IEnumerable wsdlImportExtensions)
            : this(metadata, policyImportExtensions, wsdlImportExtensions, MetadataImporterQuotas.Defaults)
        {
        } 

        public WsdlImporter(MetadataSet metadata, IEnumerable policyImportExtensions, 
            IEnumerable wsdlImportExtensions, MetadataImporterQuotas quotas) 
            : base(policyImportExtensions, quotas)
        { 
            // process wsdl extensions first for consistency with policy extensions (which are processed in base ctor)
            if (wsdlImportExtensions == null)
            {
                wsdlImportExtensions = LoadWsdlExtensionsFromConfig(); 
            }
 
            this.wsdlExtensions = new KeyedByTypeCollection(wsdlImportExtensions); 

            // then look at metadata 
            if (metadata == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadata");

            this.ProcessMetadataDocuments(metadata.MetadataSections); 
        }
 
        public KeyedByTypeCollection WsdlImportExtensions 
        {
            get { return this.wsdlExtensions; } 
        }

        public WsdlNS.ServiceDescriptionCollection WsdlDocuments
        { 
            get { return this.wsdlDocuments; }
        } 
 
        public XmlSchemaSet XmlSchemas
        { 
            get { return this.xmlSchemas; }
        }

        WsdlPolicyReader PolicyReader 
        {
            get 
            { 
                if (this.wsdlPolicyReader == null)
                { 
                    this.wsdlPolicyReader = new WsdlPolicyReader(this);
                }
                return wsdlPolicyReader;
            } 
        }
 
        //Consider this should be made public 
        internal override XmlElement ResolvePolicyReference(string policyReference, XmlElement contextAssertion)
        { 
            return this.PolicyReader.ResolvePolicyReference(policyReference, contextAssertion);
        }

        public override Collection ImportAllContracts() 
        {
            if (this.isFaulted) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 

            EnsureBeforeImportCalled(); 
            Collection contracts = new Collection();
            foreach (WsdlNS.ServiceDescription wsdl in this.wsdlDocuments)
                foreach (WsdlNS.PortType wsdlPortType in wsdl.PortTypes)		/* SSS_WARNINGS_OFF */
                { 
                    if (IsBlackListed(wsdlPortType))
                        continue; 
 
                    ContractDescription contract = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.DoNotThrowExceptions);
                    if (contract != null) 
                        contracts.Add(contract);
                }
            return contracts;
        } 

        public override ServiceEndpointCollection ImportAllEndpoints() 
        { 
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 

            EnsureBeforeImportCalled();
            ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
            foreach (WsdlNS.Port wsdlPort in this.GetAllPorts()) 
            {
                if (IsBlackListed(wsdlPort)) 
                    continue; 

                ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions); 
                if (endpoint != null)
                    endpoints.Add(endpoint);
            }
            return endpoints; 
        }
 
        public Collection ImportAllBindings() 
        {
            if (this.isFaulted) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));

            EnsureBeforeImportCalled();
            Collection bindings = new Collection(); 
            foreach (WsdlNS.Binding wsdlBinding in this.GetAllBindings())
            { 
                WsdlEndpointConversionContext importedBindingContext = null; 
                if (IsBlackListed(wsdlBinding))
                    continue; 

                importedBindingContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.DoNotThrowExceptions);
                if (importedBindingContext != null)
                    bindings.Add(importedBindingContext.Endpoint.Binding); 
            }
            return bindings; 
        } 

        // WSDL Specific methods 
        public ContractDescription ImportContract(WsdlNS.PortType wsdlPortType)
        {
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 

            if (wsdlPortType == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType"); 

            return ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions); 
        }

        public Binding ImportBinding(WsdlNS.Binding wsdlBinding)
        { 
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 
 
            if (wsdlBinding == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding"); 

            return ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions).Endpoint.Binding;
        }
 
        public ServiceEndpoint ImportEndpoint(WsdlNS.Port wsdlPort)
        { 
            if (this.isFaulted) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
 
            if (wsdlPort == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPort");

            return ImportWsdlPort(wsdlPort, ErrorBehavior.RethrowExceptions); 
        }
 
        public ServiceEndpointCollection ImportEndpoints(WsdlNS.PortType wsdlPortType) 
        {
            if (this.isFaulted) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));

            if (wsdlPortType == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType"); 

            if (IsBlackListed(wsdlPortType)) 
                throw CreateAlreadyFaultedException(wsdlPortType); 
            else
                ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions); 

            ServiceEndpointCollection endpoints = new ServiceEndpointCollection();

            foreach (WsdlNS.Binding wsdlBinding in FindBindingsForPortType(wsdlPortType)) 
                if (!IsBlackListed(wsdlBinding))
                    foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding)) 
                        endpoints.Add(endpoint); 

            return endpoints; 
        }

        internal ServiceEndpointCollection ImportEndpoints(ContractDescription contract)
        { 
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 
 
            if (contract == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract"); 

            if (!this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract)))
            {
                DiagnosticUtility.DebugAssert("WsdlImporter.ImportEndpoints(ContractDescription contract): !this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract))"); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.WsdlImporterContractMustBeInKnownContracts)));
            } 
 
            EnsureBeforeImportCalled();
            ServiceEndpointCollection endpoints = new ServiceEndpointCollection(); 

            foreach (WsdlNS.Binding wsdlBinding in FindBindingsForContract(contract))
                if (!IsBlackListed(wsdlBinding))
                    foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding)) 
                        endpoints.Add(endpoint);
 
            return endpoints; 
        }
 
        public ServiceEndpointCollection ImportEndpoints(WsdlNS.Binding wsdlBinding)
        {
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted))); 

            if (wsdlBinding == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding"); 

            if (IsBlackListed(wsdlBinding)) 
                throw CreateAlreadyFaultedException(wsdlBinding);
            else
                ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions);
 
            ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
 
            foreach (WsdlNS.Port wsdlPort in FindPortsForBinding(wsdlBinding)) 
                if (!IsBlackListed(wsdlPort))
                { 
                    ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
                    if (endpoint != null)
                        endpoints.Add(endpoint);
                } 

            return endpoints; 
        } 

        public ServiceEndpointCollection ImportEndpoints(WsdlNS.Service wsdlService) 
        {
            if (this.isFaulted)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
 
            if (wsdlService == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlService"); 
 
            EnsureBeforeImportCalled();
            ServiceEndpointCollection endpoints = new ServiceEndpointCollection(); 

            foreach (WsdlNS.Port wsdlPort in wsdlService.Ports)
                if (!IsBlackListed(wsdlPort))
                { 
                    ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
                    if (endpoint != null) 
                        endpoints.Add(endpoint); 
                }
 
            return endpoints;
        }

        bool IsBlackListed(WsdlNS.NamedItem item) 
        {
            return importErrors.ContainsKey(item); 
        } 

        ContractDescription ImportWsdlPortType(WsdlNS.PortType wsdlPortType, WsdlPortTypeImportOptions importOptions, ErrorBehavior errorBehavior) 
        {
            if (IsBlackListed(wsdlPortType))
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPortType));
 

            XmlQualifiedName wsdlPortTypeQName = new XmlQualifiedName(wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace); 
            ContractDescription contractDescription = null; 

            if (importOptions == WsdlPortTypeImportOptions.IgnoreExistingContracts || !TryFindExistingContract(wsdlPortTypeQName, out contractDescription)) 
            {
                EnsureBeforeImportCalled();

                try 
                {
 
                    contractDescription = CreateContractDescription(wsdlPortType, wsdlPortTypeQName); 
                    WsdlContractConversionContext contractContext = new WsdlContractConversionContext(contractDescription, wsdlPortType);
 
                    foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
                    {

                        OperationDescription operationDescription = CreateOperationDescription(wsdlPortType, wsdlOperation, contractDescription); 
                        contractContext.AddOperation(operationDescription, wsdlOperation);
 
                        foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages) 
                        {
                            MessageDescription messageDescription; 
                            if (TryCreateMessageDescription(wsdlOperationMessage, operationDescription, out messageDescription))
                                contractContext.AddMessage(messageDescription, wsdlOperationMessage);
                        }
 
                        foreach (WsdlNS.OperationFault wsdlOperationFault in wsdlOperation.Faults)
                        { 
                            FaultDescription faultDescription; 
                            if (TryCreateFaultDescription(wsdlOperationFault, operationDescription, out faultDescription))
                                contractContext.AddFault(faultDescription, wsdlOperationFault); 
                        }
                    }

                    CallImportContract(contractContext); 
                    VerifyImportedWsdlPortType(wsdlPortType);
 
                    importedPortTypes.Add(wsdlPortTypeQName, contractContext); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    WsdlImportException wie = WsdlImportException.Create(wsdlPortType, e);
                    LogImportError(wsdlPortType, wie); 
                    if (errorBehavior == ErrorBehavior.RethrowExceptions) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
                    else 
                        return null;
                }
            }
 
            return contractDescription;
        } 
 
        WsdlEndpointConversionContext ImportWsdlBinding(WsdlNS.Binding wsdlBinding, ErrorBehavior errorBehavior)
        { 
            //Check for exisiting exception
            if (IsBlackListed(wsdlBinding))
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlBinding));
 
            XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
            WsdlEndpointConversionContext bindingEndpointContext = null; 
 

 

            if (!importedBindings.TryGetValue(wsdlBindingQName, out bindingEndpointContext))
            {
                EnsureBeforeImportCalled(); 

                try 
                { 
                    bool wasExistingContract;
                    ContractDescription contractDescription = GetOrImportContractDescription(wsdlBinding.Type, out wasExistingContract); 
                    WsdlContractConversionContext contractContext = null;
                    importedPortTypes.TryGetValue(wsdlBinding.Type, out contractContext);

                    ServiceEndpoint newWsdlBindingEndpoint = new ServiceEndpoint(contractDescription); 
                    bindingEndpointContext = new WsdlEndpointConversionContext(contractContext, newWsdlBindingEndpoint, wsdlBinding, null);
 
                    foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations) 
                        try
                        { 
                            OperationDescription operation = Binding2DescriptionHelper.FindOperationDescription(wsdlOperationBinding, wsdlDocuments, bindingEndpointContext);
                            bindingEndpointContext.AddOperationBinding(operation, wsdlOperationBinding);

                            for(int i=0; i < operation.Messages.Count ; i++) 
                            {
                                MessageDescription message = operation.Messages[i]; 
                                WsdlNS.MessageBinding wsdlMessageBinding = Binding2DescriptionHelper.FindMessageBinding(wsdlOperationBinding, message); 

                                bindingEndpointContext.AddMessageBinding(message, wsdlMessageBinding); 
                            }

                            foreach (FaultDescription fault in operation.Faults)
                            { 
                                WsdlNS.FaultBinding wsdlFaultBinding = Binding2DescriptionHelper.FindFaultBinding(wsdlOperationBinding, fault);
                                if (wsdlFaultBinding != null) 
                                { 
                                    bindingEndpointContext.AddFaultBinding(fault, wsdlFaultBinding);
                                } 
                            }
                        }
#pragma warning suppress 56500 // covered by FxCOP
                        catch (Exception e) 
                        {
                            if (DiagnosticUtility.IsFatal(e)) 
                                throw; 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
                        } 

                    XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlBinding);
                    newWsdlBindingEndpoint.Binding = CreateBinding(bindingEndpointContext, bindingQName);
 
                    CallImportEndpoint(bindingEndpointContext);
                    VerifyImportedWsdlBinding(wsdlBinding); 
                    importedBindings.Add(wsdlBindingQName, bindingEndpointContext); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    WsdlImportException wie = WsdlImportException.Create(wsdlBinding, e);
                    LogImportError(wsdlBinding, wie); 
                    if (errorBehavior == ErrorBehavior.RethrowExceptions) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
                    else 
                        return null;
                }
            }
            return bindingEndpointContext; 
        }
 
        ServiceEndpoint ImportWsdlPort(WsdlNS.Port wsdlPort, ErrorBehavior errorBehavior) 
        {
            if (IsBlackListed(wsdlPort)) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPort));		/* SSS_WARNINGS_ON */


            ServiceEndpoint endpoint = null; 
            if (!importedPorts.TryGetValue(wsdlPort, out endpoint))
            { 
                EnsureBeforeImportCalled(); 

                try 
                {
                    WsdlNS.Binding wsdlBinding = this.wsdlDocuments.GetBinding(wsdlPort.Binding);

                    WsdlEndpointConversionContext bindingEndpointContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions); 

                    WsdlEndpointConversionContext endpointContext; 
                    endpoint = new ServiceEndpoint(bindingEndpointContext.Endpoint.Contract); 
                    endpoint.Name = WsdlNamingHelper.GetEndpointName(wsdlPort).EncodedName;
 
                    endpointContext = new WsdlEndpointConversionContext(bindingEndpointContext, endpoint, wsdlPort);

                    if (WsdlPolicyReader.HasPolicy(wsdlPort))
                    { 
                        XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlPort);
                        endpoint.Binding = CreateBinding(endpointContext, bindingQName); 
                    } 
                    else
                    { 
                        endpoint.Binding = bindingEndpointContext.Endpoint.Binding;
                    }

                    CallImportEndpoint(endpointContext); 
                    VerifyImportedWsdlPort(wsdlPort);
                    importedPorts.Add(wsdlPort, endpoint); 
 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    WsdlImportException wie = WsdlImportException.Create(wsdlPort, e);
                    LogImportError(wsdlPort, wie); 
                    if (errorBehavior == ErrorBehavior.RethrowExceptions) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
                    else 
                        return null;
                }
            }
 
            return endpoint;
        } 
 
        static bool TryCreateMessageDescription(WsdlNS.OperationMessage wsdlOperationMessage, OperationDescription operationDescription, out MessageDescription messageDescription)
        { 
            string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationMessage);
            MessageDirection direction;

            if (wsdlOperationMessage is WsdlNS.OperationInput) 
                direction = MessageDirection.Input;
            else if (wsdlOperationMessage is WsdlNS.OperationOutput) 
                direction = MessageDirection.Output; 
            else
            { 
                messageDescription = null;
                return false;
            }
 
            messageDescription = new MessageDescription(actionUri, direction);
            messageDescription.MessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage); 
            messageDescription.XsdTypeName = wsdlOperationMessage.Message; 
            operationDescription.Messages.Add(messageDescription);
            return true; 
        }

        static bool TryCreateFaultDescription(WsdlNS.OperationFault wsdlOperationFault, OperationDescription operationDescription, out FaultDescription faultDescription)
        { 

            if (string.IsNullOrEmpty(wsdlOperationFault.Name)) 
            { 
                faultDescription = null;
                return false; 
            }

            string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationFault);
            faultDescription = new FaultDescription(actionUri); 
            faultDescription.SetNameOnly(new XmlName(wsdlOperationFault.Name, true /*isEncoded*/));
            operationDescription.Faults.Add(faultDescription); 
            return true; 
        }
 
        ContractDescription CreateContractDescription(WsdlNS.PortType wsdlPortType, XmlQualifiedName wsdlPortTypeQName)
        {
            ContractDescription contractDescription;
            XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName); 
            contractDescription = new ContractDescription(contractQName.Name, contractQName.Namespace);
            NetSessionHelper.SetSession(contractDescription, wsdlPortType); 
            return contractDescription; 
        }
 
        OperationDescription CreateOperationDescription(WsdlNS.PortType wsdlPortType, WsdlNS.Operation wsdlOperation, ContractDescription contract)
        {
            string operationName = WsdlNamingHelper.GetOperationName(wsdlOperation);
            OperationDescription operationDescription = new OperationDescription(operationName, contract); 
            NetSessionHelper.SetInitiatingTerminating(operationDescription, wsdlOperation);
            contract.Operations.Add(operationDescription); 
            return operationDescription; 
        }
 
        Binding CreateBinding(WsdlEndpointConversionContext endpointContext, XmlQualifiedName bindingQName)
        {
            try
            { 
                // either the wsdl:binding has already been imported or the wsdl:port has policy
                BindingElementCollection bindingElements = ImportPolicyFromWsdl(endpointContext); 
                CustomBinding binding = new CustomBinding(bindingElements); 
                // use decoded form to preserve the user-given friendly name
                binding.Name = NamingHelper.CodeName(bindingQName.Name); 
                binding.Namespace = bindingQName.Namespace;

                return binding;
 
            }
#pragma warning suppress 56500 // covered by FxCOP 
            catch (Exception e) 
            {
                if (DiagnosticUtility.IsFatal(e)) 
                    throw;
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, e));
            }
        } 

        ContractDescription GetOrImportContractDescription(XmlQualifiedName wsdlPortTypeQName, out bool wasExistingContractDescription) 
        { 
            ContractDescription contractDescription;
 
            if (!TryFindExistingContract(wsdlPortTypeQName, out contractDescription))
            {
                WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlPortTypeQName);
 
                contractDescription = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.IgnoreExistingContracts, ErrorBehavior.RethrowExceptions);
 
                wasExistingContractDescription = false; 
            }
 
            wasExistingContractDescription = true;
            return contractDescription;
        }
 
        void ProcessMetadataDocuments(IEnumerable metadataSections)
        { 
 
            foreach (MetadataSection doc in metadataSections)
            { 
                try
                {
                    if (doc.Metadata is MetadataReference || doc.Metadata is MetadataLocation)
                        continue; 

                    if (doc.Dialect == MetadataSection.ServiceDescriptionDialect) 
                    { 
                        wsdlDocuments.Add(TryConvert(doc));
                    } 
                    if (doc.Dialect == MetadataSection.XmlSchemaDialect)
                    {
                        xmlSchemas.Add(TryConvert(doc));
                    } 
                    if (doc.Dialect == MetadataSection.PolicyDialect)
                    { 
                        if (string.IsNullOrEmpty(doc.Identifier)) 
                        {
                            LogImportWarning(SR.GetString(SR.PolicyDocumentMustHaveIdentifier)); 
                        }
                        else
                        {
                            policyDocuments.Add(doc.Identifier, TryConvert(doc)); 
                        }
                    } 
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(doc.Identifier, e)); 
                }
            } 
        } 

        T TryConvert(MetadataSection doc) 
        {
            try
            {
                return ((T)doc.Metadata); 
            }
            catch (InvalidCastException) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(
                    SR.GetString(SR.SFxBadMetadataDialect, doc.Identifier, doc.Dialect, typeof(T).FullName, doc.GetType().FullName))); 
            }
        }

        bool TryFindExistingContract(XmlQualifiedName wsdlPortTypeQName, out ContractDescription existingContract) 
        {
            XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName); 
 
            // Scan Known Contracts first because wsdl:portType may not be available
            if (this.KnownContracts.TryGetValue(contractQName, out existingContract)) 
                return true;

            WsdlContractConversionContext contractContext;
            if (importedPortTypes.TryGetValue(wsdlPortTypeQName, out contractContext)) 
            {
                existingContract = contractContext.Contract; 
                return true; 
            }
 
            return false;
        }

        void EnsureBeforeImportCalled() 
        {
            if (!beforeImportCalled) 
            { 
                foreach (IWsdlImportExtension extension in this.wsdlExtensions)
                { 
                    try
                    {
                        extension.BeforeImport(this.wsdlDocuments, this.xmlSchemas, this.policyDocuments.Values);
                    } 
#pragma warning suppress 56500 // covered by FxCOP
                    catch (Exception e) 
                    { 
                        this.isFaulted = true;
                        if (DiagnosticUtility.IsFatal(e)) 
                            throw;
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBeforeImportExtensionException(extension, e));
                    }
                } 
                beforeImportCalled = true;
            } 
        } 

        void CallImportContract(WsdlContractConversionContext contractConversionContext) 
        {
            foreach (IWsdlImportExtension extension in this.wsdlExtensions)
                try
                { 
                    extension.ImportContract(this, contractConversionContext);
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
                } 
        }
 
        void CallImportEndpoint(WsdlEndpointConversionContext endpointConversionContext) 
        {
            foreach (IWsdlImportExtension extension in this.wsdlExtensions) 
                try
                {
                    extension.ImportEndpoint(this, endpointConversionContext);
 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
                }
        } 

        void VerifyImportedWsdlPortType(WsdlNS.PortType wsdlPortType) 
        { 
            VerifyImportedExtensions(wsdlPortType);
            foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations) 
            {
                VerifyImportedExtensions(wsdlOperation);

                foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages) 
                {
                    VerifyImportedExtensions(wsdlOperationMessage); 
                } 

                foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Faults) 
                {
                    VerifyImportedExtensions(wsdlOperationMessage);
                }
            } 
        }
 
        void VerifyImportedWsdlBinding(WsdlNS.Binding wsdlBinding) 
        {
            VerifyImportedExtensions(wsdlBinding); 
            foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
            {
                VerifyImportedExtensions(wsdlOperationBinding);
 
                if (wsdlOperationBinding.Input != null)
                { 
                    VerifyImportedExtensions(wsdlOperationBinding.Input); 
                }
 
                if (wsdlOperationBinding.Output != null)
                {
                    VerifyImportedExtensions(wsdlOperationBinding.Output);
                } 

                foreach (WsdlNS.MessageBinding wsdlMessageBinding in wsdlOperationBinding.Faults) 
                { 
                    VerifyImportedExtensions(wsdlMessageBinding);
                } 
            }
        }

        void VerifyImportedWsdlPort(WsdlNS.Port wsdlPort) 
        {
            VerifyImportedExtensions(wsdlPort); 
        } 

        void VerifyImportedExtensions(WsdlNS.NamedItem item) 
        {
            foreach (object ext in item.Extensions)
            {
                if (item.Extensions.IsHandled(ext)) 
                    continue;
 
                XmlQualifiedName qName = GetUnhandledExtensionQName(ext, item); 

                if (item.Extensions.IsRequired(ext) || IsNonSoapWsdl11BindingExtension(ext)) 
                {
                    string errorMsg = SR.GetString(SR.RequiredWSDLExtensionIgnored, qName.Name, qName.Namespace);
                    WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(errorMsg));
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie); 
                }
                else 
                { 
                    string xPath = CreateXPathString(item);
                    string errorMsg = SR.GetString(SR.OptionalWSDLExtensionIgnored, qName.Name, qName.Namespace, xPath); 
                    this.Errors.Add(new MetadataConversionError(errorMsg, true));
                }
            }
        } 

        static bool IsNonSoapWsdl11BindingExtension(object ext) 
        { 
            if (ext is WsdlNS.HttpAddressBinding
                || ext is WsdlNS.HttpBinding 
                || ext is WsdlNS.HttpOperationBinding
                || ext is WsdlNS.HttpUrlEncodedBinding
                || ext is WsdlNS.HttpUrlReplacementBinding
                || ext is WsdlNS.MimeContentBinding 
                || ext is WsdlNS.MimeMultipartRelatedBinding
                || ext is WsdlNS.MimePart 
                || ext is WsdlNS.MimeTextBinding 
                || ext is WsdlNS.MimeXmlBinding
                ) 
            {
                return true;
            }
 
            return false;
 
        } 

        XmlQualifiedName GetUnhandledExtensionQName(object extension, WsdlNS.NamedItem item) 
        {
            XmlElement element = extension as XmlElement;
            if (element != null)
            { 
                return new XmlQualifiedName(element.LocalName, element.NamespaceURI);
            } 
            else if (extension is WsdlNS.ServiceDescriptionFormatExtension) 
            {
                WsdlConfigNS.XmlFormatExtensionAttribute[] xfeAttributes 
                    = (WsdlConfigNS.XmlFormatExtensionAttribute[])ServiceReflector.GetCustomAttributes(extension.GetType(),
                    typeof(WsdlConfigNS.XmlFormatExtensionAttribute), false);

                if (xfeAttributes.Length > 0) 
                {
                    return new XmlQualifiedName(xfeAttributes[0].ElementName, xfeAttributes[0].Namespace); 
                } 
            }
            WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(SR.GetString(SR.UnknownWSDLExtensionIgnored, extension.GetType().AssemblyQualifiedName))); 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
        }

        internal static class Binding2DescriptionHelper 
        {
            internal static OperationDescription FindOperationDescription(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments, WsdlEndpointConversionContext endpointContext) 
            { 

                OperationDescription operation; 
                if (endpointContext.ContractConversionContext != null)
                {
                    WsdlNS.Operation wsdlOperation = FindWsdlOperation(wsdlOperationBinding, wsdlDocuments);
                    operation = endpointContext.ContractConversionContext.GetOperationDescription(wsdlOperation); 
                }
                else 
                { 
                    operation = FindOperationDescription(endpointContext.Endpoint.Contract, wsdlOperationBinding);
                } 
                return operation;
            }

            internal static WsdlNS.MessageBinding FindMessageBinding(WsdlNS.OperationBinding wsdlOperationBinding, MessageDescription message) 
            {
                WsdlNS.MessageBinding wsdlMessageBinding; 
                if (message.Direction == MessageDirection.Input) 
                {
                    wsdlMessageBinding = wsdlOperationBinding.Input; 
                }
                else
                {
                    wsdlMessageBinding = wsdlOperationBinding.Output; 
                }
                return wsdlMessageBinding; 
            } 

            internal static WsdlNS.FaultBinding FindFaultBinding(WsdlNS.OperationBinding wsdlOperationBinding, FaultDescription fault) 
            {
                foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
                    if (faultBinding.Name == fault.Name)
                        return faultBinding; 
                return null;
            } 
 
            static WsdlNS.Operation FindWsdlOperation(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments)
            { 
                WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlOperationBinding.Binding.Type);


                if (wsdlOperationBinding.Name == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpNoName, wsdlOperationBinding.Binding.Name))); 
                } 

                foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations) 
                    if (wsdlOperation.Name == wsdlOperationBinding.Name && IsOperationBoundBy(wsdlOperationBinding, wsdlOperation))
                        return wsdlOperation;

                //unable to find wsdloperation for wsdlOperationBinding, invalid wsdl binding 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpMismatch2, wsdlOperationBinding.Binding.Name, wsdlOperationBinding.Name)));
            } 
 
            internal static bool IsOperationBoundBy(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.Operation wsdlOperation)
            { 
                foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
                {
                    WsdlNS.MessageBinding wsdlMessageBinding;
                    if (wsdlOperationMessage is WsdlNS.OperationInput) 
                        wsdlMessageBinding = wsdlOperationBinding.Input;
                    else 
                        wsdlMessageBinding = wsdlOperationBinding.Output; 

                    if (wsdlMessageBinding == null || wsdlMessageBinding.Name != wsdlOperationMessage.Name) 
                        return false;
                }
                return true;
            } 

            static OperationDescription FindOperationDescription(ContractDescription contract, WsdlNS.OperationBinding wsdlOperationBinding) 
            { 
                foreach (OperationDescription operationDescription in contract.Operations)
                { 
                    if (CompareOperations(operationDescription, contract, wsdlOperationBinding))
                        return operationDescription;
                }
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnableToLocateOperation2, wsdlOperationBinding.Name, contract.Name)));
            } 
 
            static bool CompareOperations(OperationDescription operationDescription, ContractDescription parentContractDescription, WsdlNS.OperationBinding wsdlOperationBinding)
            { 
                string wsdlOperationName = WsdlExporter.WsdlNamingHelper.GetWsdlOperationName(operationDescription, parentContractDescription);

                if (wsdlOperationName != wsdlOperationBinding.Name)
                    return false; 

                if (operationDescription.Messages.Count > 2) 
                    return false; 

                // Either both have output message or neither have an output message; 
                if (FindMessage(operationDescription.Messages, MessageDirection.Output) != (wsdlOperationBinding.Output != null))
                    return false;

                // Either both have output message or neither have an output message; 
                if (FindMessage(operationDescription.Messages, MessageDirection.Input) != (wsdlOperationBinding.Input != null))
                    return false; 
 
                return true;
 
            }

            private static bool FindMessage(MessageDescriptionCollection messageDescriptionCollection, MessageDirection transferDirection)
            { 
                foreach (MessageDescription message in messageDescriptionCollection)
                    if (message.Direction == transferDirection) 
                        return true; 
                return false;
            } 

        }

        internal static class WSAddressingHelper 
        {
            internal static string GetWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage) 
            { 
                string actionUri = FindWsaActionAttribute(wsdlOperationMessage);
                return (actionUri == null) ? CreateDefaultWsaActionUri(wsdlOperationMessage) : actionUri; 
            }

            internal static string FindWsaActionAttribute(WsdlNS.OperationMessage wsdlOperationMessage)
            { 
                XmlAttribute[] attributes = wsdlOperationMessage.ExtensibleAttributes;
                if (attributes != null && attributes.Length > 0) 
                { 
                    foreach (XmlAttribute attribute in attributes)
                    { 
                        if ((attribute.NamespaceURI == MetadataStrings.AddressingWsdl.NamespaceUri
                             || attribute.NamespaceURI == MetadataStrings.AddressingMetadata.NamespaceUri)
                            && attribute.LocalName == MetadataStrings.AddressingMetadata.Action)
                        { 
                            return attribute.Value;
                        } 
                    } 
                }
 
                return null;
            }

            static string CreateDefaultWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage) 
            {
                if (wsdlOperationMessage is WsdlNS.OperationFault) 
                    return AddressingVersion.WSAddressing10.DefaultFaultAction; 

                // We figure out default action. All specifications' rules below are the same. 
                // Using [WSDL Binding W3C Working Draft 13 April 2005] Section 3.3
                // Using [WSDL Binding W3C Candidate Recommendation 29 May 2006] Section 4.4.4
                // Using [Metadata W3C Working Draft 13 16 May 2007] Section 4.4.4
 
                string ns = wsdlOperationMessage.Operation.PortType.ServiceDescription.TargetNamespace ?? string.Empty;
                string portTypeName = wsdlOperationMessage.Operation.PortType.Name; 
                XmlName operationMessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage); 

                string delimiter = ns.StartsWith("urn:", StringComparison.OrdinalIgnoreCase) ? ":" : "/" ; 

                string baseActionUri = ns.EndsWith(delimiter, StringComparison.OrdinalIgnoreCase) ? ns : ns + delimiter;

                string actionUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}", baseActionUri, portTypeName, delimiter, operationMessageName.EncodedName); 

                return actionUri; 
            } 

            internal static EndpointAddress ImportAddress(WsdlNS.Port wsdlPort) 
            {
                //Try to read Endpoint Address from WsdlPort
                if (wsdlPort != null)
                { 
                    XmlElement addressing10Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing10Strings.Namespace);
                    XmlElement addressing200408Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing200408Strings.Namespace); 
                    WsdlNS.SoapAddressBinding soapAddressBinding = (WsdlNS.SoapAddressBinding)wsdlPort.Extensions.Find(typeof(WsdlNS.SoapAddressBinding)); 

                    // 
                    if (addressing10Element != null)
                    {
                        return EndpointAddress.ReadFrom(AddressingVersion.WSAddressing10, new XmlNodeReader(addressing10Element));
                    } 
                    if (addressing200408Element != null)
                    { 
                        return EndpointAddress.ReadFrom(AddressingVersion.WSAddressingAugust2004, new XmlNodeReader(addressing200408Element)); 
                    }
                    else if (soapAddressBinding != null) 
                    {
                        return new EndpointAddress(soapAddressBinding.Location);
                    }
 
                }
                return null; 
            } 

            internal static AddressingVersion FindAddressingVersion(PolicyConversionContext policyContext) 
            {
                if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
                            MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing,
                            MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri, true /*remove*/) != null) 
                {
                    return AddressingVersion.WSAddressing10; 
                } 
                else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
                            MetadataStrings.Addressing10.MetadataPolicy.Addressing, 
                            MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, true /*remove*/) != null)
                {
                    return AddressingVersion.WSAddressing10;
                } 
                else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
                            MetadataStrings.Addressing200408.Policy.UsingAddressing, 
                            MetadataStrings.Addressing200408.Policy.NamespaceUri, true /*remove*/) != null) 
                {
                    return AddressingVersion.WSAddressingAugust2004; 
                }
                else
                {
                    return AddressingVersion.None; 
                }
            } 
 
            internal static SupportedAddressingMode DetermineSupportedAddressingMode(MetadataImporter importer, PolicyConversionContext context)
            { 
                // Do not remove this assertion - the message encoding binding element importer owns it.
                XmlElement addressingAssertion = PolicyConversionContext.FindAssertion(context.GetBindingAssertions(),
                    MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, false);
 
                if (addressingAssertion != null)
                { 
                    XmlElement policyElement = null; 
                    foreach (XmlNode node in addressingAssertion.ChildNodes)
                    { 
                        if (node is XmlElement && MetadataSection.IsPolicyElement((XmlElement)node))
                        {
                            policyElement = (XmlElement)node;
                            break; 
                        }
                    } 
 
                    if (policyElement == null)
                    { 
                        string message = SR.GetString(SR.ElementRequired, MetadataStrings.Addressing10.MetadataPolicy.Prefix,
                            MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.WSPolicy.Prefix,
                            MetadataStrings.WSPolicy.Elements.Policy);
 
                        importer.Errors.Add(new MetadataConversionError(message, false));
                        return SupportedAddressingMode.Anonymous; 
                    } 

                    IEnumerable> alternatives = importer.NormalizePolicy(new XmlElement[] { policyElement }); 
                    foreach (IEnumerable alternative in alternatives)
                    {
                        foreach (XmlElement element in alternative)
                        { 
                            if (element.NamespaceURI == MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri)
                            { 
                                if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses) 
                                {
                                    return SupportedAddressingMode.NonAnonymous; 
                                }
                                else if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses)
                                {
                                    return SupportedAddressingMode.Anonymous; 
                                }
                            } 
                        } 
                    }
                } 

                return SupportedAddressingMode.Anonymous;
            }
        } 

        static class WsdlNamingHelper 
        { 
            internal static XmlQualifiedName GetBindingName(WsdlNS.Binding wsdlBinding)
            { 
                XmlName xmlName = new XmlName(wsdlBinding.Name, true /*isEncoded*/);
                return new XmlQualifiedName(xmlName.EncodedName, wsdlBinding.ServiceDescription.TargetNamespace);
            }
 
            internal static XmlQualifiedName GetBindingName(WsdlNS.Port wsdlPort)
            { 
                // [....]: composing names have potential problem of generating name that looks like an encoded name, consider avoiding '_' 
                XmlName xmlName = new XmlName(string.Format(CultureInfo.InvariantCulture, "{0}_{1}", wsdlPort.Service.Name, wsdlPort.Name), true /*isEncoded*/);
                return new XmlQualifiedName(xmlName.EncodedName, wsdlPort.Service.ServiceDescription.TargetNamespace); 
            }

            internal static XmlName GetEndpointName(WsdlNS.Port wsdlPort)
            { 
                return new XmlName(wsdlPort.Name, true /*isEncoded*/);
            } 
 
            internal static XmlQualifiedName GetContractName(XmlQualifiedName wsdlPortTypeQName)
            { 
                return wsdlPortTypeQName;
            }

            internal static string GetOperationName(WsdlNS.Operation wsdlOperation) 
            {
                    return wsdlOperation.Name; 
            } 

            internal static XmlName GetOperationMessageName(WsdlNS.OperationMessage wsdlOperationMessage) 
            {
                string messageName = null;
                if (!string.IsNullOrEmpty(wsdlOperationMessage.Name))
                { 
                    messageName = wsdlOperationMessage.Name;
                } 
                else if (wsdlOperationMessage.Operation.Messages.Count == 1) 
                {
                    messageName = wsdlOperationMessage.Operation.Name; 
                }
                else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 0)
                {
                    if (wsdlOperationMessage is WsdlNS.OperationInput) 
                        messageName = wsdlOperationMessage.Operation.Name + "Request";
                    else if (wsdlOperationMessage is WsdlNS.OperationOutput) 
                        messageName = wsdlOperationMessage.Operation.Name + "Solicit"; 
                }
                else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 1) 
                {
                    messageName = wsdlOperationMessage.Operation.Name + "Response";
                }
                else 
                {
                    // [....]: why this is an Assert, and not an exception? 
                    DiagnosticUtility.DebugAssert("Unsupported WSDL OM (More than 2 OperationMessages encountered in an Operation or WsdlOM is invalid)"); 
                }
                // names the come from service description documents have to be valid NCNames; XmlName.ctor will validate. 
                return new XmlName(messageName, true /*isEncoded*/);
            }
        }
 
        internal static class NetSessionHelper
        { 
            internal static void SetInitiatingTerminating(OperationDescription operationDescription, WsdlNS.Operation wsdlOperation) 
            {
                XmlAttribute isInitiating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsInitiating, 
                    WsdlExporter.NetSessionHelper.NamespaceUri);

                if (isInitiating != null)
                { 
                    if (isInitiating.Value == WsdlExporter.NetSessionHelper.True)
                    { 
                        operationDescription.IsInitiating = true; 
                    }
                    if (isInitiating.Value == WsdlExporter.NetSessionHelper.False) 
                    {
                        operationDescription.IsInitiating = false;
                    }
                } 

                XmlAttribute isTerminating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsTerminating, 
                    WsdlExporter.NetSessionHelper.NamespaceUri); 

                if (isTerminating != null) 
                {
                    if (isTerminating.Value == WsdlExporter.NetSessionHelper.True)
                    {
                        operationDescription.IsTerminating = true; 
                    }
                    if (isTerminating.Value == WsdlExporter.NetSessionHelper.False) 
                    { 
                        operationDescription.IsTerminating = false;
                    } 
                }
            }

            internal static void SetSession(ContractDescription contractDescription, WsdlNS.PortType wsdlPortType) 
            {
                XmlAttribute usingSession = FindAttribute(wsdlPortType.ExtensibleAttributes, WsdlExporter.NetSessionHelper.UsingSession, 
                    WsdlExporter.NetSessionHelper.NamespaceUri); 

                if (usingSession != null) 
                {
                    if (usingSession.Value == WsdlExporter.NetSessionHelper.True)
                    {
                        contractDescription.SessionMode = SessionMode.Required; 
                    }
                    if (usingSession.Value == WsdlExporter.NetSessionHelper.False) 
                    { 
                        contractDescription.SessionMode = SessionMode.NotAllowed;
                    } 
                }
            }

            static XmlAttribute FindAttribute(XmlAttribute[] attributes, string localName, string ns) 
            {
                if (attributes != null) 
                { 
                    foreach (XmlAttribute attribute in attributes)
                    { 
                        if (attribute.LocalName == localName && attribute.NamespaceURI == ns)
                        {
                            return attribute;
                        } 
                    }
                } 
                return null; 
            }
        } 

        internal static class SoapInPolicyWorkaroundHelper
        {
            const string soapTransportUriKey = "TransportBindingElementImporter.TransportUri"; 
            const string workaroundNS = NamingHelper.DefaultNamespace + "temporaryworkaround";
            const string bindingAttrName = "bindingName"; 
            const string bindingAttrNamespace = "bindingNamespace"; 
            static XmlDocument xmlDocument;
 
            static void InsertAdHocPolicy(WsdlNS.Binding wsdlBinding, string value, string key)
            {
                XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
                string id = AddPolicyUri(wsdlBinding, key); 
                InsertPolicy(key, id, wsdlBinding.ServiceDescription, value, wsdlBindingQName);
            } 
 
            static public string FindAdHocTransportPolicy(PolicyConversionContext policyContext, out XmlQualifiedName wsdlBindingQName)
            { 
                return FindAdHocPolicy(policyContext, soapTransportUriKey, out wsdlBindingQName);
            }

            static string FindAdHocPolicy(PolicyConversionContext policyContext, string key, out XmlQualifiedName wsdlBindingQName) 
            {
                if (policyContext == null) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext"); 

                XmlElement policy = PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(), key, workaroundNS, true); 
                if (policy != null)
                {
                    wsdlBindingQName = new XmlQualifiedName(policy.Attributes[bindingAttrName].Value, policy.Attributes[bindingAttrNamespace].Value);
                    return policy.InnerText; 
                }
                else 
                { 
                    wsdlBindingQName = null;
                    return null; 
                }
            }

            static string AddPolicyUri(WsdlNS.Binding wsdlBinding, string name) 
            {
                string policyUris = ReadPolicyUris(wsdlBinding); 
                string id = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}_BindingAdHocPolicy", wsdlBinding.Name, name); 
                string newPolicyUris = string.Format(System.Globalization.CultureInfo.InvariantCulture, "#{0} {1}", id, policyUris).Trim();
                WritePolicyUris(wsdlBinding, newPolicyUris); 
                return id;
            }

            static XmlDocument XmlDoc 
            {
                get 
                { 
                    if (xmlDocument == null)
                    { 
                        NameTable nameTable = new NameTable();
                        nameTable.Add(MetadataStrings.WSPolicy.Elements.Policy);
                        nameTable.Add(MetadataStrings.WSPolicy.Elements.All);
                        nameTable.Add(MetadataStrings.WSPolicy.Elements.ExactlyOne); 
                        nameTable.Add(MetadataStrings.WSPolicy.Attributes.PolicyURIs);
                        nameTable.Add(MetadataStrings.Wsu.Attributes.Id); 
                        xmlDocument = new XmlDocument(nameTable); 
                    }
                    return xmlDocument; 
                }
            }

            static void WritePolicyUris(WsdlNS.DocumentableItem item, string newValue) 
            {
 
                int i; 
                XmlAttribute[] attributes = item.ExtensibleAttributes;
                if (attributes != null && attributes.Length > 0) 
                {
                    foreach (XmlAttribute attribute in attributes)
                        if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute))
                        { 
                            attribute.Value = newValue;
                            return; 
                        } 
                    // Need to extend
                    i = attributes.Length; 
                    Array.Resize(ref attributes, i + 1);

                }
                else 
                {
                    //Need to create 
                    i = 0; 
                    attributes = new XmlAttribute[1];
                } 

                attributes[i] = CreatePolicyURIsAttribute(newValue);
                item.ExtensibleAttributes = attributes;
            } 

            static XmlAttribute CreatePolicyURIsAttribute(string value) 
            { 
                XmlAttribute attribute = XmlDoc.CreateAttribute(MetadataStrings.WSPolicy.Prefix,
                                                            MetadataStrings.WSPolicy.Attributes.PolicyURIs, 
                                                            MetadataStrings.WSPolicy.NamespaceUri);

                attribute.Value = value;
                return attribute; 
            }
 
            static string ReadPolicyUris(WsdlNS.DocumentableItem item) 
            {
 
                XmlAttribute[] attributes = item.ExtensibleAttributes;
                if (attributes != null && attributes.Length > 0)
                {
                    foreach (XmlAttribute attribute in attributes) 
                    {
                        if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute)) 
                        { 
                            return attribute.Value;
                        } 
                    }
                }

                return string.Empty; 
            }
 
            static void InsertPolicy(string key, string id, WsdlNS.ServiceDescription policyWsdl, string value, XmlQualifiedName wsdlBindingQName) 
            {
 
                // Create [wsp:Policy]
                XmlElement policyElement = CreatePolicyElement(key, value, wsdlBindingQName);

                //Create [wsp:Policy/@wsu:Id] 
                XmlAttribute idAttribute = XmlDoc.CreateAttribute(MetadataStrings.Wsu.Prefix,
                                                            MetadataStrings.Wsu.Attributes.Id, 
                                                            MetadataStrings.Wsu.NamespaceUri); 
                idAttribute.Value = id;
                policyElement.SetAttributeNode(idAttribute); 

                // Add wsp:Policy To WSDL
                policyWsdl.Extensions.Add(policyElement);
 
            }
 
            static XmlElement CreatePolicyElement(string elementName, string value, XmlQualifiedName wsdlBindingQName) 
            {
 
                // Create [wsp:Policy]
                XmlElement policyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
                                                            MetadataStrings.WSPolicy.Elements.Policy,
                                                            MetadataStrings.WSPolicy.NamespaceUri); 

                // Create [wsp:Policy/wsp:ExactlyOne] 
                XmlElement exactlyOneElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix, 
                                                            MetadataStrings.WSPolicy.Elements.ExactlyOne,
                                                            MetadataStrings.WSPolicy.NamespaceUri); 
                policyElement.AppendChild(exactlyOneElement);

                // Create [wsp:Policy/wsp:ExactlyOne/wsp:All]
                XmlElement allElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix, 
                                                            MetadataStrings.WSPolicy.Elements.All,
                                                            MetadataStrings.WSPolicy.NamespaceUri); 
                exactlyOneElement.AppendChild(allElement); 

                // Add [wsp:Policy/wsp:ExactlyOne/wsp:All/*] 
                XmlElement workaroundElement = xmlDocument.CreateElement(elementName, workaroundNS);
                workaroundElement.InnerText = value;

                XmlAttribute bindingName = xmlDocument.CreateAttribute(bindingAttrName); 
                bindingName.Value = wsdlBindingQName.Name;
                workaroundElement.Attributes.Append(bindingName); 
 
                XmlAttribute bindingNamespace = xmlDocument.CreateAttribute(bindingAttrNamespace);
                bindingNamespace.Value = wsdlBindingQName.Namespace; 
                workaroundElement.Attributes.Append(bindingNamespace);

                workaroundElement.Attributes.Append(bindingNamespace);
 

                allElement.AppendChild(workaroundElement); 
 
                return policyElement;
            } 

            internal static void InsertAdHocTransportPolicy(WsdlNS.ServiceDescriptionCollection wsdlDocuments)
            {
                foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments) 
                    if (wsdl != null)
                    { 
                        foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings) 
                        {
                            if (WsdlImporter.WsdlPolicyReader.ContainsPolicy(wsdlBinding)) 
                            {
                                WsdlNS.SoapBinding soapBinding = (WsdlNS.SoapBinding)wsdlBinding.Extensions.Find(typeof(WsdlNS.SoapBinding));
                                if (soapBinding != null)
                                    WsdlImporter 
                                        .SoapInPolicyWorkaroundHelper
                                        .InsertAdHocPolicy(wsdlBinding, soapBinding.Transport, soapTransportUriKey); 
                            } 
                        }
                    } 
            }
        }

        IEnumerable FindBindingsForPortType(WsdlNS.PortType wsdlPortType) 
        {
            foreach (WsdlNS.Binding wsdlBinding in GetAllBindings()) 
            { 
                if (wsdlBinding.Type.Name == wsdlPortType.Name
                    && wsdlBinding.Type.Namespace == wsdlPortType.ServiceDescription.TargetNamespace) 
                    yield return wsdlBinding;
            }
        }
 
        IEnumerable FindBindingsForContract(ContractDescription contract)
        { 
            XmlQualifiedName qName = WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract); 
            foreach (WsdlNS.Binding wsdlBinding in GetAllBindings())
            { 
                if (wsdlBinding.Type.Name == qName.Name
                    && wsdlBinding.Type.Namespace == qName.Namespace)
                    yield return wsdlBinding;
            } 
        }
 
        IEnumerable FindPortsForBinding(WsdlNS.Binding binding) 
        {
            foreach (WsdlNS.Port wsdlPort in GetAllPorts()) 
            {
                if (wsdlPort.Binding.Name == binding.Name && wsdlPort.Binding.Namespace == binding.ServiceDescription.TargetNamespace)
                    yield return wsdlPort;
            } 
        }
 
        IEnumerable GetAllBindings() 
        {
            foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments) 
            {
                foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
                {
                    yield return wsdlBinding; 
                }
            } 
        } 

        IEnumerable GetAllPorts() 
        {
            foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments)
            {
                foreach (WsdlNS.Service wsdlService in wsdl.Services) 
                {
                    foreach (WsdlNS.Port wsdlPort in wsdlService.Ports) 
                    { 
                        yield return wsdlPort;
                    } 
                }
            }
        }
 
        /// 
        ///  Critical - uses ClientSection.UnsafeGetSection to get config in PT 
        ///  Safe - does not leak config object, just picks up extensions 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        static Collection LoadWsdlExtensionsFromConfig()
        {
            return ConfigNS.ClientSection.UnsafeGetSection().Metadata.LoadWsdlImportExtensions();
        } 

        internal static IEnumerable CreateMetadataDocuments(WsdlNS.ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, IEnumerable policyDocuments) 
        { 

            if (wsdlDocuments != null) 
                foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
                    yield return MetadataSection.CreateFromServiceDescription(wsdl);

            if (xmlSchemas != null) 
                foreach (XmlSchema schema in xmlSchemas.Schemas())
                    yield return MetadataSection.CreateFromSchema(schema); 
 
            if (policyDocuments != null)
                foreach (XmlElement policyDocument in policyDocuments) 
                    yield return MetadataSection.CreateFromPolicy(policyDocument, null);
        }

        BindingElementCollection ImportPolicyFromWsdl(WsdlEndpointConversionContext endpointContext) 
        {
            PolicyAlternatives policyAlternatives = this.PolicyReader.GetPolicyAlternatives(endpointContext); 
            IEnumerable policyContexts = GetPolicyConversionContextEnumerator(endpointContext.Endpoint, policyAlternatives, this.Quotas); 
            PolicyConversionContext firstContext = null;
 
            StringBuilder unImportedPolicyMessage = null;
            int policyConversionContextsSeen = 0; //limit on the number of alternatives that we'll evaluate
            foreach (PolicyConversionContext policyConversionContext in policyContexts)
            { 
                if (firstContext == null)
                    firstContext = policyConversionContext; 
                if (this.TryImportPolicy(policyConversionContext)) 
                {
                    return policyConversionContext.BindingElements; 
                }
                else
                {
                    AppendUnImportedPolicyErrorMessage(ref unImportedPolicyMessage, endpointContext, policyConversionContext); 
                }
 
                if (++policyConversionContextsSeen >= this.Quotas.MaxPolicyConversionContexts) 
                {
                    break; 
                }
            }

            // we failed to import policy for all PolicyConversionContexts, lets pick one context (the first one) 
            // and wrap all unprocessed assertion in UnrecognizedAssertionsBindingElement
            if (firstContext != null) 
            { 
#pragma warning suppress 56506
                firstContext.BindingElements.Insert(0, CollectUnrecognizedAssertions(firstContext, endpointContext)); 
                LogImportWarning(unImportedPolicyMessage.ToString());
                return firstContext.BindingElements;
            }
            // Consider: a /verbose option for svcutil... 
            if (endpointContext.WsdlPort != null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlPort, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions)))); 
            }
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions))));
            }
        } 

        static UnrecognizedAssertionsBindingElement CollectUnrecognizedAssertions(PolicyConversionContext policyContext, WsdlEndpointConversionContext endpointContext) 
        { 
            XmlQualifiedName bindingQName = new XmlQualifiedName(endpointContext.WsdlBinding.Name, endpointContext.WsdlBinding.ServiceDescription.TargetNamespace);
            UnrecognizedAssertionsBindingElement unknownBindingElement = new UnrecognizedAssertionsBindingElement(bindingQName, policyContext.GetBindingAssertions()); 
            foreach (OperationDescription operation in policyContext.Contract.Operations)
            {
                if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
                { 
                    unknownBindingElement.Add(operation, policyContext.GetOperationBindingAssertions(operation));
                } 
 
                foreach (MessageDescription message in operation.Messages)
                { 
                    if (policyContext.GetMessageBindingAssertions(message).Count != 0)
                    {
                        unknownBindingElement.Add(message, policyContext.GetMessageBindingAssertions(message));
                    } 
                }
            } 
            return unknownBindingElement; 
        }
 
        static void AppendUnImportedPolicyErrorMessage(ref StringBuilder unImportedPolicyMessage, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)
        {
            if (unImportedPolicyMessage == null)
            { 
                unImportedPolicyMessage = new StringBuilder(SR.GetString(SR.UnabletoImportPolicy));
            } 
            else 
            {
                unImportedPolicyMessage.AppendLine(); 
            }

            if (policyContext.GetBindingAssertions().Count != 0)
                AddUnImportedPolicyString(unImportedPolicyMessage, endpointContext.WsdlBinding, policyContext.GetBindingAssertions()); 

            foreach (OperationDescription operation in policyContext.Contract.Operations) 
            { 
                if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
                { 
                    AddUnImportedPolicyString(unImportedPolicyMessage,
                        endpointContext.GetOperationBinding(operation),
                        policyContext.GetOperationBindingAssertions(operation));
                } 

                foreach (MessageDescription message in operation.Messages) 
                { 
                    if (policyContext.GetMessageBindingAssertions(message).Count != 0)
                    { 
                        AddUnImportedPolicyString(unImportedPolicyMessage,
                            endpointContext.GetMessageBinding(message),
                            policyContext.GetMessageBindingAssertions(message));
                    } 
                }
            } 
 
        }
 
        static void AddUnImportedPolicyString(StringBuilder stringBuilder, WsdlNS.NamedItem item, IEnumerable unimportdPolicy)
        {
            stringBuilder.AppendLine(SR.GetString(SR.UnImportedAssertionList, CreateXPathString(item)));
            // do not putput duplicated assetions 
            Dictionary unique = new Dictionary();
            int uniqueAsserions = 0; 
            foreach (XmlElement element in unimportdPolicy) 
            {
                if (unique.ContainsKey(element)) 
                    continue;
                unique.Add(element, element);
                uniqueAsserions++;
                if (uniqueAsserions > 128) 
                {
                    stringBuilder.Append(".."); 
                    stringBuilder.AppendLine(); ; 
                    break;
                } 
                WriteElement(element, stringBuilder);
            }
        }
 
        static void WriteElement(XmlElement element, StringBuilder stringBuilder)
        { 
            stringBuilder.Append("    <"); 
            stringBuilder.Append(element.Name);
            if (!string.IsNullOrEmpty(element.NamespaceURI)) 
            {
                stringBuilder.Append(' ');
                stringBuilder.Append("xmlns");
                if (!string.IsNullOrEmpty(element.Prefix)) 
                {
                    stringBuilder.Append(':'); 
                    stringBuilder.Append(element.Prefix); 
                }
                stringBuilder.Append('='); 
                stringBuilder.Append('\'');
                stringBuilder.Append(element.NamespaceURI);
                stringBuilder.Append('\'');
            } 
            stringBuilder.Append(">..'); 
            stringBuilder.AppendLine(); ;
        } 

        const string xPathDocumentFormatString = "//wsdl:definitions[@targetNamespace='{0}']";
        const string xPathItemSubFormatString = "/wsdl:{0}";
        const string xPathNamedItemSubFormatString = xPathItemSubFormatString + "[@name='{1}']"; 

        static string GetElementName(WsdlNS.NamedItem item) 
        { 
            if (item is WsdlNS.PortType)
                return "wsdl:portType"; 
            else if (item is WsdlNS.Binding)
                return "wsdl:binding";
            else if (item is WsdlNS.ServiceDescription)
                return "wsdl:definitions"; 
            else if (item is WsdlNS.Service)
                return "wsdl:service"; 
            else if (item is WsdlNS.Message) 
                return "wsdl:message";
            else if (item is WsdlNS.Operation) 
                return "wsdl:operation";
            else if (item is WsdlNS.Port)
                return "wsdl:port";
            else 
            {
                DiagnosticUtility.DebugAssert("GetElementName Method should be updated to support " + item.GetType()); 
                return null; 
            }
        } 

        static string CreateXPathString(WsdlNS.NamedItem item)
        {
            if (item == null) 
                return SR.GetString(SR.XPathUnavailable);
            string nameValue = item.Name; 
            string localName; 
            string wsdlNs;
            string rest = string.Empty; 
            string itemPath = string.Empty;

            GetXPathParameters(item, out wsdlNs, out localName, ref nameValue, ref rest);
            string documentPath = string.Format(CultureInfo.InvariantCulture, xPathDocumentFormatString, wsdlNs); 

            if (localName != null) 
            { 
                itemPath = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, localName, nameValue);
            } 
            DiagnosticUtility.DebugAssert(rest != null, "GetXPathParameters Method should never set rest to null. this happened for: " + item.GetType());
            return documentPath + itemPath + rest;
        }
 
        static void GetXPathParameters(WsdlNS.NamedItem item, out string wsdlNs, out string localName, ref string nameValue, ref string rest)
        { 
            if (item is WsdlNS.ServiceDescription) 
            {
                localName = null; 
                wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty;
            }
            if (item is WsdlNS.PortType)
            { 
                localName = "portType";
                wsdlNs = ((WsdlNS.PortType)item).ServiceDescription.TargetNamespace ?? String.Empty; 
            } 
            else if (item is WsdlNS.Binding)
            { 
                localName = "binding";
                wsdlNs = ((WsdlNS.Binding)item).ServiceDescription.TargetNamespace ?? String.Empty;
            }
            else if (item is WsdlNS.ServiceDescription) 
            {
                localName = "definitions"; 
                wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty; 
            }
            else if (item is WsdlNS.Service) 
            {
                localName = "service";
                wsdlNs = ((WsdlNS.Service)item).ServiceDescription.TargetNamespace ?? String.Empty;
            } 
            else if (item is WsdlNS.Message)
            { 
                localName = "message"; 
                wsdlNs = ((WsdlNS.Message)item).ServiceDescription.TargetNamespace ?? String.Empty;
            } 
            else if (item is WsdlNS.Port)
            {
                WsdlNS.Service wsdlService = ((WsdlNS.Port)item).Service;
                localName = "service"; 
                nameValue = wsdlService.Name;
                wsdlNs = wsdlService.ServiceDescription.TargetNamespace ?? String.Empty; 
                rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "port", item.Name); 
            }
            else if (item is WsdlNS.Operation) 
            {
                WsdlNS.PortType wsdlPortType = ((WsdlNS.Operation)item).PortType;
                localName = "portType";
                nameValue = wsdlPortType.Name; 
                wsdlNs = wsdlPortType.ServiceDescription.TargetNamespace ?? String.Empty;
                rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name); 
            } 
            else if (item is WsdlNS.OperationBinding)
            { 
                WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.OperationBinding)item);
                localName = "binding";
                nameValue = wsdlOperationBinding.Binding.Name;
                wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty; 
                rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name);
            } 
            else if (item is WsdlNS.MessageBinding) 
            {
                localName = "binding"; 
                WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.MessageBinding)item).OperationBinding;
                wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty;
                nameValue = wsdlOperationBinding.Binding.Name;
                string messageName = item.Name; 

                string messageTag = string.Empty; 
                if (item is WsdlNS.InputBinding) 
                    messageTag = "input";
                else if (item is WsdlNS.OutputBinding) 
                    messageTag = "output";
                else if (item is WsdlNS.FaultBinding)
                    messageTag = "fault";
                else 
                    DiagnosticUtility.DebugAssert("Unsupported WSDL OM: unknown WsdlNS.MessageBinding: " + item.GetType());
 
                rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", wsdlOperationBinding.Name); 
                if (string.IsNullOrEmpty(messageName))
                    rest += string.Format(CultureInfo.InvariantCulture, xPathItemSubFormatString, messageTag); 
                else
                    rest += string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, messageTag, messageName);
            }
            else 
            {
                DiagnosticUtility.DebugAssert("GetXPathParameters Method should be updated to support " + item.GetType()); 
                localName = null; 
                wsdlNs = null;
            } 
        }

        void LogImportWarning(string warningMessage)
        { 
            if (warnings.ContainsKey(warningMessage))
                return; 
            if (warnings.Count >= 1024) 
                warnings.Clear();
            warnings.Add(warningMessage, warningMessage); 
            this.Errors.Add(new MetadataConversionError(warningMessage, true));
        }

        void LogImportError(WsdlNS.NamedItem item, WsdlImportException wie) 
        {
            string errormessage; 
            if (wie.InnerException != null && (wie.InnerException is WsdlImportException)) 
            {
                WsdlImportException wieInner = wie.InnerException as WsdlImportException; 
                string dependencyMessage = SR.GetString(SR.WsdlImportErrorDependencyDetail, GetElementName(wieInner.SourceItem), GetElementName(item), CreateXPathString(wieInner.SourceItem));
                errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), dependencyMessage);
            }
            else 
            {
                errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), wie.Message); 
            } 

            importErrors.Add(item, wie); 
            this.Errors.Add(new MetadataConversionError(errormessage, false));
        }

        static Exception CreateBeforeImportExtensionException(IWsdlImportExtension importer, Exception e) 
        {
            string errorMessage = SR.GetString(SR.WsdlExtensionBeforeImportError, importer.GetType().AssemblyQualifiedName, e.Message); 
            return new InvalidOperationException(errorMessage, e); 
        }
 
        Exception CreateAlreadyFaultedException(WsdlNS.NamedItem item)
        {
            WsdlImportException innerException = importErrors[item];
            string warningMsg = SR.GetString(SR.WsdlItemAlreadyFaulted, GetElementName(item)); 
            return new AlreadyFaultedException(warningMsg, innerException);
        } 
 
        static Exception CreateExtensionException(IWsdlImportExtension importer, Exception e)
        { 
            string errorMessage = SR.GetString(SR.WsdlExtensionImportError, importer.GetType().FullName, e.Message);
            //consider [....], allow internal exceptions to throw WsdlImportException and handle it in some special way?
            return new InvalidOperationException(errorMessage, e);
        } 

        class AlreadyFaultedException : InvalidOperationException 
        { 
            internal AlreadyFaultedException(string message, WsdlImportException innerException)
                : base(message, innerException) { } 
        }

        class WsdlImportException : Exception
        { 
            WsdlNS.NamedItem sourceItem;
            readonly string xPath = null; 
 
            WsdlImportException(WsdlNS.NamedItem item, Exception innerException)
                : base(string.Empty, innerException) 
            {
                this.xPath = CreateXPathString(item);
                this.sourceItem = item;
            } 

            internal static WsdlImportException Create(WsdlNS.NamedItem item, Exception innerException) 
            { 
                WsdlImportException wie = innerException as WsdlImportException;
                if (wie != null && wie.IsChildNodeOf(item)) 
                {
                    wie.sourceItem = item;
                    return wie;
                } 
                else
                { 
                    AlreadyFaultedException afe = innerException as AlreadyFaultedException; 
                    if (afe != null)
                        return new WsdlImportException(item, afe.InnerException); 
                    else
                        return new WsdlImportException(item, innerException);
                }
            } 

            internal bool IsChildNodeOf(WsdlNS.NamedItem item) 
            { 
                return this.XPath.StartsWith(CreateXPathString(item), StringComparison.Ordinal);
            } 

            internal string XPath { get { return xPath; } }

            internal WsdlNS.NamedItem SourceItem { get { return sourceItem; } } 

            public override string Message 
            { 
                get
                { 
                    Exception messageException = this.InnerException;

                    while (messageException is WsdlImportException)
                        messageException = messageException.InnerException; 

                    if (messageException == null) 
                        return string.Empty; 

                    return messageException.Message; 
                }
            }
        }
 
        internal class WsdlPolicyReader
        { 
            WsdlImporter importer; 
            WsdlPolicyDictionary policyDictionary;
 
            static readonly string[] EmptyStringArray = new string[0];

            internal WsdlPolicyReader(WsdlImporter importer)
            { 
                this.importer = importer;
                this.policyDictionary = new WsdlPolicyDictionary(importer); 
                importer.PolicyWarningOccured += this.LogPolicyNormalizationWarning; 
            }
 
            IEnumerable> GetPolicyAlternatives(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
            {
                Collection policyElements = new Collection();
 
                foreach (XmlElement element in GetReferencedPolicy(item, wsdl))
                { 
                    policyElements.Add(element); 
                }
 
                foreach (XmlElement element in GetEmbeddedPolicy(item))
                {
                    policyElements.Add(element);
                    if (!policyDictionary.PolicySourceTable.ContainsKey(element)) 
                        policyDictionary.PolicySourceTable.Add(element, wsdl);
                } 
 
                return importer.NormalizePolicy(policyElements);
           } 

            void LogPolicyNormalizationWarning(XmlElement contextAssertion, string warningMessage)
            {
                string xPath = null; 
                if(contextAssertion != null)
                    xPath = this.policyDictionary.CreateIdXPath(contextAssertion); 
 
                StringBuilder warningMsg = new StringBuilder();
                warningMsg.AppendLine(warningMessage); 

                if (!string.IsNullOrEmpty(xPath))
                {
                    warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath)); 
                }
                else 
                { 
                    //
                    // We were given a context assertion that we couldn't get an XPath for 
                    //
                    warningMsg.AppendLine(SR.GetString(SR.XPathPointer, SR.GetString(SR.XPathUnavailable)));
                }
                importer.LogImportWarning(warningMsg.ToString()); 
            }
 
            internal static bool ContainsPolicy(WsdlNS.Binding wsdlBinding) 
            {
                if (HasPolicyAttached(wsdlBinding)) 
                    return true;

                foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
                { 
                    if (HasPolicyAttached(wsdlOperationBinding))
                    { 
                        return true; 
                    }
                    if (wsdlOperationBinding.Input != null && HasPolicyAttached(wsdlOperationBinding.Input)) 
                    {
                        return true;
                    }
                    if (wsdlOperationBinding.Output != null && HasPolicyAttached(wsdlOperationBinding.Output)) 
                    {
                        return true; 
                    } 
                    foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
                    { 
                        if (HasPolicyAttached(faultBinding))
                        {
                            return true;
                        } 
                    }
                } 
 
                return false;
            } 

            internal static bool HasPolicy(WsdlNS.Port wsdlPort)
            {
                return HasPolicyAttached(wsdlPort); 
            }
 
            internal static IEnumerable GetEmbeddedPolicy(WsdlNS.NamedItem item) 
            {
                List embeddedPolicies = new List(); 
                embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
                    MetadataStrings.WSPolicy.NamespaceUri));
                embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
                    MetadataStrings.WSPolicy.NamespaceUri15)); 
                return embeddedPolicies;
            } 
 
            IEnumerable GetReferencedPolicy(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
            { 
                string xPath = CreateXPathString(item);

                foreach (string policyRef in GetPolicyReferenceUris(item, xPath))
                { 
                    XmlElement policy = policyDictionary.ResolvePolicyReference(policyRef, wsdl);
                    if (policy == null) 
                    { 
                        StringBuilder warningMsg = new StringBuilder();
                        warningMsg.AppendLine(SR.GetString(SR.UnableToFindPolicyWithId, policyRef)); 
                        warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath));
                        importer.LogImportWarning(warningMsg.ToString());
                        continue;
                    } 
                    yield return policy;
                } 
            } 

            IEnumerable GetPolicyReferenceUris(WsdlNS.NamedItem item, string xPath) 
            {
                //
                // get policy from wsp:PolicyUris attribute
                // 
                foreach (string policyUri in ReadPolicyUrisAttribute(item))
                    yield return policyUri; 
 
                //
                // get policy from  Elements 
                //
                foreach (string policyUri in ReadPolicyReferenceElements(item, xPath))
                    yield return policyUri;
            } 

            IEnumerable ReadPolicyReferenceElements(WsdlNS.NamedItem item, string xPath) 
            { 
                List policyReferences = new List();
                policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference, 
                    MetadataStrings.WSPolicy.NamespaceUri));
                policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference,
                    MetadataStrings.WSPolicy.NamespaceUri15));
 
                foreach (XmlElement element in policyReferences)
                { 
                    string idRef = element.GetAttribute(MetadataStrings.WSPolicy.Attributes.URI); 

                    if (idRef == null) 
                    {
                        string warningMsg = SR.GetString(SR.PolicyReferenceMissingURI, MetadataStrings.WSPolicy.Attributes.URI);
                        importer.LogImportWarning(warningMsg);
                    } 
                    else if (idRef == string.Empty)
                    { 
                        string warningMsg = SR.GetString(SR.PolicyReferenceInvalidId); 
                        importer.LogImportWarning(warningMsg);
                        continue; 
                    }
                    else
                    {
                        yield return idRef; 
                    }
                } 
            } 

            static string[] ReadPolicyUrisAttribute(WsdlNS.NamedItem item) 
            {

                XmlAttribute[] attributes = item.ExtensibleAttributes;
                if (attributes != null && attributes.Length > 0) 
                {
                    foreach (XmlAttribute attribute in attributes) 
                    { 
                        if (PolicyHelper.IsPolicyURIs(attribute))
                        { 
                            return attribute.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                        }
                    }
                } 

                return EmptyStringArray; 
            } 

            static bool HasPolicyAttached(WsdlNS.NamedItem item) 
            {
                XmlAttribute[] attributes = item.ExtensibleAttributes;
                if (attributes != null && Array.Exists(attributes, PolicyHelper.IsPolicyURIs))
                { 
                    return true;
                } 
 
                if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri) != null
                    || item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri15) != null) 
                {
                    return true;
                }
 
                if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri) != null
                    || item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri15) != null) 
                { 
                    return true;
                } 

                return false;
            }
 
            internal PolicyAlternatives GetPolicyAlternatives(WsdlEndpointConversionContext endpointContext)
            { 
                PolicyAlternatives policyAlternatives = new PolicyAlternatives(); 

                // 
                // Create EndpointAlternatives either from wsd:binding or from CrossProduct of wsd:binding and wsdl:port policy
                //
                WsdlNS.ServiceDescription bindingWsdl = endpointContext.WsdlBinding.ServiceDescription;
                IEnumerable> wsdlBindingAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlBinding, bindingWsdl); 
                if (endpointContext.WsdlPort != null)
                { 
                    IEnumerable> wsdlPortAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlPort, endpointContext.WsdlPort.Service.ServiceDescription); 
                    policyAlternatives.EndpointAlternatives = PolicyHelper.CrossProduct(wsdlBindingAlternatives, wsdlPortAlternatives, new YieldLimiter(this.importer.Quotas.MaxYields, this.importer));
                } 
                else
                {
                    policyAlternatives.EndpointAlternatives = wsdlBindingAlternatives;
                } 

                // 
                // Create operation and message policy 
                //
                policyAlternatives.OperationBindingAlternatives = new Dictionary>>(endpointContext.Endpoint.Contract.Operations.Count); 
                policyAlternatives.MessageBindingAlternatives = new Dictionary>>();
                policyAlternatives.FaultBindingAlternatives = new Dictionary>>();

                foreach (OperationDescription operation in endpointContext.Endpoint.Contract.Operations) 
                {
                    WsdlNS.OperationBinding wsdlOperationBinding = endpointContext.GetOperationBinding(operation); 
                    try 
                    {
                        IEnumerable> operationAlternatives = this.GetPolicyAlternatives(wsdlOperationBinding, bindingWsdl); 
                        policyAlternatives.OperationBindingAlternatives.Add(operation, operationAlternatives);

                        foreach (MessageDescription message in operation.Messages)
                        { 
                            WsdlNS.MessageBinding wsdlMessageBinding = endpointContext.GetMessageBinding(message);
                            CreateMessageBindingAlternatives(policyAlternatives, bindingWsdl, message, wsdlMessageBinding); 
                        } 

                        foreach (FaultDescription fault in operation.Faults) 
                        {
                            WsdlNS.FaultBinding wsdlFaultBinding = endpointContext.GetFaultBinding(fault);
                            CreateFaultBindingAlternatives(policyAlternatives, bindingWsdl, fault, wsdlFaultBinding);
                        } 
                    }
#pragma warning suppress 56500 // covered by FxCOP 
                    catch (Exception e) 
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                            throw;
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
                    }
                } 

                return policyAlternatives; 
            } 

            void CreateMessageBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, MessageDescription message, WsdlNS.MessageBinding wsdlMessageBinding) 
            {
                try
                {
                    IEnumerable> messageAlternatives = this.GetPolicyAlternatives(wsdlMessageBinding, bindingWsdl); 
                    policyAlternatives.MessageBindingAlternatives.Add(message, messageAlternatives);
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlMessageBinding, e));
                } 
            }
 
            void CreateFaultBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, FaultDescription fault, WsdlNS.FaultBinding wsdlFaultBinding) 
            {
                try 
                {
                    IEnumerable> faultAlternatives = this.GetPolicyAlternatives(wsdlFaultBinding, bindingWsdl);
                    policyAlternatives.FaultBindingAlternatives.Add(fault, faultAlternatives);
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e) 
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlFaultBinding, e));
                }
            }
 
            internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
            { 
                return this.policyDictionary.ResolvePolicyReference(policyReference, contextPolicyAssertion); 
            }
 
            class WsdlPolicyDictionary
            {
                readonly MetadataImporter importer;
                readonly Dictionary> embeddedPolicyDictionary = new Dictionary>(); 
                readonly Dictionary externalPolicyDictionary = new Dictionary();
                readonly Dictionary policySourceTable = new Dictionary(); 
 
                internal Dictionary PolicySourceTable
                { 
                    get { return policySourceTable; }
                }

                internal WsdlPolicyDictionary(WsdlImporter importer) 
                {
                    this.importer = importer; 
 
                    //
                    // Embedded Policy documents 
                    //
                    foreach (WsdlNS.ServiceDescription wsdl in importer.wsdlDocuments)
                    {
                        foreach (XmlElement element in WsdlPolicyReader.GetEmbeddedPolicy(wsdl)) 
                        {
                            AddEmbeddedPolicy(importer, wsdl, element); 
                        } 
                    }
 
                    //
                    // External Policy documents
                    //
                    foreach (KeyValuePair policyDocument in importer.policyDocuments) 
                    {
                        AddExternalPolicy(importer, policyDocument); 
                    } 

                } 

                void AddEmbeddedPolicy(WsdlImporter importer, WsdlNS.ServiceDescription wsdl, XmlElement element)
                {
                    string key = GetFragmentIdentifier(element); 
                    if (String.IsNullOrEmpty(key))
                    { 
                        string xPath = CreateXPathString(wsdl); 
                        string warningMsg = SR.GetString(SR.PolicyInWsdlMustHaveFragmentId, xPath);
                        importer.LogImportWarning(warningMsg); 
                        return;
                    }

                    Dictionary wsdlPolicyDictionary; 
                    if (!this.embeddedPolicyDictionary.TryGetValue(wsdl, out wsdlPolicyDictionary))
                    { 
                        wsdlPolicyDictionary = new Dictionary(); 
                        this.embeddedPolicyDictionary.Add(wsdl, wsdlPolicyDictionary);
                    } 
                    else if (wsdlPolicyDictionary.ContainsKey(key))
                    {
                        string xPath = CreateIdXPath(wsdl, element, key);
                        string warningMsg = SR.GetString(SR.DuplicatePolicyInWsdlSkipped, xPath); 
                        importer.LogImportWarning(warningMsg);
                        return; 
                    } 

                    wsdlPolicyDictionary.Add(key, element); 
                    policySourceTable.Add(element, wsdl);
                }

                void AddExternalPolicy(WsdlImporter importer, KeyValuePair policyDocument) 
                {
                    if (policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri 
                        && policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri15) 
                    {
                        string warningMsg = SR.GetString(SR.UnrecognizedPolicyDocumentNamespace, policyDocument.Value.NamespaceURI); 
                        importer.LogImportWarning(warningMsg);
                        return;
                    }
 
                    if (PolicyHelper.GetNodeType(policyDocument.Value) != PolicyHelper.NodeType.Policy)
                    { 
                        string warningMsg = SR.GetString(SR.UnsupportedPolicyDocumentRoot, policyDocument.Value.Name); 
                        importer.LogImportWarning(warningMsg);
                        return; 
                    }

                    string key = CreateKeyFromPolicy(policyDocument.Key, policyDocument.Value);
                    if (externalPolicyDictionary.ContainsKey(key)) 
                    {
                        string warningMsg = SR.GetString(SR.DuplicatePolicyDocumentSkipped, key); 
                        importer.LogImportWarning(warningMsg); 
                        return;
                    } 

                    this.externalPolicyDictionary.Add(key, policyDocument.Value);
                }
 
                internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
                { 
                    XmlElement policy; 

                    if (policyReference[0] != '#') 
                    {
                        externalPolicyDictionary.TryGetValue(policyReference, out policy);
                        return policy;
                    } 

                    if (contextPolicyAssertion == null) 
                    { 
                        return null;
                    } 

                    WsdlNS.ServiceDescription sourceWsdl;
                    if (!policySourceTable.TryGetValue(contextPolicyAssertion, out sourceWsdl))
                    { 
                        return null;
                    } 
 
                    return ResolvePolicyReference(policyReference, sourceWsdl);
                } 

                internal XmlElement ResolvePolicyReference(string policyReference, WsdlNS.ServiceDescription wsdlDocument)
                {
                    XmlElement policy; 
                    if (policyReference[0] != '#')
                    { 
                        externalPolicyDictionary.TryGetValue(policyReference, out policy); 
                        return policy;
                    } 

                    Dictionary wsdlPolicyDictionary;
                    if (!this.embeddedPolicyDictionary.TryGetValue(wsdlDocument, out wsdlPolicyDictionary))
                    { 
                        return null;
                    } 
 
                    wsdlPolicyDictionary.TryGetValue(policyReference, out policy);
                    return policy; 
                }

                static string CreateKeyFromPolicy(string identifier, XmlElement policyElement)
                { 
                    string policyId = GetFragmentIdentifier(policyElement);
                    string policyUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}", identifier, policyId); 
                    return policyUri; 
                }
 
                static string GetFragmentIdentifier(XmlElement element)
                {
                    return PolicyHelper.GetFragmentIdentifier(element);
                } 

                static readonly string wspPolicy = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.WSPolicy.Prefix, MetadataStrings.WSPolicy.Elements.Policy); 
                static readonly string xmlId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Xml.Prefix, MetadataStrings.Xml.Attributes.Id); 
                static readonly string wsuId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Wsu.Prefix, MetadataStrings.Wsu.Attributes.Id);
 
                internal string CreateIdXPath(XmlElement policyAssertion)
                {
                    WsdlNS.ServiceDescription sourceWsdl;
                    if (!policySourceTable.TryGetValue(policyAssertion, out sourceWsdl)) 
                    {
                        return null; 
                    } 
                    string key = GetFragmentIdentifier(policyAssertion);
                    if (string.IsNullOrEmpty(key)) 
                    {
                        return null;
                    }
                    return CreateIdXPath(sourceWsdl, policyAssertion, key); 
                }
 
                internal static string CreateIdXPath(WsdlNS.ServiceDescription wsdl, XmlElement element, string key) 
                {
                    string xPath = CreateXPathString(wsdl); 

                    string idAttrib;
                    if (element.HasAttribute(MetadataStrings.Wsu.Attributes.Id, MetadataStrings.Wsu.NamespaceUri))
                    { 
                        idAttrib = wsuId;
                    } 
                    else if (element.HasAttribute(MetadataStrings.Xml.Attributes.Id, MetadataStrings.Xml.NamespaceUri)) 
                    {
                        idAttrib = xmlId; 
                    }
                    else
                    {
                        DiagnosticUtility.DebugAssert("CreateIdXPath always called with a valid key"); 
                        return null;
                    } 
                    return string.Format(CultureInfo.InvariantCulture, "{0}/{1}/[@{2}='{3}']", xPath, wspPolicy, idAttrib, key); 
                }
 
            }

        }
 
        enum ErrorBehavior
        { 
            RethrowExceptions, 
            DoNotThrowExceptions,
        } 

        enum WsdlPortTypeImportOptions
        {
            ReuseExistingContracts, 
            IgnoreExistingContracts,
        } 
    } 
}

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