Beispiel #1
0
        public void MatchSingle()
        {
            var t = new UriTemplateTable(new Uri("http://localhost:37564"));

            t.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object> (new UriTemplate("/jsdebug"), null));
            Assert.IsNull(t.MatchSingle(new Uri("http://localhost:37564/js")), "#1");
            Assert.IsNotNull(t.MatchSingle(new Uri("http://localhost:37564/jsdebug")), "#2");
        }
Beispiel #2
0
            public string SelectOperation(ref Message message)
            {
                if (message == null)
                {
                    return(string.Empty);
                }
                object o;

                if (!message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out o))
                {
                    return(string.Empty);
                }
                HttpRequestMessageProperty prop = (HttpRequestMessageProperty)o;

                if (prop.Method != "GET")
                {
                    return(string.Empty);
                }

                UriTemplateMatch match = table.MatchSingle(message.Properties.Via);

                if (match == null)
                {
                    return(string.Empty);
                }
                message.Properties["HelpPageMatch"] = match;
                return(HelpPageInvoker.OperationName);
            }
Beispiel #3
0
        /// <summary>
        /// Associates a local operation with the incoming method.
        /// </summary>
        /// <returns>
        /// The name of the operation to be associated with the <paramref name="message"/>.
        /// </returns>
        /// <param name="message">The incoming <see cref="T:System.ServiceModel.Channels.Message"/> to be associated with an operation.</param>
        public string SelectOperation(ref Message message)
        {
            //Ensure that the documentation page is invoked via the GET method, else don't send the documentation page
            object propertyValue;

            if (!message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out propertyValue) ||
                ((HttpRequestMessageProperty)propertyValue).Method != "GET")
            {
                return(string.Empty);
            }

            //Check for the matches with the help page templates
            UriTemplateMatch match = templateTable.MatchSingle(message.Properties.Via);

            if (match == null)
            {
                for (int i = 0; i < selectors.Length; ++i)
                {
                    string name = selectors[i].SelectOperation(ref message);
                    if (!string.IsNullOrEmpty(name))
                    {
                        return(name);
                    }
                }
                return(string.Empty);
            }

            //Attach the matched object to the message properties with a constant key
            message.Properties[DocumentationMatchPropertyKey] = match;

            //This ensures that our DocumentInvoker is invoked for this documenting operation
            return(OperationName);
        }
Beispiel #4
0
        public static void Snippet10()
        {
            // <Snippet10>
            Uri prefix = new Uri("http://localhost/");

            //Create a series of templates
            UriTemplate weatherByCity    = new UriTemplate("weather/ state}/ city}");
            UriTemplate weatherByCountry = new UriTemplate("weather/ country}/ village}");
            UriTemplate weatherByState   = new UriTemplate("weather/ state}");
            UriTemplate traffic          = new UriTemplate("traffic/*");
            UriTemplate wildcard         = new UriTemplate("*");

            //Create a template table
            UriTemplateTable table = new UriTemplateTable(prefix);

            //Add each template to the table with some associated data
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCity, "weatherByCity"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCountry, "weatherByCountry"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByState, "weatherByState"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(traffic, "traffic"));

            table.MakeReadOnly(true);

            //Call MatchSingle to retrieve some match results:
            Uri weatherInSeattle   = new Uri("http://localhost/weather/Washington/Seattle");
            UriTemplateMatch match = table.MatchSingle(weatherInSeattle);

            Console.WriteLine("Matching template: {0}", match.Template.ToString());
            // </Snippet10>
        }
        private IEnumerable <HttpMethod> RetrieveAllowedMethodsIfAny(HttpRequestMessage request)
        {
            HashSet <HttpMethod> allowedMethods = null;

            foreach (KeyValuePair <HttpMethod, UriTemplateTable> pair in this.methodSpecificTables)
            {
                if (pair.Key != request.Method && pair.Key != wildCardHttpMethod)
                {
                    UriTemplateTable table = pair.Value;

                    if (table.MatchSingle(request.RequestUri) != null)
                    {
                        if (allowedMethods == null)
                        {
                            allowedMethods = new HashSet <HttpMethod>();
                        }

                        if (!allowedMethods.Contains(pair.Key))
                        {
                            allowedMethods.Add(pair.Key);
                        }
                    }
                }
            }

            return(allowedMethods);
        }
