WebHttpDispatchOperationSelector.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 / NetFx35 / System.ServiceModel.Web / System / ServiceModel / Dispatcher / WebHttpDispatchOperationSelector.cs / 3 / WebHttpDispatchOperationSelector.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
#pragma warning disable 1634, 1691
namespace System.ServiceModel.Dispatcher 
{
    using System; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Collections.Generic;
    using System.Globalization; 
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.Collections.ObjectModel; 
    using System.ServiceModel.Web;
    using System.Diagnostics; 
    using System.ServiceModel.Diagnostics; 
    using System.ServiceModel.Activation;
 
    public class WebHttpDispatchOperationSelector : IDispatchOperationSelector
    {
        public const string HttpOperationSelectorUriMatchedPropertyName = "UriMatched";
        internal const string redirectOperationName = ""; // always unhandled invoker 
        internal const string RedirectPropertyName = "WebHttpRedirect";
 
        string catchAllOperationName = ""; // user UT=* Method=* operation, else unhandled invoker 

        UriTemplateTable table; 

        public WebHttpDispatchOperationSelector(ServiceEndpoint endpoint)
        {
            if (endpoint == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint"); 
            } 
            if (endpoint.Address == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                    SR2.GetString(SR2.EndpointAddressCannotBeNull)));
            }
#pragma warning disable 56506 // [....], endpoint.Address.Uri is never null 
            this.table = new UriTemplateTable(endpoint.Address.Uri);
#pragma warning restore 56506 
            Dictionary alreadyHaves = new Dictionary(); 

#pragma warning disable 56506 // [....], endpoint.Contract is never null 
            foreach (OperationDescription od in endpoint.Contract.Operations)
#pragma warning restore 56506
            {
                // ignore callback operations 
                if (od.Messages[0].Direction == MessageDirection.Input)
                { 
                    string method = WebHttpBehavior.GetWebMethod(od); 
                    string path = UriTemplateClientFormatter.GetUTStringOrDefault(od);
                    if (UriTemplateHelpers.IsWildcardPath(path) && (method == WebHttpBehavior.WildcardMethod)) 
                    {
                        if (this.catchAllOperationName != "")
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                new InvalidOperationException(
                                SR2.GetString(SR2.MultipleOperationsInContractWithPathMethod, 
                                endpoint.Contract.Name, path, method))); 
                        }
                        this.catchAllOperationName = od.Name; 
                    }
                    UriTemplate ut = new UriTemplate(path);
                    WCFKey wcfKey = new WCFKey(ut, method);
                    if (alreadyHaves.ContainsKey(wcfKey)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new InvalidOperationException( 
                            SR2.GetString(SR2.MultipleOperationsInContractWithPathMethod,
                            endpoint.Contract.Name, path, method))); 
                    }
                    alreadyHaves.Add(wcfKey, od.Name);
                    WCFLookupResult wlr = new WCFLookupResult(method, od.Name);
                    table.KeyValuePairs.Add(new KeyValuePair(ut, wlr)); 
                }
            } 
            if (this.table.KeyValuePairs.Count == 0) 
            {
                this.table = null; 
            }
            else
            {
                this.table.MakeReadOnly(true); 
            }
        } 
 
        protected WebHttpDispatchOperationSelector()
        { 
        }

        [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#", Justification = "This method is defined by the IDispatchOperationSelector interface")]
        public string SelectOperation(ref Message message) 
        {
            if (message == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
            } 
            bool uriMatched;
            string result = this.SelectOperation(ref message, out uriMatched);
#pragma warning disable 56506 // [....], Message.Properties is never null
            message.Properties.Add(HttpOperationSelectorUriMatchedPropertyName, uriMatched); 
#pragma warning restore 56506
            if (result != null && DiagnosticUtility.ShouldTraceInformation) 
            { 
#pragma warning disable 56506 // [....], Message.Headers is never null
                DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.WebRequestMatchesOperation, SR2.GetString(SR2.TraceCodeWebRequestMatchesOperation, message.Headers.To, result)); 
#pragma warning restore 56506
            }
            return result;
        } 

        [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#", Justification = "This method is like that defined by the IDispatchOperationSelector interface")] 
        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "This API needs to return multiple things")] 
        protected virtual string SelectOperation(ref Message message, out bool uriMatched)
        { 
            if (message == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
            } 
            uriMatched = false;
            if (this.table == null) 
            { 
                return this.catchAllOperationName;
            } 

#pragma warning disable 56506 // [....], message.Properties is never null
            if (!message.Properties.ContainsKey(HttpRequestMessageProperty.Name))
            { 
                return this.catchAllOperationName;
            } 
            HttpRequestMessageProperty prop = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; 
            if (prop == null)
            { 
                return this.catchAllOperationName;
            }
            string method = prop.Method;
 
            Uri to = message.Headers.To;
#pragma warning restore 56506 
 
            if (to == null)
            { 
                return this.catchAllOperationName;
            }

            Collection results = table.Match(to); 
            if (results.Count == 0)
            { 
                UriBuilder ub = new UriBuilder(to); 
                if (!ub.Path.EndsWith("/", StringComparison.Ordinal))
                { 
                    ub.Path = ub.Path + "/";
                    Uri originalPlusSlash = ub.Uri;
                    results = table.Match(originalPlusSlash);
                    if (results.Count != 0) 
                    {
                        if (message.Properties.ContainsKey(HostedHttpContext.OriginalHttpRequestUriPropertyName)) 
                        { 
                            ub.Host = ((Uri)(message.Properties[HostedHttpContext.OriginalHttpRequestUriPropertyName])).Host;
                            originalPlusSlash = ub.Uri; 
                        }
                        message.Properties.Add(RedirectPropertyName, originalPlusSlash);
                        return redirectOperationName;
                    } 
                }
            } 
            uriMatched = (results.Count != 0); 
            string methodStarOperationName = catchAllOperationName;
            UriTemplateMatch methodStarMatch = null; 
            for (int i = 0; i < results.Count; ++i)
            {
                UriTemplateMatch r = results[i];
                WCFLookupResult wlr = r.Data as WCFLookupResult; 
                Fx.Assert(wlr != null, "bad result");
                if (wlr.Method == method) 
                { 
                    message.Properties.Add(IncomingWebRequestContext.UriTemplateMatchResultsPropertyName, r);
                    return wlr.OperationName; 
                }
                if (wlr.Method == WebHttpBehavior.WildcardMethod)
                {
                    Fx.Assert(methodStarOperationName == catchAllOperationName, "there should be at most one WildcardMethod result in results"); 
                    methodStarMatch = r;
                    methodStarOperationName = wlr.OperationName; 
                } 
            }
            if (methodStarMatch != null) 
            {
                message.Properties.Add(IncomingWebRequestContext.UriTemplateMatchResultsPropertyName, methodStarMatch);
            }
            return methodStarOperationName; 
        }
 
        // to enforce that no two ops have same UriTemplate & Method 
        class WCFKey
        { 
            string method;
            UriTemplate uriTemplate;
            public WCFKey(UriTemplate uriTemplate, string method)
            { 
                this.uriTemplate = uriTemplate;
                this.method = method; 
            } 
            public override bool Equals(object obj)
            { 
                WCFKey other = obj as WCFKey;
                if (other == null)
                {
                    return false; 
                }
                return this.uriTemplate.IsEquivalentTo(other.uriTemplate) && this.method == other.method; 
            } 
            public override int GetHashCode()
            { 
                return UriTemplateEquivalenceComparer.Instance.GetHashCode(this.uriTemplate);
            }
        }
 
        // data of the UriTemplateMatchResults
        class WCFLookupResult 
        { 
            string method;
            string operationName; 
            public WCFLookupResult(string method, string operationName)
            {
                this.method = method;
                this.operationName = operationName; 
            }
            public string Method 
            { get { return this.method; } } 
            public string OperationName
            { get { return this.operationName; } } 
        }

    }
} 


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