Exemplo n.º 1
0
        /// <summary>
        /// Given a path, attempts to match the next part of it to the current segment.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="path">The path.</param>
        /// <returns>
        /// An object that indicates whether the path was successfully matched.
        /// </returns>
        public override SegmentPathMatch MatchPath(IRoute route, PathIterator path)
        {
            var values = new RouteValueDictionary();
            var next = path.Next();
            
            if (next.Length == 0)
            {
                if (defaultValue != UrlParameter.NotSpecified)
                {
                    values[parameterName] = defaultValue;
                }
                else
                {
                    return SegmentPathMatch.Failure(string.Format("The path does not contain a segment for parameter '{0}'", parameterName));   
                }
            }
            else
            {
                values[parameterName] = next;

                if (constraint != null && !constraint.IsValid(route, next, parameterName))
                {
                    return SegmentPathMatch.Failure(string.Format("Segment '{0}' did not match the constraint on parameter '{1}'", next, parameterName));
                }
            }
            return SegmentPathMatch.Successful(values);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ModelBindingContext"/> class.
 /// </summary>
 /// <param name="targetParameterName">Name of the target parameter.</param>
 /// <param name="targetMethod">The target method.</param>
 /// <param name="targetParameterType">Type of the target parameter.</param>
 /// <param name="potentialValues">The potential values.</param>
 public ModelBindingContext(string targetParameterName, MethodInfo targetMethod, Type targetParameterType, RouteValueDictionary potentialValues)
 {
     this.targetParameterName = targetParameterName;
     this.targetMethod = targetMethod;
     this.targetParameterType = targetParameterType;
     this.potentialValues = potentialValues;
 }
Exemplo n.º 3
0
        /// <summary>
        /// Matches a collection of route values to a path. This method is primarily used when producing a
        /// link or navigating programmatically.
        /// </summary>
        /// <param name="values">The values.</param>
        /// <returns>
        /// A result containing the route, if matched, or a reason for failure if not matched.
        /// </returns>
        public PathMatch MatchRouteToPath(RouteValueDictionary values)
        {
            var routes = GetRoutes();
            var fails = new List<PathMatch>();

            if (routes.Count == 0)
            {
                return PathMatch.Failure(null, "No routes are registered in this route collection.");
            }

            foreach (var route in routes)
            {
                var match = route.MatchRouteToPath(values);
                if (match.Success)
                {
                    return match;
                }

                fails.Add(match);
            }

            return PathMatch.Failure(
                null,
                string.Join(Environment.NewLine,
                    fails.Select(fail => string.Format("- Route with specification '{0}' did not match: {1}.", fail.Route, fail.FailReason).CleanErrorMessage()).ToArray()
                    ));
        }
Exemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RouteMatch"/> class.
 /// </summary>
 /// <param name="success">if set to <c>true</c> [success].</param>
 /// <param name="route">The route.</param>
 /// <param name="parameterValues">The parameter values.</param>
 /// <param name="failReason">The fail reason.</param>
 private RouteMatch(bool success, IRoute route, IDictionary parameterValues, string failReason)
 {
     this.success = success;
     this.route = route;
     this.failReason = failReason;
     values = new RouteValueDictionary(parameterValues);
 }
Exemplo n.º 5
0
 private RouteValidationResult EnsureNoUnrecognizableSegments(Segment[] segments, RouteValueDictionary defaults, RouteValueDictionary constraints)
 {
     var unrecognized = segments.Where(x => SupportedSegmentTypes.Contains(x.GetType()) == false).ToList();
     return unrecognized.Count > 0 
         ? RouteValidationResult.Failure(string.Format("Unrecognized segment types were found. If using a custom segment type, please replace the IRouteValidator to enforce your own route validation rules. Unrecognized types: {0}", string.Join(", ", unrecognized.Select(x => "'" + x.GetType().Name + "'").ToArray()))) 
         : RouteValidationResult.Successful();
 }
 public void WhenConstructedWithObjectShouldUsePropertiesAsKeys()
 {
     var parameters = new RouteValueDictionary(new { foo = "bar", abc = "123"});
     Assert.AreEqual(2, parameters.Count);
     Assert.AreEqual("bar", parameters["foo"]);
     Assert.AreEqual("123", parameters["abc"]);
 }
Exemplo n.º 7
0
 private static RouteValidationResult EnsureNoMoreThanOneCatchAllSegment(Segment[] segments, RouteValueDictionary defaults, RouteValueDictionary constraints)
 {
     var catchAll = segments.OfType<CatchAllParameterSegment>().ToList();
     return catchAll.Count > 1 
         ? RouteValidationResult.Failure(string.Format("A route cannot have more than one catch-all parameter. Catch all parameters: {0}", string.Join(", ", catchAll.Select(x => "'" + x.ParameterName + "'").ToArray()))) 
         : RouteValidationResult.Successful();
 }
Exemplo n.º 8
0
 private static RouteValidationResult EnsureCatchAllOnlyAppearAtEnd(Segment[] segments, RouteValueDictionary defaults, RouteValueDictionary constraints)
 {
     var catchAll = segments.OfType<CatchAllParameterSegment>().ToList();
     return catchAll.Count == 1 && segments.Last() != catchAll.Single()
         ? RouteValidationResult.Failure(string.Format("Catch-all parameters may only appear at the end of a route. Catch all parameter: '{0}'", catchAll.Single().ParameterName))
         : RouteValidationResult.Successful();
 }
Exemplo n.º 9
0
 public void RedirectResultShouldUseSuppliedNavigator()
 {
     var request = RequestBuilder.CreateRequest();
     var newRequest = new RouteValueDictionary(new {controller = "Foo", action = "Bar", abc = "123"});
     var result = new RedirectResult(newRequest);
     result.Execute(request.BuildControllerContext());
     request.Navigator.Verify(x => x.ProcessRequest(It.IsAny<NavigationRequest>()));
 }
        /// <summary>
        /// Tries to produce an appropriate segment for the given route specification part. Returning null
        /// indicates that the value is not valid for this kind of segment.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="defaults">The defaults.</param>
        /// <param name="constraints">The constraints.</param>
        /// <returns>
        /// The <see cref="Segment"/> produced by this <see cref="SegmentRecognizer"/>, or null if
        /// the value is not recognizable.
        /// </returns>
        public override Segment Recognise(string value, RouteValueDictionary defaults, RouteValueDictionary constraints)
        {
            var match = formatRegex.Match(value);
            if (!match.Success)
                return null;

            return Build(match, defaults, constraints);
        }
 private static RouteValidationResult MustHaveActionSegment(Segment[] segments, RouteValueDictionary defaults, RouteValueDictionary constraints)
 {
     var hasController = segments.OfType<ParameterSegment>().Any(x => x.ParameterName == "action")
                         || defaults.GetOrDefault<object>("action") != null;
  
     return hasController 
         ? RouteValidationResult.Successful()
         : RouteValidationResult.Failure("The route does not contain an '{action}' segment, and no default action was provided.");
 }
 /// <summary>
 /// Builds a segment from the regular expression match. This method is only called when the base
 /// class matches a the value to this regex.
 /// </summary>
 /// <param name="match">The regular expression match.</param>
 /// <param name="defaults">The default values used in the route.</param>
 /// <param name="constraints">The constraints used in the route.</param>
 /// <returns>The route segment.</returns>
 protected override Segment Build(Match match, RouteValueDictionary defaults, RouteValueDictionary constraints)
 {
     var placeholder = match.Groups[1].Value;
     return new CatchAllParameterSegment(
         placeholder,
         defaults.GetOrDefault<object>(placeholder, UrlParameter.NotSpecified),
         constraints.GetOrDefault<object>(placeholder, UrlParameter.NotSpecified)
         );
 }
        private static RouteValidationResult MustHaveViewModelSegment(Segment[] segments, RouteValueDictionary defaults, RouteValueDictionary constraints)
        {
            var hasViewModel = segments.OfType<ParameterSegment>().Any(x => x.ParameterName == "viewModel")
                || defaults.GetOrDefault<object>("viewModel") != null;

            return hasViewModel 
                ? RouteValidationResult.Successful() 
                : RouteValidationResult.Failure("The route does not contain a '{viewModel}' segment, and no default ViewModel type was provided.");
        }
Exemplo n.º 14
0
 /// <summary>
 /// Navigates to the specified controller and action, passing the parameters dictionary to the action, using a transiton.
 /// </summary>
 /// <param name="navigator">The navigator that will perform the navigation.</param>
 /// <param name="controller">The controller.</param>
 /// <param name="action">The action.</param>
 /// <param name="transition">The transition.</param>
 /// <param name="parameters">The parameters.</param>
 public static void NavigateWithTransition(this INavigator navigator, string controller, string action, string transition, object parameters)
 {
     Guard.ArgumentNotNull(navigator, "navigator");
     var request = new RouteValueDictionary(parameters);
     request["controller"] = controller;
     request["action"] = action;
     request["Transition"] = transition;
     navigator.Navigate(request);
 }
Exemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PathMatch"/> class.
 /// </summary>
 /// <param name="success">if set to <c>true</c> [success].</param>
 /// <param name="route">The route.</param>
 /// <param name="routeValues">The route values.</param>
 /// <param name="leftOver">The left over.</param>
 /// <param name="segmentValues">The segment values.</param>
 /// <param name="failReason">The fail reason.</param>
 private PathMatch(bool success, IRoute route, RouteValueDictionary routeValues, RouteValueDictionary leftOver, List<object> segmentValues, string failReason)
 {
     this.success = success;
     this.route = route;
     this.routeValues = routeValues;
     this.leftOver = leftOver;
     this.segmentValues = segmentValues;
     this.failReason = failReason;
 }
 public void WhenEnumeratedShouldYieldKeyValuePairs()
 {
     var parameters = new RouteValueDictionary(new { foo = "bar", abc = "123" });
     var items = parameters.Select(x => x).ToArray();
     Assert.AreEqual(2, items.Count());
     Assert.AreEqual("foo", items[0].Key);
     Assert.AreEqual("bar", items[0].Value);
     Assert.AreEqual("abc", items[1].Key);
     Assert.AreEqual("123", items[1].Value);
 }
        public void WhenConstructedWithDictionaryShouldCopyItems()
        {
            var dictionary = new Dictionary<string, object>();
            dictionary.Add("Key1", "Value1");
            dictionary.Add("Key2", "Value2");

            var parameters = new RouteValueDictionary(dictionary);
            Assert.AreEqual(2, parameters.Count);
            Assert.AreEqual("Value1", parameters["Key1"]);
            Assert.AreEqual("Value2", parameters["Key2"]);
        }
        public void WhenItemsAreRemovedShouldRemoveItem()
        {
            var parameters = new RouteValueDictionary(new { foo = "bar", abc = "123" });
            Assert.AreEqual(2, parameters.Count);
            Assert.AreEqual("bar", parameters["foo"]);
            Assert.AreEqual("123", parameters["abc"]);

            parameters.Remove("foo");
            Assert.AreEqual(1, parameters.Count);
            Assert.AreEqual("123", parameters["abc"]);
        }
Exemplo n.º 19
0
 private RequestBuilder(string controllerName, string actionName, object routeValues)
 {
     _controllerName = controllerName;
     _actionName = actionName;
     _routeValues = new RouteValueDictionary(routeValues);
     NavigationService = new Mock<INavigationService>();
     Navigator = new Mock<INavigator>();
     Route = new Mock<IRoute>();
     Controller = new Mock<IController>();
     Path = "TestPath";
     ProgressListeners = new List<INavigationProgressListener>();
     Dispatcher = new SingleThreadDispatcher();
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="ResolvedNavigationRequest"/> class.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="path">The path.</param>
        /// <param name="hasNonUriData">Indicates whether the URI is enough to get back to this request, or whether additional data lives in the route data.</param>
        /// <param name="navigator">The navigator.</param>
        /// <param name="route">The route.</param>
        /// <param name="routeData">The route data.</param>
        /// <param name="progressListeners">The progress listeners.</param>
        public ResolvedNavigationRequest(Uri uri, string path, bool hasNonUriData, INavigator navigator, IRoute route, RouteValueDictionary routeData, IEnumerable<INavigationProgressListener> progressListeners)
        {
            Guard.ArgumentNotNullOrEmpty(path, "path");
            Guard.ArgumentNotNull(navigator, "navigator");
            Guard.ArgumentNotNull(route, "route");

            this.uri = uri;
            this.path = path;
            this.hasNonUriData = hasNonUriData;
            this.navigator = navigator;
            this.route = route;
            this.routeData = routeData ?? new RouteValueDictionary();
            this.progressListeners = (progressListeners ?? new INavigationProgressListener[0]).ToList();
        }
Exemplo n.º 21
0
        public ResolvedNavigationRequest BuildRequest()
        {
            Navigator.SetupGet(x => x.Dispatcher).Returns(Dispatcher);

            var values = new RouteValueDictionary(_routeValues);
            values["controller"] = _controllerName;
            values["action"] = _actionName;
            return new ResolvedNavigationRequest(
                new Uri("magellan://MyPath"),
                "MyPath",
                true,
                Navigator.Object, 
                Route.Object, 
                values, 
                ProgressListeners
                );
        }
Exemplo n.º 22
0
 private void ExpectNavigationRequest(string controllerName, string actionName, object parameters)
 {
     Navigator.Setup(x => x.ProcessRequest(It.IsAny<NavigationRequest>())).Callback(
         (NavigationRequest request) =>
         {
             Assert.AreEqual(request.RouteData["action"], actionName);
             Assert.AreEqual(request.RouteData["controller"], controllerName);
             var expectedParameters = new RouteValueDictionary(parameters);
             foreach (var expectedParameter in expectedParameters)
             {
                 var expected = expectedParameter.Value;
                 var paramName = expectedParameter.Key;
                 var actual = request.RouteData[expectedParameter.Key];
                 Assert.AreEqual(expected, actual, string.Format("Parameter {0}", paramName));
             }
         });
 }
Exemplo n.º 23
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Route"/> class.
        /// </summary>
        /// <param name="routeSpecification">The path specification, which gives the pattern that paths will
        /// follow. For example, "/patients/{action}".</param>
        /// <param name="routeHandler">A delegate that will produce a route handler when needed for this
        /// route.</param>
        /// <param name="defaults">The default values of this route.</param>
        /// <param name="constraints">The constraints that will apply to this route.</param>
        /// <param name="parser">An object charged with parsing the route specification, producing a
        /// <see cref="ParsedRoute"/>.</param>
        /// <param name="validator">An object charged with validating the route configuration, ensuring the
        /// route doesn't violate any expectations around how a route can be declared.</param>
        public Route(string routeSpecification, Func<IRouteHandler> routeHandler, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteParser parser, IRouteValidator validator)
        {
            Guard.ArgumentNotNull(routeHandler, "routeHandler");

            pathSpecification = routeSpecification ?? string.Empty;
            this.routeHandler = routeHandler;

            this.validator = validator ?? new RouteValidator();
            this.defaults = defaults ?? new RouteValueDictionary();
            this.constraints = constraints ?? new RouteValueDictionary();
            
            this.parser = parser ?? new RouteParser(
                new ParameterSegmentRecognizer(),
                new LiteralSegmentRecognizer(),
                new CatchAllParameterSegmentRecognizer()
                );
        }
Exemplo n.º 24
0
        /// <summary>
        /// Parses the given route specification, producing a <see cref="ParsedRoute"/>.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="routeSpecification">The route specification.</param>
        /// <param name="defaults">The defaults.</param>
        /// <param name="constraints">The constraints.</param>
        /// <returns></returns>
        public ParsedRoute Parse(IRoute route, string routeSpecification, RouteValueDictionary defaults, RouteValueDictionary constraints)
        {
            var parts = routeSpecification.SplitUrlPath();
            var segments = new Segment[parts.Length];
            for (var i = 0; i < parts.Length; i++)
            {
                var segment = recognisers.Select(x => x.Recognise(parts[i], defaults, constraints)).FirstOrDefault(x => x != null);
                if (segment == null)
                {
                    throw new InvalidRouteException(
                        route,
                        string.Format("Invalid route: {0}. The route segment '{1}' was not recognized as a valid segment.", route, parts[i])
                        );
                }
                segments[i] = segment;
            }

            return new ParsedRoute(defaults, constraints, segments);
        }
        /// <summary>
        /// Matches the path.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        public override SegmentPathMatch MatchPath(IRoute route, PathIterator reader)
        {
            var values = new RouteValueDictionary();
            var path = reader.ReadAll();

            values[parameterName] = path;
            if (path.Length == 0)
            {
                if (defaultValue != UrlParameter.NotSpecified)
                {
                    values[parameterName] = defaultValue;
                }
            }
            else if (constraint != null && !constraint.IsValid(route, path, parameterName))
            {
                return SegmentPathMatch.Failure(string.Format("Segment '{0}' did not match constraint for parameter '{1}'", path, parameterName));
            }
            return SegmentPathMatch.Successful(values);
        }
Exemplo n.º 26
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");
        }
 /// <summary>
 /// Builds a segment from the regular expression match. This method is only called when the base 
 /// class matches a the value to this regex.
 /// </summary>
 /// <param name="match">The regular expression match.</param>
 /// <param name="defaults">The default values used in the route.</param>
 /// <param name="constraints">The constraints used in the route.</param>
 /// <returns>The route segment.</returns>
 protected abstract Segment Build(Match match, RouteValueDictionary defaults, RouteValueDictionary constraints);
 private void NavigateInternal(string controller, string action, object routeValues, NavigationDirections direction)
 {
     var request = new RouteValueDictionary(routeValues);
     request["MessageToken"] = MessageToken;
     _navigator.NavigateWithTransition(controller, action, direction.ToString(), request);
 }
Exemplo n.º 29
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()
                    ));
        }