Beispiel #6
0
        public string SelectOperation(ref Message message)
        {
            if (!message.Properties.ContainsKey(HttpRequestMessageProperty.Name))
            {
                return("");
            }
            HttpRequestMessageProperty messageProperty = (HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name];

            var address = message.Headers.To;
            var method  = messageProperty.Method;
            UriTemplateTable uriTemplateTable = null;

            if (!this.UriTemplateTables.TryGetValue(method, out uriTemplateTable))
            {
                return("");
            }

            UriTemplateMatch match = uriTemplateTable.MatchSingle(address);

            if (null == match)
            {
                return("");
            }
            return(match.Data.ToString());
        }
        protected virtual string SelectOperation(ref Message message, out bool uriMatched)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
            {
                throw new ArgumentException("There is already message property for Web body format");
            }
            uriMatched = false;
            Uri to = message.Headers.To;

            if (to == null)
            {
                return(String.Empty);
            }

            UriTemplateMatch     match = table.MatchSingle(to);
            OperationDescription od    = null;

            if (match != null)
            {
                uriMatched = true;
                foreach (TemplateTablePair p in table.KeyValuePairs)
                {
                    if (p.Key == match.Template)
                    {
                        od = p.Value as OperationDescription;
                    }
                }
            }
            return(od != null ? od.Name : String.Empty);
        }
Beispiel #8
0
        public void MatchSingleNoPair()
        {
            var t = new UriTemplateTable(new Uri("http://localhost:37564"));

            // at least one UriTemplate must exist in the table.
            t.MatchSingle(new Uri("http://localhost:37564"));
        }
        protected virtual string SelectOperation(ref Message message, out bool uriMatched)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (message.Properties.ContainsKey(UriMatchedProperty.Name))
            {
                throw new ArgumentException(String.Format("There is already a message property for template-matched URI '{0}'", UriMatchedProperty.Name));
            }
            uriMatched = false;
            var hp = (HttpRequestMessageProperty)message.Properties [HttpRequestMessageProperty.Name];

            OperationDescription od = null;
            Message dummy           = message; // since lambda expression prohibits ref variable...

            Uri to = message.Headers.To;
            // First, UriTemplateTable with corresponding HTTP method is tested. Then other tables can be tested for match.
            UriTemplateTable table = null;

            if (hp != null && hp.Method != null)
            {
                tables.TryGetValue(hp.Method, out table);
            }
            // FIXME: looks like To header does not matter on .NET. (But how to match then? I have no idea)
            UriTemplateMatch match = to == null || table == null ? null : table.MatchSingle(to);

            if (to != null && match == null)
            {
                foreach (var tab in tables.Values)
                {
                    if ((match = tab.MatchSingle(to)) != null)
                    {
                        table = tab;
                        break;
                    }
                }
            }

            if (match != null)
            {
                uriMatched = true;
                foreach (TemplateTablePair p in table.KeyValuePairs)
                {
                    if (p.Key == match.Template)
                    {
                        od = p.Value as OperationDescription;
                    }
                }
            }
            if (od != null)
            {
                message.Properties.Add(UriMatchedProperty.Name, new UriMatchedProperty());
            }

            return(uriMatched && od != null ? od.Name : String.Empty);
        }
