File: System\ServiceModel\Web\AutomaticEndpointGenerator.cs
Project: ndp\cdf\src\NetFx35\System.ServiceModel.Web\System.ServiceModel.Web.csproj (System.ServiceModel.Web)
// <copyright>
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
 
namespace System.ServiceModel.Web
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Runtime;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Configuration;
    using System.ServiceModel.Description;
 
    internal abstract class AutomaticEndpointGenerator
    {
        private IDictionary<string, ContractDescription> implementedContracts;
        private string multipleContractsErrorMessage;
        private string noContractErrorMessage;
        private string standardEndpointKind;
        private Type singleImplementedContract;
 
        protected AutomaticEndpointGenerator(IDictionary<string, ContractDescription> implementedContracts, string multipleContractsErrorMessage, string noContractErrorMessage, string standardEndpointKind)
        {
            Fx.Assert(implementedContracts != null, "The 'implementedContracts' parameter should not be null.");
            Fx.Assert(multipleContractsErrorMessage != null, "The 'multipleContractsErrorMessage' parameter should not be null.");
            Fx.Assert(noContractErrorMessage != null, "The 'noContractErrorMessage' parameter should not be null.");
            Fx.Assert(standardEndpointKind != null, "The 'standardEndpointKind' parameter should not be null.");
 
            this.implementedContracts = implementedContracts;
            this.multipleContractsErrorMessage = multipleContractsErrorMessage;
            this.noContractErrorMessage = noContractErrorMessage;
            this.standardEndpointKind = standardEndpointKind;
        }
 
        protected abstract string BindingCollectionElementName { get; }
 
        public ServiceEndpoint GenerateServiceEndpoint(ServiceHostBase serviceHost, Uri baseAddress)
        {
            Fx.Assert(serviceHost != null, "The 'serviceHost' parameter should not be null.");
            Fx.Assert(baseAddress != null, "The 'baseAddress' parameter should not be null.");
 
            AuthenticationSchemes supportedSchemes = GetAuthenticationSchemes(baseAddress);
            Type contractType = this.GetSingleImplementedContract();
            ConfigLoader configLoader = new ConfigLoader(serviceHost.GetContractResolver(this.implementedContracts));
            ServiceEndpointElement serviceEndpointElement = new ServiceEndpointElement();
            
            serviceEndpointElement.Contract = contractType.FullName;
            this.SetBindingConfiguration(baseAddress.Scheme, serviceEndpointElement);
            serviceEndpointElement.Kind = this.standardEndpointKind;
 
            ServiceEndpoint serviceEndpoint = configLoader.LookupEndpoint(serviceEndpointElement, null, serviceHost, serviceHost.Description, true);
            this.ConfigureBinding(serviceEndpoint.Binding, baseAddress.Scheme, supportedSchemes, AspNetEnvironment.Enabled);
 
            // Setting the Endpoint address and listenUri now that we've set the binding security
            ConfigLoader.ConfigureEndpointAddress(serviceEndpointElement, serviceHost, serviceEndpoint);
            ConfigLoader.ConfigureEndpointListenUri(serviceEndpointElement, serviceHost, serviceEndpoint);
 
            return serviceEndpoint;
        }
 
        protected abstract void ConfigureBinding(Binding binding, string uriScheme, AuthenticationSchemes supportedAuthenticationSchemes, bool hostedEnvironment);
 
        private static AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
        {
            AuthenticationSchemes supportedSchemes = AspNetEnvironment.Current.GetAuthenticationSchemes(baseAddress);
 
            if (AspNetEnvironment.Current.IsSimpleApplicationHost)
            {
                // Cassini always reports the auth scheme as anonymous or Ntlm. Map this to Ntlm, except when forms auth
                // is requested
                if (supportedSchemes == (AuthenticationSchemes.Anonymous | AuthenticationSchemes.Ntlm))
                {
                    if (AspNetEnvironment.Current.IsWindowsAuthenticationConfigured())
                    {
                        supportedSchemes = AuthenticationSchemes.Ntlm;
                    }
                    else
                    {
                        supportedSchemes = AuthenticationSchemes.Anonymous;
                    }
                }
            }
 
            return supportedSchemes;
        }
 
        private Type GetSingleImplementedContract()
        {
            if (this.singleImplementedContract == null)
            {
                Fx.Assert(this.implementedContracts != null, "The 'implementedContracts' field should not be null.");
                Fx.Assert(this.multipleContractsErrorMessage != null, "The 'multipleContractsErrorMessage' field should not be null.");
                Fx.Assert(this.noContractErrorMessage != null, "The 'noContractErrorMessage' field should not be null.");
 
                if (this.implementedContracts.Count > 1)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(this.multipleContractsErrorMessage));
                }
                else if (this.implementedContracts.Count == 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(this.noContractErrorMessage));
                }
 
                foreach (ContractDescription contract in this.implementedContracts.Values)
                {
                    this.singleImplementedContract = contract.ContractType;
                    break;
                }
            }
 
            return this.singleImplementedContract;
        }
 
        private void SetBindingConfiguration(string uriScheme, ServiceEndpointElement serviceEndpointElement)
        {
            Fx.Assert(uriScheme != null, "The 'uriScheme' parameter should not be null.");
            Fx.Assert(serviceEndpointElement != null, "The 'serviceEndpointElement' parameter should not be null.");
            Fx.Assert(this.BindingCollectionElementName != null, "The 'this.BindingCollectionElementName' property should not be null.");
 
            ProtocolMappingItem protocolMappingItem = ConfigLoader.LookupProtocolMapping(uriScheme);
            if (protocolMappingItem != null &&
                string.Equals(protocolMappingItem.Binding, this.BindingCollectionElementName, StringComparison.Ordinal))
            {
                serviceEndpointElement.BindingConfiguration = protocolMappingItem.BindingConfiguration;
            }
        }
    }
}