예제 #1
0
        /// <summary>
        /// Attempts to matche given route values to this parsed route, building up a probable path that
        /// could be used to navigate to this route.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="values">The values.</param>
        /// <returns>
        /// An object indicating the success or failure of the attempt to match the path.
        /// </returns>
        public PathMatch MatchRouteToPath(IRoute route, RouteValueDictionary values)
        {
            var valueBag      = new RouteValueBag(values);
            var segmentValues = new List <object>();

            foreach (var segment in Segments)
            {
                var match = segment.MatchValues(route, valueBag);
                if (match.Success)
                {
                    segmentValues.Add(match.SegmentValue);
                }
                else
                {
                    return(PathMatch.Failure(route, match.FailReason));
                }
            }

            var allValues = new RouteValueDictionary(Defaults);

            allValues.AddRange(values, true);
            allValues.AddRange(values, true);

            var leftOver = valueBag.GetRemaining();

            foreach (var leftOverItem in leftOver)
            {
                var key = leftOverItem.Key;
                if (Defaults.ContainsKey(key))
                {
                    var leftOverValue = leftOverItem.Value;
                    var defaultValue  = Defaults[leftOverItem.Key];

                    if ((leftOverValue == null || defaultValue == null) && (leftOverValue != defaultValue) ||
                        (leftOverValue != null && !leftOverValue.Equals(defaultValue)))
                    {
                        return(PathMatch.Failure(route, string.Format("The route was a close match, but the value of the '{0}' parameter was expected to be '{1}', but '{2}' was provided instead.", key, defaultValue, leftOverValue)));
                    }
                }
            }

            if (leftOver.Count > 0)
            {
                foreach (var defaultItem in Defaults.Where(item => leftOver.ContainsKey(item.Key)))
                {
                    leftOver.Remove(defaultItem.Key);
                }
            }

            return(PathMatch.Successful(route, allValues, leftOver, segmentValues));
        }
예제 #2
0
        /// <summary>
        /// Attempts to matche a path to this parsed route.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="request">The request.</param>
        /// <returns>An object indicating the success or failure of the attempt to match the path.</returns>
        public RouteMatch MatchPathToRoute(IRoute route, string request)
        {
            var values   = new RouteValueDictionary();
            var iterator = new PathIterator(request);

            foreach (var segment in Segments)
            {
                var match = segment.MatchPath(route, iterator);
                if (match.Success)
                {
                    values.AddRange(match.Values);
                }
                else
                {
                    return(RouteMatch.Failure(route, match.FailReason));
                }
            }

            return(iterator.IsAtEnd
                ? RouteMatch.Successful(route, values)
                : RouteMatch.Failure(route, "Route was initially matched, but the request contains additional unexpected segments"));
        }
예제 #3
0
        /// <summary>
        /// Attempts to matche a path to this parsed route.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="request">The request.</param>
        /// <returns>An object indicating the success or failure of the attempt to match the path.</returns>
        public RouteMatch MatchPathToRoute(IRoute route, string request)
        {
            var values = new RouteValueDictionary();
            var iterator = new PathIterator(request);

            foreach (var segment in Segments)
            {
                var match = segment.MatchPath(route, iterator);
                if (match.Success)
                {
                    values.AddRange(match.Values);
                }
                else
                {
                    return RouteMatch.Failure(route, match.FailReason);
                }
            }

            return iterator.IsAtEnd
                ? RouteMatch.Successful(route, values)
                : RouteMatch.Failure(route, "Route was initially matched, but the request contains additional unexpected segments");
        }