Beispiel #10
0
        private ServerResponse DispatchRequest(Uri resourcePath, string httpMethod, string requestBody)
        {
            HttpStatusCode   codeToReturn    = HttpStatusCode.OK;
            Response         commandResponse = new Response();
            UriTemplateTable templateTable   = this.FindDispatcherTable(httpMethod);
            UriTemplateMatch match           = templateTable.MatchSingle(resourcePath);

            if (resourcePath.AbsolutePath.ToUpperInvariant().Contains(ShutdownUrlFragment))
            {
                this.serverLogger.Log("Executing: [Shutdown] at URL: " + resourcePath.AbsolutePath);
            }
            else if (match == null)
            {
                codeToReturn          = HttpStatusCode.NotFound;
                commandResponse.Value = "No command associated with " + resourcePath.AbsolutePath;
            }
            else
            {
                string relativeUrl = match.RequestUri.AbsoluteUri.Substring(match.RequestUri.AbsoluteUri.IndexOf(this.listenerPath, StringComparison.OrdinalIgnoreCase) + this.listenerPath.Length - 1);

                string commandName = (string)match.Data;

                Command commandToExecute = new Command(commandName, requestBody);
                foreach (string key in match.BoundVariables.Keys)
                {
                    object value = match.BoundVariables[key];
                    if (relativeUrl.Contains("/element/") && key == "ID")
                    {
                        // So that we are consistent in sending element references over the
                        // wire to the phone, if we find an element reference in the URL,
                        // convert it to an element reference dictionary before sending it.
                        Dictionary <string, object> element = new Dictionary <string, object>();
                        element["ELEMENT"] = match.BoundVariables[key];
                        value = element;
                    }

                    commandToExecute.Parameters.Add(key, value);
                }

                commandResponse = this.executor.Execute(commandToExecute);
                if (commandResponse.Status != WebDriverResult.Success)
                {
                    codeToReturn = HttpStatusCode.InternalServerError;
                }

                if (commandToExecute.Name != DriverCommand.Status)
                {
                    this.serverLogger.Log("Done: " + relativeUrl);
                }
            }

            return(new ServerResponse(commandResponse, codeToReturn));
        }
