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

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

namespace System.ServiceModel.Description 
{
    using System.Collections.Generic; 
    using System.ServiceModel.Dispatcher; 
    using System.Collections.ObjectModel;
    using System.Net; 
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Xml;
    using System.Xml.Schema; 
    using System.Runtime.Serialization;
    using WsdlNS = System.Web.Services.Description; 
    using System.Text; 
    using System.Globalization;
    using System.IO; 
    using System.Threading;
    using System.Diagnostics;
    using System.Reflection;
    using System.ServiceModel.Diagnostics; 
    using System.ServiceModel.Activation;
    using System.ServiceModel.Configuration; 
 
    // the description/metadata "mix-in"
    public class ServiceMetadataExtension : IExtension 
    {
        const string BaseAddressPattern = "{%BaseAddress%}";
        static readonly Uri EmptyUri = new Uri(String.Empty, UriKind.Relative);
 
        static readonly Type[] httpGetSupportedChannels = new Type[] { typeof(IReplyChannel), };
 
        ServiceMetadataBehavior.MetadataExtensionInitializer initializer; 
        MetadataSet metadata;
        bool isInitialized = false; 
        Uri externalMetadataLocation;
        ServiceHostBase owner;
        object syncRoot = new object();
        bool mexEnabled = false; 
        bool httpGetEnabled = false;
        bool httpsGetEnabled = false; 
        bool httpHelpPageEnabled = false; 
        bool httpsHelpPageEnabled = false;
        Uri mexUrl; 
        Uri httpGetUrl;
        Uri httpsGetUrl;
        Uri httpHelpPageUrl;
        Uri httpsHelpPageUrl; 
        Binding httpHelpPageBinding;
        Binding httpsHelpPageBinding; 
        Binding httpGetBinding; 
        Binding httpsGetBinding;
 

        public ServiceMetadataExtension()
            : this(null)
        { 
        }
 
        internal ServiceMetadataExtension(ServiceMetadataBehavior.MetadataExtensionInitializer initializer) 
        {
            this.initializer = initializer; 
        }

        internal ServiceMetadataBehavior.MetadataExtensionInitializer Initializer
        { 
            get { return this.initializer; }
            set { this.initializer = value; } 
        } 

        public MetadataSet Metadata 
        {
            get
            {
                EnsureInitialized(); 

                return this.metadata; 
            } 
        }
 
        internal Uri ExternalMetadataLocation
        {
            get { return this.externalMetadataLocation; }
            set { this.externalMetadataLocation = value; } 
        }
 
        internal bool MexEnabled 
        {
            get { return this.mexEnabled; } 
            set { this.mexEnabled = value; }
        }

        internal bool HttpGetEnabled 
        {
            get { return this.httpGetEnabled; } 
            set { this.httpGetEnabled = value; } 
        }
 
        internal bool HttpsGetEnabled
        {
            get { return this.httpsGetEnabled; }
            set { this.httpsGetEnabled = value; } 
        }
 
        internal bool HelpPageEnabled 
        {
            get { return this.httpHelpPageEnabled || this.httpsHelpPageEnabled; } 
        }

        internal bool MetadataEnabled
        { 
            get { return this.mexEnabled || this.httpGetEnabled || this.httpsGetEnabled; }
        } 
 
        internal bool HttpHelpPageEnabled
        { 
            get { return this.httpHelpPageEnabled; }
            set { this.httpHelpPageEnabled = value; }
        }
 
        internal bool HttpsHelpPageEnabled
        { 
            get { return this.httpsHelpPageEnabled; } 
            set { this.httpsHelpPageEnabled = value; }
        } 

        internal Uri MexUrl
        {
            get { return this.mexUrl; } 
            set { this.mexUrl = value; }
        } 
 
        internal Uri HttpGetUrl
        { 
            get { return this.httpGetUrl; }
            set { this.httpGetUrl = value; }
        }
 
        internal Uri HttpsGetUrl
        { 
            get { return this.httpsGetUrl; } 
            set { this.httpsGetUrl = value; }
        } 

        internal Uri HttpHelpPageUrl
        {
            get { return this.httpHelpPageUrl; } 
            set { this.httpHelpPageUrl = value; }
        } 
 
        internal Uri HttpsHelpPageUrl
        { 
            get { return this.httpsHelpPageUrl; }
            set { this.httpsHelpPageUrl = value; }
        }
 
        internal Binding HttpHelpPageBinding
        { 
            get { return this.httpHelpPageBinding; } 
            set { this.httpHelpPageBinding = value; }
        } 

        internal Binding HttpsHelpPageBinding
        {
            get { return this.httpsHelpPageBinding; } 
            set { this.httpsHelpPageBinding = value; }
        } 
 
        internal Binding HttpGetBinding
        { 
            get { return this.httpGetBinding; }
            set { this.httpGetBinding = value; }
        }
 
        internal Binding HttpsGetBinding
        { 
            get { return this.httpsGetBinding; } 
            set { this.httpsGetBinding = value; }
        } 

        void EnsureInitialized()
        {
            if (!this.isInitialized) 
            {
                lock (this.syncRoot) 
                { 
                    if (!this.isInitialized)
                    { 
                        if (this.initializer != null)
                        {
                            // the following call will initialize this
                            // it will use the Metadata property to do the initialization 
                            // this will call back into this method, but exit because isInitialized is set.
                            // if other threads try to call these methods, they will block on the lock 
                            this.metadata = this.initializer.GenerateMetadata(); 
                        }
 
                        if (this.metadata == null)
                        {
                            this.metadata = new MetadataSet();
                        } 

                        Thread.MemoryBarrier(); 
 
                        this.isInitialized = true;
                        this.initializer = null; 
                    }
                }
            }
        } 

        void IExtension.Attach(ServiceHostBase owner) 
        { 
            if (owner == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("owner")); 

            if (this.owner != null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TheServiceMetadataExtensionInstanceCouldNot2_0)));
 
            owner.ThrowIfClosedOrOpened();
 