예제 #4
0
        /// <summary>
        /// Navigates to the specified URI, resolving the first matching route.
        /// </summary>
        /// <param name="requestUri">The request URI.</param>
        /// <param name="additionalData">Additional data (like post data) that is not in the URI but is used
        /// for navigation.</param>
        private void ExecuteRequestWithUri(Uri requestUri, RouteValueDictionary additionalData)
        {
            additionalData = additionalData ?? new RouteValueDictionary();
            var path = requestUri.GetComponents(UriComponents.Host | UriComponents.Path, UriFormat.Unescaped);
            var queryString = requestUri.GetComponents(UriComponents.Query, UriFormat.Unescaped);

            var route = _routes.MatchPathToRoute(path);
            if (!route.Success)
            {
                throw new UnroutableRequestException(string.Format("The request URI '{0}' could not be routed. {1}{2}", requestUri, Environment.NewLine, route.FailReason));
            }

            // Create a value dictionary with all of the known information - post data, query string data, 
            // and data extracted from the route. We'll use this for the navigation request.
            var data = new RouteValueDictionary(additionalData);
            data.AddRange(route.Values, true);
            var queryValues = new QueryValueCollection(queryString);
            foreach (var pair in queryValues)
            {
                if (!data.ContainsKey(pair.Key))
                {
                    data[pair.Key] = pair.Value;
                }
            }

            var handler = route.Route.CreateRouteHandler();

            handler.ProcessRequest(
                new ResolvedNavigationRequest(
                    requestUri,
                    path,
                    additionalData.Count > 0,
                    this,
                    route.Route,
                    data,
                    _progressListeners.Union(Factory.ProgressListeners ?? new NavigationProgressListenerCollection()).ToList()
                    ));
        }
예제 #5
0
        /// <summary>
        /// Attempts to matche given route values to this parsed route, building up a probable path that
        /// could be used to navigate to this route.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="values">The values.</param>
        /// <returns>
        /// An object indicating the success or failure of the attempt to match the path.
        /// </returns>
        public PathMatch MatchRouteToPath(IRoute route, RouteValueDictionary values)
        {
            var valueBag = new RouteValueBag(values);
            var segmentValues = new List<object>();

            foreach (var segment in Segments)
            {
                var match = segment.MatchValues(route, valueBag);
                if (match.Success)
                {
                    segmentValues.Add(match.SegmentValue);
                }
                else
                {
                    return PathMatch.Failure(route, match.FailReason);
                }
            }

            var allValues = new RouteValueDictionary(Defaults);
            allValues.AddRange(values, true);
            allValues.AddRange(values, true);

            var leftOver = valueBag.GetRemaining();
            
            foreach (var leftOverItem in leftOver)
            {
                var key = leftOverItem.Key;
                if (Defaults.ContainsKey(key))
                {
                    var leftOverValue = leftOverItem.Value;
                    var defaultValue = Defaults[leftOverItem.Key];
                    
                    if ((leftOverValue == null || defaultValue == null) && (leftOverValue != defaultValue)
                        || (leftOverValue != null && !leftOverValue.Equals(defaultValue)))
                    {
                        return PathMatch.Failure(route, string.Format("The route was a close match, but the value of the '{0}' parameter was expected to be '{1}', but '{2}' was provided instead.", key, defaultValue, leftOverValue));
                    }
                }
            }
            
            if (leftOver.Count > 0)
            {
                foreach (var defaultItem in Defaults.Where(item => leftOver.ContainsKey(item.Key)))
                {
                    leftOver.Remove(defaultItem.Key);
                }
            }

            return PathMatch.Successful(route, allValues, leftOver, segmentValues);
        }
 public void ShouldNotOverrideAddItemsWhenToldNotTo()
 {
     var original = new RouteValueDictionary(new { foo = "1", abc = "3" });
     var replacement = new RouteValueDictionary(new { foo = "2", abc = "4", def = "6" });
     original.AddRange(replacement, false);
     Assert.AreEqual("1", original["foo"]);
     Assert.AreEqual("3", original["abc"]);
     Assert.AreEqual("6", original["def"]);
 }
 public void CannotAddRangeSelf()
 {
     var parameters = new RouteValueDictionary();
     Assert.Throws<InvalidOperationException>(() => parameters.AddRange(parameters));
 }
 public void ShouldIgnoreNullAddRange()
 {
     var original = new RouteValueDictionary(new { foo = "1", abc = "3" });
     original.AddRange(null);
 }