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

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

namespace System.ServiceModel.Description 
{
    using System.IO; 
    using System.ServiceModel.Dispatcher; 
    using System.ServiceModel.Activation;
    using System.ServiceModel.Channels; 
    using System.Xml;
    using WsdlNS = System.Web.Services.Description;

    using XsdNS = System.Xml.Schema; 
    using System.Collections.ObjectModel;
    using System.Collections.Generic; 
    using System.Xml.Schema; 
    using System.ServiceModel.Configuration;
    using System.Collections; 
    using System.ServiceModel.Diagnostics;
    using System.Diagnostics;

 
    public class ServiceMetadataBehavior : IServiceBehavior
    { 
        public const string MexContractName = "IMetadataExchange"; 
        internal const string MexContractNamespace = "http://schemas.microsoft.com/2006/04/mex";
 
        static readonly Uri emptyUri = new Uri(String.Empty, UriKind.Relative);

        bool httpGetEnabled = false;
        bool httpsGetEnabled = false; 
        Uri httpGetUrl;
        Uri httpsGetUrl; 
        Binding httpGetBinding; 
        Binding httpsGetBinding;
        Uri externalMetadataLocation = null; 
        MetadataExporter metadataExporter = null;

        ContractDescription mexContract = null;
        object thisLock = new object(); 

        public bool HttpGetEnabled 
        { 
            get { return this.httpGetEnabled; }
            set { this.httpGetEnabled = value; } 
        }