            this.owner = owner; 
        }
 
        void IExtension.Detach(ServiceHostBase owner)
        {
            if (owner == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("owner"); 

            if (this.owner == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TheServiceMetadataExtensionInstanceCouldNot3_0))); 

            if (this.owner != owner) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("owner", SR.GetString(SR.TheServiceMetadataExtensionInstanceCouldNot4_0));

            this.owner.ThrowIfClosedOrOpened();
 
            this.owner = null;
        } 
 
        static internal ServiceMetadataExtension EnsureServiceMetadataExtension(ServiceDescription description, ServiceHostBase host)
        { 
            ServiceMetadataExtension mex = host.Extensions.Find();
            if (mex == null)
            {
                mex = new ServiceMetadataExtension(); 
                host.Extensions.Add(mex);
            } 
 
            return mex;
        } 

        internal ChannelDispatcher EnsureGetDispatcher(Uri listenUri)
        {
            ChannelDispatcher channelDispatcher = FindGetDispatcher(listenUri); 

            if (channelDispatcher == null) 
            { 
                channelDispatcher = CreateGetDispatcher(listenUri);
                owner.ChannelDispatchers.Add(channelDispatcher); 
            }

            return channelDispatcher;
        } 

        internal ChannelDispatcher EnsureGetDispatcher(Uri listenUri, bool isServiceDebugBehavior) 
        { 
            ChannelDispatcher channelDispatcher = FindGetDispatcher(listenUri);
 
            Binding binding;
            if (channelDispatcher == null)
            {
                if (listenUri.Scheme == Uri.UriSchemeHttp) 
                {
                    if (isServiceDebugBehavior) 
                    { 
                        binding = this.httpHelpPageBinding ?? MetadataExchangeBindings.HttpGet;
                    } 
                    else
                    {
                        binding = this.httpGetBinding ?? MetadataExchangeBindings.HttpGet;
                    } 
                }
                else if (listenUri.Scheme == Uri.UriSchemeHttps) 
                { 
                    if (isServiceDebugBehavior)
                    { 
                        binding = this.httpsHelpPageBinding ?? MetadataExchangeBindings.HttpsGet;
                    }
                    else
                    { 
                        binding = this.httpsGetBinding ?? MetadataExchangeBindings.HttpsGet;
                    } 
                } 
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxGetChannelDispatcherDoesNotSupportScheme, typeof(ChannelDispatcher).Name, Uri.UriSchemeHttp, Uri.UriSchemeHttps)));
                }
                channelDispatcher = CreateGetDispatcher(listenUri, binding);
                owner.ChannelDispatchers.Add(channelDispatcher); 
            }
 
            return channelDispatcher; 
        }
 
        private ChannelDispatcher FindGetDispatcher(Uri listenUri)
        {
            foreach (ChannelDispatcher channelDispatcher in owner.ChannelDispatchers)
            { 
                if (channelDispatcher.Listener.Uri == listenUri)
                { 
                    if(channelDispatcher.Endpoints.Count==1 && 
                        channelDispatcher.Endpoints[0].DispatchRuntime.SingletonInstanceContext != null &&
                        channelDispatcher.Endpoints[0].DispatchRuntime.SingletonInstanceContext.UserObject is HttpGetImpl) 
                    {
                        return channelDispatcher;
                    }
                } 
            }
            return null; 
        } 

        private ChannelDispatcher CreateGetDispatcher(Uri listenUri) 
        {
            if (listenUri.Scheme == Uri.UriSchemeHttp)
            {
                return CreateGetDispatcher(listenUri, MetadataExchangeBindings.HttpGet); 
            }
            else if (listenUri.Scheme == Uri.UriSchemeHttps) 
            { 
                return CreateGetDispatcher(listenUri, MetadataExchangeBindings.HttpsGet);
            } 
            else
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxGetChannelDispatcherDoesNotSupportScheme, typeof(ChannelDispatcher).Name, Uri.UriSchemeHttp, Uri.UriSchemeHttps)));
            } 
        }
 
        private ChannelDispatcher CreateGetDispatcher(Uri listenUri, Binding binding) 
        {
            EndpointAddress address = new EndpointAddress(listenUri); 
            Uri listenUriBaseAddress = listenUri;
            string listenUriRelativeAddress = string.Empty;

            BindingParameterCollection parameters = GetBindingParameters(owner.Description); 

            // find listener for HTTP GET 
            IChannelListener listener = null; 
            if (binding.CanBuildChannelListener(parameters))
            { 
                listener = binding.BuildChannelListener(listenUriBaseAddress, listenUriRelativeAddress, parameters);
            }
            else
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxBindingNotSupportedForMetadataHttpGet)));
            } 
 
            //create dispatchers
            ChannelDispatcher channelDispatcher = new ChannelDispatcher(listener, HttpGetImpl.MetadataHttpGetBinding, binding); 
            channelDispatcher.MessageVersion = binding.MessageVersion;
            EndpointDispatcher dispatcher = new EndpointDispatcher(address, HttpGetImpl.ContractName, HttpGetImpl.ContractNamespace);

            //Add operation 
            DispatchOperation operationDispatcher = new DispatchOperation(dispatcher.DispatchRuntime, HttpGetImpl.GetMethodName, HttpGetImpl.RequestAction, HttpGetImpl.ReplyAction);
            operationDispatcher.Formatter = MessageOperationFormatter.Instance; 
            MethodInfo methodInfo = typeof(IHttpGetMetadata).GetMethod(HttpGetImpl.GetMethodName); 
            operationDispatcher.Invoker = new SyncMethodInvoker(methodInfo);
            dispatcher.DispatchRuntime.Operations.Add(operationDispatcher); 

            //wire up dispatchers
            HttpGetImpl impl = new HttpGetImpl(this, listener.Uri);
            dispatcher.DispatchRuntime.SingletonInstanceContext = new InstanceContext(owner, impl, false); 
            dispatcher.DispatchRuntime.MessageInspectors.Add(impl);
            channelDispatcher.Endpoints.Add(dispatcher); 
            dispatcher.ContractFilter = new MatchAllMessageFilter(); 
            dispatcher.FilterPriority = 0;
            dispatcher.DispatchRuntime.InstanceContextProvider = InstanceContextProviderBase.GetProviderForMode(InstanceContextMode.Single, dispatcher.DispatchRuntime); 
            channelDispatcher.ServiceThrottle = owner.ServiceThrottle;

            ServiceDebugBehavior sdb = owner.Description.Behaviors.Find();
            if (sdb != null) 
                channelDispatcher.IncludeExceptionDetailInFaults |= sdb.IncludeExceptionDetailInFaults;
 
            ServiceBehaviorAttribute sba = owner.Description.Behaviors.Find(); 
            if (sba != null)
                channelDispatcher.IncludeExceptionDetailInFaults |= sba.IncludeExceptionDetailInFaults; 


            return channelDispatcher;
        } 

        static BindingParameterCollection GetBindingParameters(ServiceDescription description) 
        { 
            BindingParameterCollection c = new BindingParameterCollection();
            foreach (IServiceBehavior b in description.Behaviors) 
            {
                if (b is ServiceCredentials || b is ServiceSecurityAuditBehavior)
                {
 
                    c.Add(b);
                } 
                else if (b is HostedBindingBehavior) 
                {
                    c.Add(((HostedBindingBehavior)b).VirtualPathExtension); 
                    c.Add(new HostedMetadataProperty());
                }
            }
 
            return c;
        } 
 
        internal class WSMexImpl : IMetadataExchange
        { 
            internal const string MetadataMexBinding = "ServiceMetadataBehaviorMexBinding";
            internal const string ContractName = MetadataStrings.WSTransfer.Name;
            internal const string ContractNamespace = MetadataStrings.WSTransfer.Namespace;
            internal const string GetMethodName = "Get"; 
            internal const string RequestAction = MetadataStrings.WSTransfer.GetAction;
            internal const string ReplyAction = MetadataStrings.WSTransfer.GetResponseAction; 
 
            ServiceMetadataExtension parent;
            MetadataSet metadataLocationSet; 
            TypedMessageConverter converter;

            bool isListeningOnHttps = false;
 
            internal WSMexImpl(ServiceMetadataExtension parent)
            { 
                this.parent = parent; 

                if (this.parent.ExternalMetadataLocation != null && this.parent.ExternalMetadataLocation != EmptyUri) 
                {
                    this.metadataLocationSet = new MetadataSet();
                    string location = this.GetLocationToReturn();
                    MetadataSection metadataLocationSection = new MetadataSection(MetadataSection.ServiceDescriptionDialect, null, new MetadataLocation(location)); 
                    this.metadataLocationSet.MetadataSections.Add(metadataLocationSection);
                } 
            } 

            internal bool IsListeningOnHttps 
            {
                get { return this.isListeningOnHttps; }
                set { this.isListeningOnHttps = value; }
            } 

            private string GetLocationToReturn() 
            { 
                Debug.Assert(this.parent.ExternalMetadataLocation != null);
                Uri location = this.parent.ExternalMetadataLocation; 

                if (!location.IsAbsoluteUri)
                {
                    Uri httpAddr = parent.owner.GetVia(Uri.UriSchemeHttp, location); 
                    Uri httpsAddr = parent.owner.GetVia(Uri.UriSchemeHttps, location);
 
                    if (this.IsListeningOnHttps && httpsAddr != null) 
                    {
                        location = httpsAddr; 
                    }
                    else if (httpAddr != null)
                    {
                        location = httpAddr; 
                    }
                    else 
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ExternalMetadataLocation", SR.GetString(SR.SFxBadMetadataLocationNoAppropriateBaseAddress, this.parent.ExternalMetadataLocation.OriginalString));
                    } 
                }

                return location.ToString();
            } 

            MetadataSet GatherMetadata(string dialect, string identifier) 
            { 
                if (metadataLocationSet != null)
                { 
                    return metadataLocationSet;
                }
                else
                { 
                    MetadataSet metadataSet = new MetadataSet();
 
                    foreach (MetadataSection document in parent.Metadata.MetadataSections) 
                    {
                        if ((dialect == null || dialect == document.Dialect) && 
                            (identifier == null || identifier == document.Identifier))
                            metadataSet.MetadataSections.Add(document);
                    }
 
                    return metadataSet;
                } 
            } 

            public Message Get(Message request) 
            {
                GetResponse response = new GetResponse();
                response.Metadata = GatherMetadata(null, null);
 
                response.Metadata.WriteFilter = new LocationUpdatingWriter(BaseAddressPattern, null);
 
                if(converter == null) 
                    converter = TypedMessageConverter.Create(typeof(GetResponse), ReplyAction);
 
                return converter.ToMessage(response, request.Version);
            }

            public IAsyncResult BeginGet(Message request, AsyncCallback callback, object state) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException()); 
            } 

            public Message EndGet(IAsyncResult result) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
            }
        } 

        //If this contract is changed, you may need to change ServiceMetadataExtension.CreateHttpGetDispatcher() 
        [ServiceContract] 
        internal interface IHttpGetMetadata
        { 
            [OperationContract(Action = MessageHeaders.WildcardAction, ReplyAction = MessageHeaders.WildcardAction)]
            Message Get(Message msg);
        }
 
        internal class HttpGetImpl : IHttpGetMetadata, IDispatchMessageInspector
        { 
            const string DiscoToken = "disco token"; 
            const string DiscoQueryString = "disco";
            const string WsdlQueryString = "wsdl"; 
            const string XsdQueryString = "xsd";

            const string HtmlContentType = "text/html; charset=UTF-8";
            const string XmlContentType = "text/xml; charset=UTF-8"; 

            const int closeTimeoutInSeconds = 90; 
            const int maxQueryStringChars = 2048; 

            internal const string MetadataHttpGetBinding = "ServiceMetadataBehaviorHttpGetBinding"; 
            internal const string ContractName = "IHttpGetHelpPageAndMetadataContract";
            internal const string ContractNamespace = "http://schemas.microsoft.com/2006/04/http/metadata";
            internal const string GetMethodName = "Get";
            internal const string RequestAction = MessageHeaders.WildcardAction; 
            internal const string ReplyAction = MessageHeaders.WildcardAction;
            internal const string HtmlBreak = "
"; static string[] NoQueries = new string[0]; ServiceMetadataExtension parent; object sync = new object(); InitializationData initData; Uri listenUri; bool helpPageEnabled = false; bool getWsdlEnabled = false; internal HttpGetImpl(ServiceMetadataExtension parent, Uri listenUri) { this.parent = parent; this.listenUri = listenUri; } public bool HelpPageEnabled { get { return this.helpPageEnabled; } set { this.helpPageEnabled = value; } } public bool GetWsdlEnabled { get { return this.getWsdlEnabled; } set { this.getWsdlEnabled = value; } } InitializationData GetInitData() { if (this.initData == null) { lock (this.sync) { if (this.initData == null) { this.initData = InitializationData.InitializeFrom(parent); } } } return this.initData; } string FindWsdlReference() { if (this.parent.ExternalMetadataLocation == null || this.parent.ExternalMetadataLocation == EmptyUri) { return null; } else { Uri location = this.parent.ExternalMetadataLocation; return ServiceHost.GetUri(this.listenUri, location).ToString(); } } bool TryHandleDocumentationRequest(Message httpGetRequest, string[] queries, out Message replyMessage) { replyMessage = null; if (!this.HelpPageEnabled) return false; if (parent.MetadataEnabled) { string discoUrl = null; string wsdlUrl = null; string httpGetUrl = null; bool linkMetadata = true; wsdlUrl = FindWsdlReference(); httpGetUrl = GetHttpGetUrl(); if (wsdlUrl == null && httpGetUrl != null) wsdlUrl = httpGetUrl + "?" + WsdlQueryString; if (httpGetUrl != null) discoUrl = httpGetUrl + "?" + DiscoQueryString; if (wsdlUrl == null) { wsdlUrl = GetMexUrl(); linkMetadata = false; } replyMessage = new MetadataOnHelpPageMessage(discoUrl, wsdlUrl, GetInitData().ServiceName, GetInitData().ClientName, linkMetadata); } else { replyMessage = new MetadataOffHelpPageMessage(GetInitData().ServiceName); } AddHttpProperty(replyMessage, HttpStatusCode.OK, HtmlContentType); return true; } private string GetHttpGetUrl() { if (this.listenUri.Scheme == Uri.UriSchemeHttp) { if (parent.HttpGetEnabled) return parent.HttpGetUrl.ToString(); else if (parent.HttpsGetEnabled) return parent.HttpsGetUrl.ToString(); } else { if (parent.HttpsGetEnabled) return parent.HttpsGetUrl.ToString(); else if (parent.HttpGetEnabled) return parent.HttpGetUrl.ToString(); } return null; } private string GetMexUrl() { if (parent.MexEnabled) return parent.MexUrl.ToString(); return null; } bool TryHandleMetadataRequest(Message httpGetRequest, string[] queries, out Message replyMessage) { replyMessage = null; if (!this.GetWsdlEnabled) return false; string query = FindQuery(queries); if (String.IsNullOrEmpty(query)) { //if the documentation page is not available return the default wsdl if it exists if (!this.helpPageEnabled && GetInitData().DefaultWsdl != null) { // use the default WSDL using (httpGetRequest) { replyMessage = new ServiceDescriptionMessage( GetInitData().DefaultWsdl, this.listenUri.ToString()); AddHttpProperty(replyMessage, HttpStatusCode.OK, XmlContentType); GetInitData().FixImportAddresses(); return true; } } return false; } // try to look the document up in the query table object doc; if (GetInitData().TryQueryLookup(query, out doc)) { using (httpGetRequest) { if (doc is WsdlNS.ServiceDescription) { replyMessage = new ServiceDescriptionMessage( (WsdlNS.ServiceDescription)doc, this.listenUri.ToString()); } else if (doc is XmlSchema) { replyMessage = new XmlSchemaMessage( ((XmlSchema)doc), this.listenUri.ToString()); } else if (doc is string) { if (((string)doc) == DiscoToken) { replyMessage = CreateDiscoMessage(); } else { DiagnosticUtility.DebugAssert("Bad object in HttpGetImpl docFromQuery table"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Bad object in HttpGetImpl docFromQuery table"))); } } else { DiagnosticUtility.DebugAssert("Bad object in HttpGetImpl docFromQuery table"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Bad object in HttpGetImpl docFromQuery table"))); } AddHttpProperty(replyMessage, HttpStatusCode.OK, XmlContentType); GetInitData().FixImportAddresses(); return true; } } // otherwise see if they just wanted ?WSDL if (String.Compare(query, WsdlQueryString, StringComparison.OrdinalIgnoreCase) == 0) { if (GetInitData().DefaultWsdl != null) { // use the default WSDL using (httpGetRequest) { replyMessage = new ServiceDescriptionMessage( GetInitData().DefaultWsdl, this.listenUri.ToString()); AddHttpProperty(replyMessage, HttpStatusCode.OK, XmlContentType); GetInitData().FixImportAddresses(); return true; } } // or redirect to an external WSDL string wsdlReference = FindWsdlReference(); if (wsdlReference != null) { replyMessage = CreateRedirectMessage(wsdlReference); return true; } } // we weren't able to handle the request -- return the documentation page if available return false; } Message CreateDiscoMessage() { string wsdlUrl = this.listenUri.ToString() + "?" + WsdlQueryString; string docUrl = null; if (this.listenUri.Scheme == Uri.UriSchemeHttp) { if (parent.HttpHelpPageEnabled) docUrl = parent.HttpHelpPageUrl.ToString(); else if (parent.HttpsHelpPageEnabled) docUrl = parent.HttpsGetUrl.ToString(); } else { if (parent.HttpsHelpPageEnabled) docUrl = parent.HttpsHelpPageUrl.ToString(); else if (parent.HttpHelpPageEnabled) docUrl = parent.HttpGetUrl.ToString(); } return new DiscoMessage(wsdlUrl, docUrl); } private string FindQuery(string[] queries) { string query = null; foreach (string q in queries) { int start = (q.Length > 0 && q[0] == '?') ? 1 : 0; if (String.Compare(q, start, WsdlQueryString, 0, WsdlQueryString.Length, StringComparison.OrdinalIgnoreCase) == 0) query = q; else if (String.Compare(q, start, XsdQueryString, 0, XsdQueryString.Length, StringComparison.OrdinalIgnoreCase) == 0) query = q; else if (parent.HelpPageEnabled && (String.Compare(q, start, DiscoQueryString, 0, DiscoQueryString.Length, StringComparison.OrdinalIgnoreCase) == 0)) query = q; } return query; } Message ProcessHttpRequest(Message httpGetRequest) { string queryString = httpGetRequest.Properties.Via.Query; if (queryString.Length > maxQueryStringChars) return CreateHttpResponseMessage(HttpStatusCode.RequestUriTooLong); if (queryString.StartsWith("?", StringComparison.OrdinalIgnoreCase)) queryString = queryString.Substring(1); string[] queries = queryString.Length > 0 ? queryString.Split('&') : NoQueries; Message replyMessage = null; if (TryHandleMetadataRequest(httpGetRequest, queries, out replyMessage)) return replyMessage; if (TryHandleDocumentationRequest(httpGetRequest, queries, out replyMessage)) return replyMessage; return CreateHttpResponseMessage(HttpStatusCode.MethodNotAllowed); } public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { return request.Version; } public void BeforeSendReply(ref Message reply, object correlationState) { if ((reply != null) && reply.IsFault) { string error = SR.GetString(SR.SFxInternalServerError); ExceptionDetail exceptionDetail = null; MessageFault fault = MessageFault.CreateFault(reply, /* maxBufferSize */ 64 * 1024); if (fault.HasDetail) { exceptionDetail = fault.GetDetail(); if (exceptionDetail != null) { error = SR.GetString(SR.SFxDocExt_Error); } } reply = new MetadataOnHelpPageMessage(error, exceptionDetail); AddHttpProperty(reply, HttpStatusCode.InternalServerError, HtmlContentType); } } public Message Get(Message message) { return ProcessHttpRequest(message); } class InitializationData { readonly Dictionary docFromQuery; readonly Dictionary queryFromDoc; WsdlNS.ServiceDescriptionCollection wsdls; XmlSchemaSet xsds; public string ServiceName; public string ClientName; public WsdlNS.ServiceDescription DefaultWsdl; InitializationData( Dictionary docFromQuery, Dictionary queryFromDoc, WsdlNS.ServiceDescriptionCollection wsdls, XmlSchemaSet xsds) { this.docFromQuery = docFromQuery; this.queryFromDoc = queryFromDoc; this.wsdls = wsdls; this.xsds = xsds; } public bool TryQueryLookup(string query, out object doc) { return docFromQuery.TryGetValue(query, out doc); } public static InitializationData InitializeFrom(ServiceMetadataExtension extension) { Dictionary docFromQueryInit = new Dictionary(StringComparer.OrdinalIgnoreCase); Dictionary queryFromDocInit = new Dictionary(); // this collection type provides useful lookup features WsdlNS.ServiceDescriptionCollection wsdls = CollectWsdls(extension.Metadata); XmlSchemaSet xsds = CollectXsds(extension.Metadata); WsdlNS.ServiceDescription defaultWsdl = null; WsdlNS.Service someService = GetAnyService(wsdls); if (someService != null) defaultWsdl = someService.ServiceDescription; // WSDLs { int i = 0; foreach (WsdlNS.ServiceDescription wsdlDoc in wsdls) { string query = WsdlQueryString; if (wsdlDoc != defaultWsdl) // don't count the WSDL at ?WSDL query += "=wsdl" + i++.ToString(System.Globalization.CultureInfo.InvariantCulture); docFromQueryInit.Add(query, wsdlDoc); queryFromDocInit.Add(wsdlDoc, query); } } // XSDs { int i = 0; foreach (XmlSchema xsdDoc in xsds.Schemas()) { string query = XsdQueryString + "=xsd" + i++.ToString(System.Globalization.CultureInfo.InvariantCulture); docFromQueryInit.Add(query, xsdDoc); queryFromDocInit.Add(xsdDoc, query); } } // Disco if (extension.HelpPageEnabled) { string query = DiscoQueryString; docFromQueryInit.Add(query, DiscoToken); queryFromDocInit.Add(DiscoToken, query); } InitializationData data = new InitializationData(docFromQueryInit, queryFromDocInit, wsdls, xsds); data.DefaultWsdl = defaultWsdl; data.ServiceName = GetAnyWsdlName(wsdls); data.ClientName = ClientClassGenerator.GetClientClassName(GetAnyContractName(wsdls) ?? "IHello"); return data; } static WsdlNS.ServiceDescriptionCollection CollectWsdls(MetadataSet metadata) { WsdlNS.ServiceDescriptionCollection wsdls = new WsdlNS.ServiceDescriptionCollection(); foreach (MetadataSection section in metadata.MetadataSections) { if (section.Metadata is WsdlNS.ServiceDescription) { wsdls.Add((WsdlNS.ServiceDescription)section.Metadata); } } return wsdls; } static XmlSchemaSet CollectXsds(MetadataSet metadata) { XmlSchemaSet xsds = new XmlSchemaSet(); xsds.XmlResolver = null; foreach (MetadataSection section in metadata.MetadataSections) { if (section.Metadata is XmlSchema) { xsds.Add((XmlSchema)section.Metadata); } } return xsds; } internal void FixImportAddresses() { // fixup imports and includes with addresses // WSDLs foreach (WsdlNS.ServiceDescription wsdlDoc in this.wsdls) { FixImportAddresses(wsdlDoc); } // XSDs foreach (XmlSchema xsdDoc in this.xsds.Schemas()) { FixImportAddresses(xsdDoc); } } void FixImportAddresses(WsdlNS.ServiceDescription wsdlDoc) { foreach (WsdlNS.Import import in wsdlDoc.Imports) { if (!String.IsNullOrEmpty(import.Location)) continue; WsdlNS.ServiceDescription targetDoc = this.wsdls[import.Namespace ?? String.Empty]; if (targetDoc != null) { string query = queryFromDoc[targetDoc]; import.Location = BaseAddressPattern + "?" + query; } } if (wsdlDoc.Types != null) { foreach (XmlSchema xsdDoc in wsdlDoc.Types.Schemas) { FixImportAddresses(xsdDoc); } } } void FixImportAddresses(XmlSchema xsdDoc) { foreach (XmlSchemaObject o in xsdDoc.Includes) { XmlSchemaExternal external = o as XmlSchemaExternal; if (external == null || !String.IsNullOrEmpty(external.SchemaLocation)) continue; string targetNs = external is XmlSchemaImport ? ((XmlSchemaImport)external).Namespace : xsdDoc.TargetNamespace; foreach (XmlSchema targetXsd in this.xsds.Schemas(targetNs ?? String.Empty)) { if (targetXsd != xsdDoc) { string query = this.queryFromDoc[targetXsd]; external.SchemaLocation = BaseAddressPattern + "?" + query; break; } } } } static string GetAnyContractName(WsdlNS.ServiceDescriptionCollection wsdls) { // try to track down a WSDL portType name using a wsdl:service as a starting point foreach (WsdlNS.ServiceDescription wsdl in wsdls) { foreach (WsdlNS.Service service in wsdl.Services) { foreach (WsdlNS.Port port in service.Ports) { if (!port.Binding.IsEmpty) { WsdlNS.Binding binding = wsdls.GetBinding(port.Binding); if (!binding.Type.IsEmpty) { return binding.Type.Name; } } } } } return null; } static WsdlNS.Service GetAnyService(WsdlNS.ServiceDescriptionCollection wsdls) { // try to track down a WSDL service foreach (WsdlNS.ServiceDescription wsdl in wsdls) { if (wsdl.Services.Count > 0) { return wsdl.Services[0]; } } return null; } static string GetAnyWsdlName(WsdlNS.ServiceDescriptionCollection wsdls) { // try to track down a WSDL name foreach (WsdlNS.ServiceDescription wsdl in wsdls) { if (!String.IsNullOrEmpty(wsdl.Name)) { return wsdl.Name; } } return null; } } #region static helpers static void AddHttpProperty(Message message, HttpStatusCode status, string contentType) { HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty(); responseProperty.StatusCode = status; responseProperty.Headers.Add(HttpResponseHeader.ContentType, contentType); message.Properties.Add(HttpResponseMessageProperty.Name, responseProperty); } static Message CreateRedirectMessage(string redirectedDestination) { Message redirectMessage = CreateHttpResponseMessage(HttpStatusCode.RedirectKeepVerb); HttpResponseMessageProperty httpResponseProperty = (HttpResponseMessageProperty)redirectMessage.Properties[HttpResponseMessageProperty.Name]; httpResponseProperty.Headers["Location"] = redirectedDestination; return redirectMessage; } static Message CreateHttpResponseMessage(HttpStatusCode code) { Message message = new NullMessage(); HttpResponseMessageProperty httpResponseProperty = new HttpResponseMessageProperty(); httpResponseProperty.StatusCode = code; message.Properties.Add(HttpResponseMessageProperty.Name, httpResponseProperty); return message; } #endregion static helpers #region Helper Message implementations class DiscoMessage : ContentOnlyMessage { string wsdlAddress; string docAddress; public DiscoMessage(string wsdlAddress, string docAddress) : base() { this.wsdlAddress = wsdlAddress; this.docAddress = docAddress; } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { writer.WriteStartDocument(); writer.WriteStartElement("discovery", "http://schemas.xmlsoap.org/disco/"); writer.WriteStartElement("contractRef", "http://schemas.xmlsoap.org/disco/scl/"); writer.WriteAttributeString("ref", wsdlAddress); writer.WriteAttributeString("docRef", docAddress); writer.WriteEndElement(); // writer.WriteEndElement(); // writer.WriteEndDocument(); } } class MetadataOnHelpPageMessage : ContentOnlyMessage { string discoUrl; string metadataUrl; string serviceName; string clientName; bool linkMetadata; string errorMessage; ExceptionDetail exceptionDetail; public MetadataOnHelpPageMessage(string discoUrl, string metadataUrl, string serviceName, string clientName, bool linkMetadata) : base() { this.discoUrl = discoUrl; this.metadataUrl = metadataUrl; this.serviceName = serviceName; this.clientName = clientName; this.linkMetadata = linkMetadata; } public MetadataOnHelpPageMessage(string errorMessage, ExceptionDetail exceptionDetail) : base() { this.errorMessage = errorMessage; this.exceptionDetail = exceptionDetail; } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { HelpPageWriter page = new HelpPageWriter(writer); writer.WriteStartElement("HTML"); writer.WriteStartElement("HEAD"); if (!String.IsNullOrEmpty(this.discoUrl)) { page.WriteDiscoLink(this.discoUrl); } page.WriteStyleSheet(); page.WriteTitle(!String.IsNullOrEmpty(this.serviceName) ? SR.GetString(SR.SFxDocExt_MainPageTitle, this.serviceName) : SR.GetString(SR.SFxDocExt_MainPageTitleNoServiceName)); if (!String.IsNullOrEmpty(this.errorMessage)) { page.WriteError(this.errorMessage); if (this.exceptionDetail != null) { page.WriteExceptionDetail(this.exceptionDetail); } } else { page.WriteToolUsage(this.metadataUrl, this.linkMetadata); page.WriteSampleCode(this.clientName); } writer.WriteEndElement(); // BODY writer.WriteEndElement(); // HTML } struct HelpPageWriter { XmlWriter writer; public HelpPageWriter(XmlWriter writer) { this.writer = writer; } internal void WriteClass(string className) { writer.WriteStartElement("font"); writer.WriteAttributeString("color", "teal"); writer.WriteString(className); writer.WriteEndElement(); // font } internal void WriteComment(string comment) { writer.WriteStartElement("font"); writer.WriteAttributeString("color", "green"); writer.WriteString(comment); writer.WriteEndElement(); // font } internal void WriteDiscoLink(string discoUrl) { writer.WriteStartElement("link"); writer.WriteAttributeString("rel", "alternate"); writer.WriteAttributeString("type", "text/xml"); writer.WriteAttributeString("href", discoUrl); writer.WriteEndElement(); // link } internal void WriteError(string message) { writer.WriteStartElement("P"); writer.WriteAttributeString("class", "intro"); writer.WriteString(message); writer.WriteEndElement(); // P } internal void WriteKeyword(string keyword) { writer.WriteStartElement("font"); writer.WriteAttributeString("color", "blue"); writer.WriteString(keyword); writer.WriteEndElement(); // font } internal void WriteSampleCode(string clientName) { writer.WriteStartElement("P"); writer.WriteAttributeString("class", "intro"); writer.WriteEndElement(); // P writer.WriteRaw(SR.GetString(SR.SFxDocExt_MainPageIntro2)); // C# writer.WriteRaw(SR.GetString(SR.SFxDocExt_CS)); writer.WriteStartElement("PRE"); WriteKeyword("class "); WriteClass("Test\n"); writer.WriteString("{\n"); WriteKeyword(" static void "); writer.WriteString("Main()\n"); writer.WriteString(" {\n"); writer.WriteString(" "); WriteClass(clientName); writer.WriteString(" client = "); WriteKeyword("new "); WriteClass(clientName); writer.WriteString("();\n\n"); WriteComment(" // " + SR.GetString(SR.SFxDocExt_MainPageComment) + "\n\n"); WriteComment(" // " + SR.GetString(SR.SFxDocExt_MainPageComment2) + "\n"); writer.WriteString(" client.Close();\n"); writer.WriteString(" }\n"); writer.WriteString("}\n"); writer.WriteEndElement(); // PRE writer.WriteRaw(HttpGetImpl.HtmlBreak); // VB writer.WriteRaw(SR.GetString(SR.SFxDocExt_VB)); writer.WriteStartElement("PRE"); WriteKeyword("Class "); WriteClass("Test\n"); WriteKeyword(" Shared Sub "); writer.WriteString("Main()\n"); WriteKeyword(" Dim "); writer.WriteString("client As "); WriteClass(clientName); writer.WriteString(" = "); WriteKeyword("New "); WriteClass(clientName); writer.WriteString("()\n"); WriteComment(" ' " + SR.GetString(SR.SFxDocExt_MainPageComment) + "\n\n"); WriteComment(" ' " + SR.GetString(SR.SFxDocExt_MainPageComment2) + "\n"); writer.WriteString(" client.Close()\n"); WriteKeyword(" End Sub\n"); WriteKeyword("End Class"); writer.WriteEndElement(); // PRE } internal void WriteExceptionDetail(ExceptionDetail exceptionDetail) { writer.WriteStartElement("PRE"); writer.WriteString(exceptionDetail.ToString().Replace("\r", "")); writer.WriteEndElement(); // PRE } internal void WriteStyleSheet() { writer.WriteStartElement("STYLE"); writer.WriteAttributeString("type", "text/css"); writer.WriteString("#content{ FONT-SIZE: 0.7em; PADDING-BOTTOM: 2em; MARGIN-LEFT: 30px}"); writer.WriteString("BODY{MARGIN-TOP: 0px; MARGIN-LEFT: 0px; COLOR: #000000; FONT-FAMILY: Verdana; BACKGROUND-COLOR: white}"); writer.WriteString("P{MARGIN-TOP: 0px; MARGIN-BOTTOM: 12px; COLOR: #000000; FONT-FAMILY: Verdana}"); writer.WriteString("PRE{BORDER-RIGHT: #f0f0e0 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #f0f0e0 1px solid; MARGIN-TOP: -5px; PADDING-LEFT: 5px; FONT-SIZE: 1.2em; PADDING-BOTTOM: 5px; BORDER-LEFT: #f0f0e0 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #f0f0e0 1px solid; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e5e5cc}"); writer.WriteString(".heading1{MARGIN-TOP: 0px; PADDING-LEFT: 15px; FONT-WEIGHT: normal; FONT-SIZE: 26px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 3px; MARGIN-LEFT: -30px; WIDTH: 100%; COLOR: #ffffff; PADDING-TOP: 10px; FONT-FAMILY: Tahoma; BACKGROUND-COLOR: #003366}"); writer.WriteString(".intro{MARGIN-LEFT: -15px}"); writer.WriteEndElement(); // STYLE } internal void WriteTitle(string title) { writer.WriteElementString("TITLE", title); writer.WriteEndElement(); // HEAD writer.WriteStartElement("BODY"); writer.WriteStartElement("DIV"); writer.WriteAttributeString("id", "content"); writer.WriteStartElement("P"); writer.WriteAttributeString("class", "heading1"); writer.WriteString(title); writer.WriteEndElement(); // P writer.WriteRaw(HttpGetImpl.HtmlBreak); } internal void WriteToolUsage(string wsdlUrl, bool linkMetadata) { writer.WriteStartElement("P"); writer.WriteAttributeString("class", "intro"); if (wsdlUrl != null) { writer.WriteRaw(SR.GetString(SR.SFxDocExt_MainPageIntro1a)); writer.WriteRaw(HttpGetImpl.HtmlBreak); writer.WriteStartElement("PRE"); writer.WriteString("svcutil.exe "); if (linkMetadata) { writer.WriteStartElement("A"); writer.WriteAttributeString("HREF", wsdlUrl); } writer.WriteString(wsdlUrl); if (linkMetadata) { writer.WriteEndElement(); // A } writer.WriteEndElement(); // PRE } else { // no metadata message writer.WriteRaw(SR.GetString(SR.SFxDocExt_MainPageIntro1b)); } writer.WriteEndElement(); // P } } } class MetadataOffHelpPageMessage : ContentOnlyMessage { public MetadataOffHelpPageMessage(string serviceName) { } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { writer.WriteStartElement("HTML"); writer.WriteStartElement("HEAD"); writer.WriteRaw(String.Format(CultureInfo.InvariantCulture, @" Service")); writer.WriteEndElement(); //HEAD writer.WriteRaw(String.Format(CultureInfo.InvariantCulture, @"

Service


{0}

 
<" + ConfigurationStrings.BehaviorsSectionName + @"> 
    <" + ConfigurationStrings.ServiceBehaviors + @">
        <" + ConfigurationStrings.Behavior + @" " + ConfigurationStrings.Name + @"=""MyServiceTypeBehaviors"" > 
            <" + ConfigurationStrings.ServiceMetadataPublishingSectionName + @" " + ConfigurationStrings.HttpGetEnabled + @"=""true"" />
        </" + ConfigurationStrings.Behavior + @">
    </" + ConfigurationStrings.ServiceBehaviors + @">
</" + ConfigurationStrings.BehaviorsSectionName + @"> 

{1}

 
<" + ConfigurationStrings.Service + @" " + ConfigurationStrings.Name + @"=""MyNamespace.MyServiceType"" " + ConfigurationStrings.BehaviorConfiguration + @"=""MyServiceTypeBehaviors"" >

{2}

<" + ConfigurationStrings.Endpoint + @" " + ConfigurationStrings.Contract + @"=""" + ServiceMetadataBehavior.MexContractName + @""" " + ConfigurationStrings.Binding + @"=""mexHttpBinding"" " + ConfigurationStrings.Address + @"=""mex"" />

{3}

 
<configuration>
    <" + ConfigurationStrings.SectionGroupName + @"> 

        <" + ConfigurationStrings.ServicesSectionName + @">
            <!-- {4} -->
            <" + ConfigurationStrings.Service + @" " + ConfigurationStrings.Name + @"=""MyNamespace.MyServiceType"" " + ConfigurationStrings.BehaviorConfiguration + @"=""MyServiceTypeBehaviors"" > 
                <!-- {5} -->
                <!-- {6} --> 
                <" + ConfigurationStrings.Endpoint + @" " + ConfigurationStrings.Contract + @"=""" + ServiceMetadataBehavior.MexContractName + @""" " + ConfigurationStrings.Binding + @"=""mexHttpBinding"" " + ConfigurationStrings.Address + @"=""mex"" /> 
            </" + ConfigurationStrings.Service + @">
        </" + ConfigurationStrings.ServicesSectionName + @"> 

        <" + ConfigurationStrings.BehaviorsSectionName + @">
            <" + ConfigurationStrings.ServiceBehaviors + @">
                <" + ConfigurationStrings.Behavior + @" name=""MyServiceTypeBehaviors"" > 
                    <!-- {7} -->
                    <" + ConfigurationStrings.ServiceMetadataPublishingSectionName + @" " + ConfigurationStrings.HttpGetEnabled + @"=""true"" /> 
                </" + ConfigurationStrings.Behavior + @"> 
            </" + ConfigurationStrings.ServiceBehaviors + @">
        </" + ConfigurationStrings.BehaviorsSectionName + @"> 

    </" + ConfigurationStrings.SectionGroupName + @">
</configuration>

{8}

", SR.GetString(SR.SFxDocExt_NoMetadataSection1), SR.GetString(SR.SFxDocExt_NoMetadataSection2), SR.GetString(SR.SFxDocExt_NoMetadataSection3), SR.GetString(SR.SFxDocExt_NoMetadataSection4), SR.GetString(SR.SFxDocExt_NoMetadataConfigComment1), SR.GetString(SR.SFxDocExt_NoMetadataConfigComment2), SR.GetString(SR.SFxDocExt_NoMetadataConfigComment3), SR.GetString(SR.SFxDocExt_NoMetadataConfigComment4), SR.GetString(SR.SFxDocExt_NoMetadataSection5) )); writer.WriteEndElement(); //HTML } } class ServiceDescriptionMessage : ContentOnlyMessage { WsdlNS.ServiceDescription description; string requestUri; public ServiceDescriptionMessage(WsdlNS.ServiceDescription description, string requestUri) : base() { this.description = description; this.requestUri = requestUri; } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { LocationUpdatingWriter responseWriter = new LocationUpdatingWriter(ServiceMetadataExtension.BaseAddressPattern, requestUri); responseWriter.Writer = writer; description.Write(responseWriter); } } class XmlSchemaMessage : ContentOnlyMessage { XmlSchema schema; string requestUri; public XmlSchemaMessage(XmlSchema schema, string requestUri) : base() { this.schema = schema; this.requestUri = requestUri; } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { LocationUpdatingWriter responseWriter = new LocationUpdatingWriter(ServiceMetadataExtension.BaseAddressPattern, requestUri); responseWriter.Writer = writer; schema.Write(responseWriter); } } #endregion //Helper Message implementations } internal abstract class WriteFilter : XmlDictionaryWriter { internal XmlWriter Writer; } class LocationUpdatingWriter : WriteFilter { readonly string oldValue; readonly string newValue; // passing null for newValue filters any string with oldValue as a prefix rather than replacing internal LocationUpdatingWriter(string oldValue, string newValue) { this.oldValue = oldValue; this.newValue = newValue; } public override void Close() { this.Writer.Close(); } public override void Flush() { this.Writer.Flush(); } public override string LookupPrefix(string ns) { return this.Writer.LookupPrefix(ns); } public override void WriteBase64(byte[] buffer, int index, int count) { this.Writer.WriteBase64(buffer, index, count); } public override void WriteCData(string text) { this.Writer.WriteCData(text); } public override void WriteCharEntity(char ch) { this.Writer.WriteCharEntity(ch); } public override void WriteChars(char[] buffer, int index, int count) { this.Writer.WriteChars(buffer, index, count); } public override void WriteComment(string text) { this.Writer.WriteComment(text); } public override void WriteDocType(string name, string pubid, string sysid, string subset) { this.Writer.WriteDocType(name, pubid, sysid, subset); } public override void WriteEndAttribute() { this.Writer.WriteEndAttribute(); } public override void WriteEndDocument() { this.Writer.WriteEndDocument(); } public override void WriteEndElement() { this.Writer.WriteEndElement(); } public override void WriteEntityRef(string name) { this.Writer.WriteEntityRef(name); } public override void WriteFullEndElement() { this.Writer.WriteFullEndElement(); } public override void WriteProcessingInstruction(string name, string text) { this.Writer.WriteProcessingInstruction(name, text); } public override void WriteRaw(string data) { this.Writer.WriteRaw(data); } public override void WriteRaw(char[] buffer, int index, int count) { this.Writer.WriteRaw(buffer, index, count); } public override void WriteStartAttribute(string prefix, string localName, string ns) { this.Writer.WriteStartAttribute(prefix, localName, ns); } public override void WriteStartDocument(bool standalone) { this.Writer.WriteStartDocument(standalone); } public override void WriteStartDocument() { this.Writer.WriteStartDocument(); } public override void WriteStartElement(string prefix, string localName, string ns) { this.Writer.WriteStartElement(prefix, localName, ns); } public override WriteState WriteState { get { return this.Writer.WriteState; } } public override void WriteString(string text) { if (this.newValue != null) text = text.Replace(this.oldValue, this.newValue); else if (text.StartsWith(this.oldValue, StringComparison.Ordinal)) text = String.Empty; this.Writer.WriteString(text); } public override void WriteSurrogateCharEntity(char lowChar, char highChar) { this.Writer.WriteSurrogateCharEntity(lowChar, highChar); } public override void WriteWhitespace(string ws) { this.Writer.WriteWhitespace(ws); } } } } // 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