Beispiel #11
0
        public static void Main()
        {
            Uri prefix = new Uri("http://localhost/");

            //A UriTemplateTable is an associative set of UriTemplates. It lets you match
            //candidate URI's against the templates in the set, and retrieve the data associated
            //with the matching templates.

            //To start, we need some example templates and a table to put them in:
            UriTemplate weatherByCity  = new UriTemplate("weather/{state}/{city}");
            UriTemplate weatherByState = new UriTemplate("weather/{state}");
            UriTemplate traffic        = new UriTemplate("traffic/*");
            UriTemplate wildcard       = new UriTemplate("*");

            UriTemplateTable table = new UriTemplateTable(prefix);

            //Now we associate each template with some data. Here we're just using strings;
            //you can associate anything you want with the template.
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(weatherByCity, "weatherByCity"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(weatherByState, "weatherByState"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(traffic, "traffic"));

            //Once the table is populated, we can use the MatchSingle function to
            //retrieve some match results:

            UriTemplateMatch results = null;
            Uri weatherInSeattle     = new Uri("http://localhost/weather/Washington/Seattle");

            //The Match function will select the best match for the incoming URI
            //based on the templates in the table. There are two variants of Match --
            //Match() can potentially return multiple results, which MatchSingle() will
            //either return exactly one result or throw an exception.

            results = table.MatchSingle(weatherInSeattle);

            //We get back the associated data in the Data member of
            //the UriTemplateMatchResults that are returned.
            if (results != null)
            {
                //Output will be "weatherByCity"
                Console.WriteLine(results.Data);

                //The UriTemplateMatch contains useful data obtained during the
                //matching process.

                Console.WriteLine("State: {0}", results.BoundVariables["state"]);
                Console.WriteLine("City: {0}", results.BoundVariables["city"]);
            }

            Console.WriteLine("Press any key to terminate");
            Console.ReadLine();
        }
        bool CanUriMatch(UriTemplateTable methodSpecificTable, Uri to, HttpRequestMessageProperty prop, Message message, out string operationName)
        {
            operationName = null;
            UriTemplateMatch result = methodSpecificTable.MatchSingle(to);

            if (result != null)
            {
                operationName = result.Data as string;
                Fx.Assert(operationName != null, "bad result");
                AddUriTemplateMatch(result, prop, message);
                return(true);
            }
            return(false);
        }
        bool ShouldRedirectToUriWithSlashAtTheEnd(UriTemplateTable methodSpecificTable, Message message, Uri to)
        {
            UriBuilder ub = new UriBuilder(to);

            if (ub.Path.EndsWith("/", StringComparison.Ordinal))
            {
                return(false);
            }

            ub.Path = ub.Path + "/";
            Uri originalPlusSlash = ub.Uri;

            bool result = false;

            if (methodSpecificTable != null && methodSpecificTable.MatchSingle(originalPlusSlash) != null)
            {
                // as an optimization, we check the table that matched the request's method
                // first, as it is more probable that a hit happens there
                result = true;
            }
            else
            {
                // back-compat:
                // we will redirect as long as there is any method
                // - not necessary the one the user is looking for -
                // that matches the uri with a slash at the end

                foreach (KeyValuePair <string, UriTemplateTable> pair in methodSpecificTables)
                {
                    UriTemplateTable table = pair.Value;
                    if (table != methodSpecificTable && table.MatchSingle(originalPlusSlash) != null)
                    {
                        result = true;
                        break;
                    }
                }
            }

            if (result)
            {
                string hostAndPort = GetAuthority(message);
                originalPlusSlash = UriTemplate.RewriteUri(ub.Uri, hostAndPort);
                message.Properties.Add(RedirectPropertyName, originalPlusSlash);
            }
            return(result);
        }
        private static bool CanUriMatch(UriTemplateTable methodSpecificTable, Uri requestUri, out string operationName)
        {
            Fx.Assert(requestUri != null, "The 'requestUri' parameter should not be null.");

            operationName = null;

            if (methodSpecificTable != null)
            {
                UriTemplateMatch result = methodSpecificTable.MatchSingle(requestUri);
                if (result != null)
                {
                    operationName = result.Data as string;
                    Fx.Assert(operationName != null, "The 'operationName' variable should never be null.");
                    return(true);
                }
            }

            return(false);
        }
Beispiel #15
0
        private ServerResponse DispatchRequest(Uri resourcePath, string httpMethod, string requestBody)
        {
            HttpStatusCode codeToReturn    = HttpStatusCode.OK;
            Response       commandResponse = new Response();
            Dictionary <string, string> locatorParameters = new Dictionary <string, string>();
            UriTemplateTable            templateTable     = this.FindDispatcherTable(httpMethod);
            UriTemplateMatch            match             = templateTable.MatchSingle(resourcePath);

            if (resourcePath.AbsolutePath.ToUpperInvariant().Contains(ShutdownUrlFragment))
            {
                this.serverLogger.Log("Executing: [Shutdown] at URL: " + resourcePath.AbsolutePath);
            }
            else if (match == null)
            {
                codeToReturn          = HttpStatusCode.NotFound;
                commandResponse.Value = "No command associated with " + resourcePath.AbsolutePath;
            }
            else
            {
                string    relativeUrl    = match.RequestUri.AbsoluteUri.Substring(match.RequestUri.AbsoluteUri.IndexOf(this.listenerPath, StringComparison.OrdinalIgnoreCase) + this.listenerPath.Length - 1);
                SessionId sessionIdValue = null;

                string commandName = (string)match.Data;
                foreach (string key in match.BoundVariables.Keys)
                {
                    string value = match.BoundVariables[key];
                    locatorParameters.Add(key, value);
                }

                Command commandToExecute = new Command(commandName, requestBody);

                object          resultValue = null;
                WebDriverResult resultCode  = WebDriverResult.Success;
                try
                {
                    CommandHandler handler = this.handlerFactory.CreateHandler(commandToExecute.Name, locatorParameters, commandToExecute.Parameters);
                    sessionIdValue = handler.SessionId;
                    this.serverLogger.Log("Executing: " + handler.ToString() + " at URL: " + relativeUrl);
                    resultValue  = handler.Execute();
                    codeToReturn = handler.StatusCode;
                }
                catch (CommandNotImplementedException ex)
                {
                    codeToReturn = HttpStatusCode.NotImplemented;
                    resultValue  = ex.Message + " (" + commandName + ")";
                }
                catch (InvalidCommandException ex)
                {
                    codeToReturn = HttpStatusCode.MethodNotAllowed;
                    resultValue  = ex.Message;
                }
                catch (ResourceNotFoundException ex)
                {
                    codeToReturn = HttpStatusCode.NotFound;
                    resultValue  = ex.Message + " (" + resourcePath.AbsolutePath + ")";
                }
                catch (InvalidParameterException ex)
                {
                    codeToReturn = HttpStatusCode.BadRequest;
                    resultValue  = ex.Message;
                }
                catch (NoSuchWindowException ex)
                {
                    resultCode  = WebDriverResult.NoSuchWindow;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (NoSuchElementException ex)
                {
                    resultCode  = WebDriverResult.NoSuchElement;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (NoSuchFrameException ex)
                {
                    resultCode  = WebDriverResult.NoSuchFrame;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (StaleElementReferenceException ex)
                {
                    resultCode  = WebDriverResult.ObsoleteElement;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (ElementNotVisibleException ex)
                {
                    resultCode  = WebDriverResult.ElementNotDisplayed;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (InvalidElementStateException ex)
                {
                    resultCode  = WebDriverResult.InvalidElementState;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (NotImplementedException ex)
                {
                    resultCode  = WebDriverResult.InvalidElementState;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (XPathLookupException ex)
                {
                    resultCode  = WebDriverResult.XPathLookupError;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (WebDriverTimeoutException ex)
                {
                    resultCode  = WebDriverResult.Timeout;
                    resultValue = CreateErrorResponse(commandName, ex);
                }
                catch (UnhandledAlertException ex)
                {
                    resultCode = WebDriverResult.UnexpectedAlertOpen;

                    // This is ridiculously ugly. To be refactored.
                    ErrorResponse err = CreateErrorResponse(commandName, ex);
                    Dictionary <string, object> resp = new Dictionary <string, object>();
                    resp["class"]      = err.ClassName;
                    resp["message"]    = err.Message;
                    resp["screen"]     = err.Screenshot;
                    resp["stackTrace"] = err.StackTrace;
                    Dictionary <string, object> alert = new Dictionary <string, object>();
                    alert["text"] = ex.Alert.Text;
                    resp["alert"] = alert;
                    resultValue   = resp;
                }
                catch (Exception ex)
                {
                    resultCode  = WebDriverResult.UnhandledError;
                    resultValue = CreateErrorResponse(commandName, ex);
                }

                commandResponse        = new Response(sessionIdValue);
                commandResponse.Status = resultCode;
                commandResponse.Value  = resultValue;

                this.serverLogger.Log("Done: " + relativeUrl);
            }

            return(new ServerResponse(commandResponse, codeToReturn));
        }
        protected virtual string SelectOperation(ref Message message, out bool uriMatched)
        {
            if (message == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
            }
            uriMatched = false;
            if (this.methodSpecificTables == 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);
            }

            if (this.helpUriTable != null)
            {
                UriTemplateMatch match = this.helpUriTable.MatchSingle(to);
                if (match != null)
                {
                    uriMatched = true;
                    AddUriTemplateMatch(match, prop, message);
                    if (method == WebHttpBehavior.GET)
                    {
                        return(HelpOperationInvoker.OperationName);
                    }
                    message.Properties.Add(WebHttpDispatchOperationSelector.HttpOperationSelectorDataPropertyName,
                                           new WebHttpDispatchOperationSelectorData()
                    {
                        AllowedMethods = new List <string>()
                        {
                            WebHttpBehavior.GET
                        }
                    });
                    return(this.catchAllOperationName);
                }
            }

            UriTemplateTable methodSpecificTable;
            bool             methodMatchesExactly = methodSpecificTables.TryGetValue(method, out methodSpecificTable);
            if (methodMatchesExactly)
            {
                string operationName;
                uriMatched = CanUriMatch(methodSpecificTable, to, prop, message, out operationName);
                if (uriMatched)
                {
                    return(operationName);
                }
            }

            if (wildcardTable != null)
            {
                string operationName;
                uriMatched = CanUriMatch(wildcardTable, to, prop, message, out operationName);
                if (uriMatched)
                {
                    return(operationName);
                }
            }

            if (ShouldRedirectToUriWithSlashAtTheEnd(methodSpecificTable, message, to))
            {
                return(redirectOperationName);
            }

            // the {method, uri} pair does not match anything the service supports.
            // we know at this point that we'll return some kind of error code, but we
            // should go through all methods for the uri to see if any method is supported
            // so that that information could be returned to the user as well

            List <string> allowedMethods = null;
            foreach (KeyValuePair <string, UriTemplateTable> pair in methodSpecificTables)
            {
                if (pair.Key == method || pair.Key == WebHttpBehavior.WildcardMethod)
                {
                    // the uri must not match the uri template
                    continue;
                }
                UriTemplateTable table = pair.Value;
                if (table.MatchSingle(to) != null)
                {
                    if (allowedMethods == null)
                    {
                        allowedMethods = new List <string>();
                    }

                    //

                    if (!allowedMethods.Contains(pair.Key))
                    {
                        allowedMethods.Add(pair.Key);
                    }
                }
            }

            if (allowedMethods != null)
            {
                uriMatched = true;
                message.Properties.Add(WebHttpDispatchOperationSelector.HttpOperationSelectorDataPropertyName,
                                       new WebHttpDispatchOperationSelectorData()
                {
                    AllowedMethods = allowedMethods
                });
            }
            return(catchAllOperationName);
        }
Beispiel #17
0
        public static void Main()
        {
            Uri prefix = new Uri("http://localhost/");

            //One interesting use for UriTemplateTable is as a dispatching engine.
            //This is accomplished by using the UriTemplateTable to associate
            //a delegate handler with each UriTemplate.

            //To start, we need a UriTemplateTable.
            UriTemplateTable table = new UriTemplateTable(prefix);

            //Now, we add templates to the table and associate them
            //with handler functions, written as anonymous delegates:

            AddHandler(table, new UriTemplate("weather/{state}/{city}"),
                       delegate(UriTemplateMatch r)
            {
                Console.WriteLine("Matched the WeatherByCity template");
                Console.WriteLine("State: {0}", r.BoundVariables["state"]);
                Console.WriteLine("City: {0}", r.BoundVariables["city"]);
            });

            AddHandler(table, new UriTemplate("weather/{state}"),
                       delegate(UriTemplateMatch r)
            {
                Console.WriteLine("Matched the WeatherByState template");
                Console.WriteLine("State: {0}", r.BoundVariables["state"]);
            });

            AddHandler(table, new UriTemplate("traffic/*"),
                       delegate(UriTemplateMatch r)
            {
                Console.WriteLine("Matched the traffic/* template");
                Console.WriteLine("Wildcard segments:");

                foreach (string s in r.WildcardPathSegments)
                {
                    Console.WriteLine("   " + s);
                }
            });

            //MakeReadOnly() freezes the table and prevents further additions.
            //Passing false to this method will disallow duplicate URI's,
            //guaranteeing that at most a single match will be returned.
            //Calling this method explictly is optional, as the collection
            //will be made read-only during the first call to Match() or MatchSingle()
            table.MakeReadOnly(false);

            Uri request = null;

            //Match WeatherByCity
            request = new Uri("http://localhost/weather/Washington/Seattle");
            Console.WriteLine(request);
            InvokeDelegate(table.MatchSingle(request));

            //Match WeatherByState
            request = new Uri("http://localhost/weather/Washington");
            Console.WriteLine(request);
            InvokeDelegate(table.MatchSingle(request));

            //Wildcard match Traffic
            request = new Uri("http://localhost/Traffic/Washington/Seattle/SR520");
            Console.WriteLine(request);
            InvokeDelegate(table.MatchSingle(request));

            Console.WriteLine("Press any key to terminate");
            Console.ReadLine();
        }
        /// <summary>
        /// Executes if the current request is processed by ASP.NET on the begin of request.
        /// Rewrites the Url if there IIS is configured for extensionless Urls.
        /// </summary>
        /// <param name="sender">The current <see cref="HttpApplication" />.</param>
        /// <param name="e">The EventArgs.</param>
        private void context_BeginRequest(object sender, EventArgs e)
        {
            // Get the current HTTP context.
            var context = ((HttpApplication)sender).Context;

            // Get the navigation service.
            var navigationService =
                this.Container.Resolve <INavigationService>();

            // Get the url from the current request.
            var currentPath = context.Request.Url;

            // Set up the table with the URI templates.
            var uriTemplateTable = new UriTemplateTable();

            // Set the table's base address.
            uriTemplateTable.BaseAddress = new Uri(navigationService.GetApplicationPath());

            // Set the rules.
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetDownloadUriTemplate() + "{data}"), HandlerAction.Download));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetRedirectUriTemplate() + "{data}"), HandlerAction.Redirect));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetSecurityTokenServiceUriTemplate()), HandlerAction.SecurityTokenService));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetSecurityTokenServiceUriTemplate().TrimEnd('/')), HandlerAction.SecurityTokenService));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetSecurityTokenServiceUriTemplate() + "{data}"), HandlerAction.SecurityTokenService));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate().TrimEnd('/')), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate()), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate() + "{controller}"), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate() + "{controller}/"), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate() + "{controller}/{controllerAction}"), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate() + "{controller}/{controllerAction}/"), HandlerAction.UI));
            uriTemplateTable.KeyValuePairs.Add(new KeyValuePair <UriTemplate, object>(new UriTemplate(navigationService.GetUIUriTemplate() + "{controller}/{controllerAction}/{data}"), HandlerAction.UI));

            // Check whether the current path matches any of these rewrite rules. If not, return.
            UriTemplateMatch uriTemplateMatch = uriTemplateTable.MatchSingle(currentPath);

            if (uriTemplateMatch == null)
            {
                // Before returning, check whether silkveil.net's application handler was called
                // directly. If so, check if SSL is required for silkveil.net, and redirect, if
                // neccessary.
                if (context.Request.Url.GetLeftPart(UriPartial.Path).TrimEnd('/').ToLowerInvariant() ==
                    navigationService.GetApplicationHandlerFactoryPath().TrimEnd('/').ToLowerInvariant())
                {
                    this.Container.Resolve <IProtocolManager>().RedirectIfNeccessary(context.Request);
                }

                // Return to the caller.
                return;
            }

            // Check if SSL is required for silkveil.net, and redirect, if neccessary.
            this.Container.Resolve <IProtocolManager>().RedirectIfNeccessary(context.Request);

            // Otherwise, redirect using the URI match.
            var applicationHandlerFactoryVirtualPath = navigationService.GetApplicationHandlerFactoryVirtualPath();

            switch ((HandlerAction)uriTemplateMatch.Data)
            {
            case HandlerAction.Download:
                context.RewritePath(string.Format(CultureInfo.InvariantCulture,
                                                  applicationHandlerFactoryVirtualPath + "?Action={0}&Data={1}", HandlerAction.Download, uriTemplateMatch.BoundVariables["data"]));
                break;

            case HandlerAction.Redirect:
                context.RewritePath(string.Format(CultureInfo.InvariantCulture,
                                                  applicationHandlerFactoryVirtualPath + "?Action={0}&Data={1}", HandlerAction.Redirect, uriTemplateMatch.BoundVariables["data"]));
                break;

            case HandlerAction.SecurityTokenService:
                string data = uriTemplateMatch.BoundVariables["data"] ?? "Logon";
                string wa;
                switch (data)
                {
                case "Logon":
                    wa = WSFederationConstants.Actions.SignIn;
                    break;

                case "Logoff":
                    wa = WSFederationConstants.Actions.SignOut;
                    break;

                default:
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture,
                                                                      "The data '{0}' is not supported.", data));
                }
                var wtrealm = "http://www.silkveil.net/";
                context.RewritePath(string.Format(CultureInfo.InvariantCulture,
                                                  applicationHandlerFactoryVirtualPath + "?Action={0}&Data={1}&wa={2}&wtrealm={3}", HandlerAction.SecurityTokenService,
                                                  data, wa, HttpUtility.UrlEncode(wtrealm)));
                break;

            case HandlerAction.UI:
                context.RewritePath(string.Format(CultureInfo.InvariantCulture,
                                                  applicationHandlerFactoryVirtualPath + "?Action={0}&Controller={1}&ControllerAction={2}&Data={3}", HandlerAction.UI,
                                                  uriTemplateMatch.BoundVariables["controller"] ?? string.Empty,
                                                  uriTemplateMatch.BoundVariables["controllerAction"] ?? string.Empty,
                                                  uriTemplateMatch.BoundVariables["data"] ?? string.Empty));
                break;
            }
        }