Exemplo n.º 30
0
        /// <summary>
        /// Resolves and navigates to the first route that matches the given set of route values.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ExecuteRequestWithoutUri(RouteValueDictionary request)
        {
            var path = _routes.MatchRouteToPath(request);
            if (!path.Success)
            {
                throw new UnroutableRequestException(string.Format("The request values '{0}' could not be routed. {1}{2}", request, Environment.NewLine, path.FailReason));
            }

            var handler = path.Route.CreateRouteHandler();

            var uriBuilder = new StringBuilder();
            uriBuilder.Append(_scheme).Append("://").Append(path.Path);

            var queryValues = path.LeftOverValues.Where(x => x.Value is IFormattable || x.Value is string)
                .Select(x => x.Key + "=" + Uri.EscapeDataString(x.Value.ToString()))
                .ToArray();

            if (queryValues.Length > 0)
            {
                uriBuilder.Append("?");
                uriBuilder.Append(string.Join("&", queryValues));
            }

            var uri = new Uri(uriBuilder.ToString());

            handler.ProcessRequest(
                new ResolvedNavigationRequest(
                    uri,
                    path.Path,
                    path.LeftOverValues.Count > queryValues.Length,
                    this,
                    path.Route,
                    path.RouteValues,
                    _progressListeners.Union(Factory.ProgressListeners ?? new NavigationProgressListenerCollection()).ToList()
                    ));
        }