        public Uri HttpGetUrl
        { 
            get { return this.httpGetUrl; }
            set 
            { 
                if (value != null && value.IsAbsoluteUri && value.Scheme != Uri.UriSchemeHttp)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxServiceMetadataBehaviorUrlMustBeHttpOrRelative,
                            "HttpGetUrl", Uri.UriSchemeHttp, value.ToString(), value.Scheme));
                }
                this.httpGetUrl = value; 
            }
        } 
 
        public bool HttpsGetEnabled
        { 
            get { return this.httpsGetEnabled; }
            set { this.httpsGetEnabled = value; }
        }
 
        public Uri HttpsGetUrl
        { 
            get { return this.httpsGetUrl; } 
            set
            { 
                if (value != null && value.IsAbsoluteUri && value.Scheme != Uri.UriSchemeHttps)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxServiceMetadataBehaviorUrlMustBeHttpOrRelative,
                        "HttpsGetUrl", Uri.UriSchemeHttps, value.ToString(), value.Scheme)); 
                }
 
                this.httpsGetUrl = value; 
            }
        } 

        public Binding HttpGetBinding
        {
            get { return this.httpGetBinding; } 
            set
            { 
                if (value != null) 
                {
                    if (!value.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxBindingSchemeDoesNotMatch,
                            value.Scheme, value.GetType().ToString(), Uri.UriSchemeHttp));
                    } 
                    CustomBinding customBinding = new CustomBinding(value);
                    TextMessageEncodingBindingElement textMessageEncodingBindingElement = customBinding.Elements.Find(); 
                    if (textMessageEncodingBindingElement != null && !textMessageEncodingBindingElement.MessageVersion.IsMatch(MessageVersion.None)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxIncorrectMessageVersion, 
                            textMessageEncodingBindingElement.MessageVersion.ToString(), MessageVersion.None.ToString()));
                    }
                    HttpTransportBindingElement httpTransportBindingElement = customBinding.Elements.Find();
                    if (httpTransportBindingElement != null) 
                    {
                        httpTransportBindingElement.Method = "GET"; 
                    } 
                    this.httpGetBinding = customBinding;
                } 
            }
        }

        public Binding HttpsGetBinding 
        {
            get { return this.httpsGetBinding; } 
            set 
            {
                if (value != null) 
                {
                    if (!value.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxBindingSchemeDoesNotMatch, 
                            value.Scheme, value.GetType().ToString(), Uri.UriSchemeHttps));
                    } 
                    CustomBinding customBinding = new CustomBinding(value); 
                    TextMessageEncodingBindingElement textMessageEncodingBindingElement = customBinding.Elements.Find();
                    if (textMessageEncodingBindingElement != null && !textMessageEncodingBindingElement.MessageVersion.IsMatch(MessageVersion.None)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxIncorrectMessageVersion,
                            textMessageEncodingBindingElement.MessageVersion.ToString(), MessageVersion.None.ToString()));
                    } 
                    HttpsTransportBindingElement httpsTransportBindingElement = customBinding.Elements.Find();
                    if (httpsTransportBindingElement != null) 
                    { 
                        httpsTransportBindingElement.Method = "GET";
                    } 
                    this.httpsGetBinding = customBinding;
                }
            }
        } 

        public Uri ExternalMetadataLocation 
        { 
            get { return this.externalMetadataLocation; }
            set 
            {
                if (value != null && value.IsAbsoluteUri && !(value.Scheme == Uri.UriSchemeHttp || value.Scheme == Uri.UriSchemeHttps))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ExternalMetadataLocation", SR.GetString(SR.SFxBadMetadataLocationUri, value.OriginalString, value.Scheme)); 
                }
                this.externalMetadataLocation = value; 
            } 
        }
 
        public MetadataExporter MetadataExporter
        {
            get
            { 
                if (this.metadataExporter == null)
                    this.metadataExporter = new WsdlExporter(); 
 
                return this.metadataExporter;
            } 
            set
            {
                this.metadataExporter = value;
            } 
        }
 
        void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) 
        {
        } 

        void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection parameters)
        {
        } 

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase) 
        { 
           if (description == null)
               throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description"); 
           if (serviceHostBase == null)
               throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceHostBase");

           ApplyBehavior(description, serviceHostBase); 
        }
 
        void ApplyBehavior(ServiceDescription description, ServiceHostBase host) 
        {
            ServiceMetadataExtension mex = ServiceMetadataExtension.EnsureServiceMetadataExtension(description, host); 
            SetExtensionProperties(description, host, mex);
            CustomizeMetadataEndpoints(description, host, mex);
            CreateHttpGetEndpoints(description, host, mex);
        } 

        private void CreateHttpGetEndpoints(ServiceDescription description, ServiceHostBase host, ServiceMetadataExtension mex) 
        { 
            if (this.httpGetEnabled)
            { 
                ChannelDispatcher channelDispatcher = EnsureGetDispatcher(host, mex, this.httpGetUrl, Uri.UriSchemeHttp);
                ((ServiceMetadataExtension.HttpGetImpl)channelDispatcher.Endpoints[0].DispatchRuntime.SingletonInstanceContext.UserObject).GetWsdlEnabled = true;
            }
 
            if (this.httpsGetEnabled)
            { 
                ChannelDispatcher channelDispatcher = EnsureGetDispatcher(host, mex, this.httpsGetUrl, Uri.UriSchemeHttps); 
                ((ServiceMetadataExtension.HttpGetImpl)channelDispatcher.Endpoints[0].DispatchRuntime.SingletonInstanceContext.UserObject).GetWsdlEnabled = true;
            } 
        }

        private static ChannelDispatcher EnsureGetDispatcher(ServiceHostBase host, ServiceMetadataExtension mex, Uri url, string scheme)
        { 
            Uri address = host.GetVia(scheme, url == null ? new Uri(string.Empty, UriKind.Relative) : url);
 
            if (address == null) 
            {
                if(scheme == Uri.UriSchemeHttp) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceMetadataBehaviorNoHttpBaseAddress)));
                else
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceMetadataBehaviorNoHttpsBaseAddress)));
 
            }
 
            return mex.EnsureGetDispatcher(address, false /* isServiceDebugBehavior */); 

        } 

        private void SetExtensionProperties(ServiceDescription description, ServiceHostBase host, ServiceMetadataExtension mex)
        {
            mex.ExternalMetadataLocation = this.ExternalMetadataLocation; 
            mex.Initializer = new MetadataExtensionInitializer(this, description, host);
            mex.HttpGetEnabled = this.httpGetEnabled; 
            mex.HttpsGetEnabled = this.httpsGetEnabled; 

            mex.HttpGetUrl = host.GetVia(Uri.UriSchemeHttp, this.httpGetUrl == null ? new Uri(string.Empty, UriKind.Relative) : this.httpGetUrl); 
            mex.HttpsGetUrl = host.GetVia(Uri.UriSchemeHttps, this.httpsGetUrl == null ? new Uri(string.Empty, UriKind.Relative) : this.httpsGetUrl);

            mex.HttpGetBinding = this.httpGetBinding;
            mex.HttpsGetBinding = this.httpsGetBinding; 

            foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers) 
            { 
                if (IsMetadataTransferDispatcher(description, dispatcher))
                { 
                    mex.MexEnabled = true;
                    mex.MexUrl = dispatcher.Listener.Uri;
                    break;
                } 
            }
 
        } 

        private static void CustomizeMetadataEndpoints(ServiceDescription description, ServiceHostBase host, ServiceMetadataExtension mex) 
        {
            for (int i = 0; i < host.ChannelDispatchers.Count; i++)
            {
                ChannelDispatcher channelDispatcher = host.ChannelDispatchers[i] as ChannelDispatcher; 
                if (channelDispatcher != null && ServiceMetadataBehavior.IsMetadataTransferDispatcher(description, channelDispatcher))
                { 
                    if (channelDispatcher.Endpoints.Count != 1) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new InvalidOperationException(SR.GetString(SR.SFxServiceMetadataBehaviorInstancingError, channelDispatcher.Listener.Uri, channelDispatcher.CreateContractListString())));
                    }

                    DispatchRuntime dispatcher = channelDispatcher.Endpoints[0].DispatchRuntime; 

                    // set instancing 
                    dispatcher.InstanceContextProvider = 
                       InstanceContextProviderBase.GetProviderForMode(InstanceContextMode.Single, dispatcher);
 
                    ServiceMetadataExtension.WSMexImpl impl = new ServiceMetadataExtension.WSMexImpl(mex);
                    dispatcher.SingletonInstanceContext = new InstanceContext(host, impl, false);
                    impl.IsListeningOnHttps = channelDispatcher.Listener.Uri.Scheme == Uri.UriSchemeHttps;
                } 
            }
        } 
 
        static EndpointDispatcher GetListenerByID(SynchronizedCollection channelDispatchers, string id)
        { 
            for (int i=0; i() == null)
                return true;
            if (description.ServiceType!=null && description.ServiceType.GetInterface(typeof(IMetadataExchange).Name) != null)
                return true; 

            return false; 
        } 

        internal static bool IsHttpGetMetadataDispatcher(ServiceDescription description, ChannelDispatcher channelDispatcher) 
        {
            if (description.Behaviors.Find() == null)
                return false;
 
            foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
            { 
                if (endpointDispatcher.ContractName == ServiceMetadataExtension.HttpGetImpl.ContractName 
                    && endpointDispatcher.ContractNamespace == ServiceMetadataExtension.HttpGetImpl.ContractNamespace)
                    return true; 
            }
            return false;
        }
 
        internal static bool IsMetadataEndpoint(ServiceDescription description, ServiceEndpoint endpoint)
        { 
            if (BehaviorMissingObjectNullOrServiceImplements(description, endpoint)) 
                return false;
 
            return IsMetadataEndpoint(endpoint);

        }
 
        static bool IsMetadataEndpoint(ServiceEndpoint endpoint)
        { 
            return (endpoint.Contract.Name == ServiceMetadataBehavior.MexContractName 
                    && endpoint.Contract.Namespace == ServiceMetadataBehavior.MexContractNamespace);
        } 

        internal static bool IsMetadataImplementedType(ServiceDescription description, Type type)
        {
            if (BehaviorMissingObjectNullOrServiceImplements(description, type)) 
                return false;
 
            return type == typeof(IMetadataExchange); 
        }
 
        internal static bool IsMetadataImplementedType(Type type)
        {
            return type == typeof(IMetadataExchange);
        } 

        internal void AddImplementedContracts(ServiceHostBase.ServiceAndBehaviorsContractResolver resolver) 
        { 
            if (!resolver.BehaviorContracts.ContainsKey(MexContractName))
            { 
                EnsureMexContractDescription();
                resolver.BehaviorContracts.Add(MexContractName, this.mexContract);
            }
        } 

        private void EnsureMexContractDescription() 
        { 
            if (this.mexContract == null)
            { 
                lock (this.thisLock)
                {
                    if (this.mexContract == null)
                    { 
                        this.mexContract = CreateMexContract();
                    } 
                } 
            }
        } 

        static ContractDescription CreateMexContract()
        {
            ContractDescription mexContract = ContractDescription.GetContract(typeof(IMetadataExchange)); 
            foreach (OperationDescription operation in mexContract.Operations)
            { 
                operation.Behaviors.Find().Impersonation = ImpersonationOption.Allowed; 
            }
            mexContract.Behaviors.Add(new ServiceMetadataContractBehavior(true)); 

            return mexContract;

        } 

        internal class MetadataExtensionInitializer 
        { 
            ServiceMetadataBehavior behavior;
            ServiceDescription description; 
            ServiceHostBase host;
            Exception metadataGenerationException = null;

            internal MetadataExtensionInitializer(ServiceMetadataBehavior behavior, ServiceDescription description, ServiceHostBase host) 
            {
                this.behavior = behavior; 
                this.description = description; 
                this.host = host;
            } 

            internal MetadataSet GenerateMetadata()
            {
                if (this.behavior.ExternalMetadataLocation == null || this.behavior.ExternalMetadataLocation.ToString() == string.Empty) 
                {
                    if (this.metadataGenerationException != null) 
                        throw this.metadataGenerationException; 

                    try 
                    {
                        MetadataExporter exporter = this.behavior.MetadataExporter;
                        XmlQualifiedName serviceName = new XmlQualifiedName(this.description.Name, this.description.Namespace);
                        Collection exportedEndpoints = new Collection(); 
                        foreach (ServiceEndpoint endpoint in this.description.Endpoints)
                        { 
                            // skip contracts marked as disabled 
                            ServiceMetadataContractBehavior contractBehavior = endpoint.Contract.Behaviors.Find();
                            if (contractBehavior != null && contractBehavior.MetadataGenerationDisabled) 
                                continue;

                            EndpointAddress address = null;
                            EndpointDispatcher endpointDispatcher = GetListenerByID(this.host.ChannelDispatchers, endpoint.Id); 
                            if (endpointDispatcher != null)
                            { 
                                address = endpointDispatcher.EndpointAddress; 
                            }
                            ServiceEndpoint exportedEndpoint = new ServiceEndpoint(endpoint.Contract); 
                            exportedEndpoint.Binding = endpoint.Binding;
                            exportedEndpoint.Name = endpoint.Name;
                            exportedEndpoint.Address = address;
                            foreach (IEndpointBehavior behavior in endpoint.Behaviors) 
                            {
                                exportedEndpoint.Behaviors.Add(behavior); 
                            } 
                            exportedEndpoints.Add(exportedEndpoint);
                        } 
                        WsdlExporter wsdlExporter = exporter as WsdlExporter;
                        if (wsdlExporter != null)
                        {
                            wsdlExporter.ExportEndpoints(exportedEndpoints, serviceName); 
                        }
                        else 
                        { 
                            foreach (ServiceEndpoint endpoint in exportedEndpoints)
                            { 
                                exporter.ExportEndpoint(endpoint);
                            }
                        }
 
                        if (exporter.Errors.Count > 0 && DiagnosticUtility.ShouldTraceWarning)
                        { 
                            TraceWsdlExportErrors(exporter); 
                        }
 
                        return exporter.GetGeneratedMetadata();
                    }
                    catch (Exception e)
                    { 
                        this.metadataGenerationException = e;
                        throw; 
                    } 
                }
                return null; 
            }

            static void TraceWsdlExportErrors(MetadataExporter exporter)
            { 
                foreach (MetadataConversionError error in exporter.Errors)
                { 
                    if (DiagnosticUtility.ShouldTraceWarning) 
                    {
                        Hashtable h = new Hashtable(2); 
                        h.Add("IsWarning", error.IsWarning);
                        h.Add("Message", error.Message);
                        TraceUtility.TraceEvent(TraceEventType.Warning,
                                            TraceCode.WsmexNonCriticalWsdlExportError, 
                                            new DictionaryTraceRecord(h), null, null);
                    } 
                } 
            }
        } 

    }
}

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