Esempio n. 1
0
        public void VirtualPath_ReturnsEmptyStringIfNull()
        {
            // Arrange
            var router = new Mock<IRouter>().Object;

            // Act
            var pathData = new VirtualPathData(router, virtualPath: null);

            // Assert
            Assert.Same(router, pathData.Router);
            Assert.Equal(new PathString(string.Empty), pathData.VirtualPath);
            Assert.NotNull(pathData.DataTokens);
            Assert.Empty(pathData.DataTokens);
        }
Esempio n. 2
0
        public void VirtualPath_ReturnsEmptyStringIfNull()
        {
            // Arrange
            var router = Mock.Of<IRouter>();

            // Act
            var pathData = new VirtualPathData(router, virtualPath: null);

            // Assert
            Assert.Same(router, pathData.Router);
            Assert.Empty(pathData.VirtualPath);
            Assert.NotNull(pathData.DataTokens);
            Assert.Empty(pathData.DataTokens);
        }
Esempio n. 3
0
        public void Constructor_CreatesEmptyDataTokensIfNull()
        {
            // Arrange
            var router = new Mock<IRouter>().Object;
            var path = new PathString("/virtual path");

            // Act
            var pathData = new VirtualPathData(router, path, null);

            // Assert
            Assert.Same(router, pathData.Router);
            Assert.Equal(path, pathData.VirtualPath);
            Assert.NotNull(pathData.DataTokens);
            Assert.Empty(pathData.DataTokens);
        }
Esempio n. 4
0
        public void Constructor_CopiesDataTokens()
        {
            // Arrange
            var router = new Mock<IRouter>().Object;
            var path = new PathString("/virtual path");
            var dataTokens = new RouteValueDictionary();
            dataTokens["TestKey"] = "TestValue";

            // Act
            var pathData = new VirtualPathData(router, path, dataTokens);

            // Assert
            Assert.Same(router, pathData.Router);
            Assert.Equal(path, pathData.VirtualPath);
            Assert.NotNull(pathData.DataTokens);
            Assert.Equal("TestValue", pathData.DataTokens["TestKey"]);
            Assert.Equal(1, pathData.DataTokens.Count);
            Assert.NotSame(dataTokens, pathData.DataTokens);
        }
Esempio n. 5
0
        public void Constructor_CopiesDataTokens()
        {
            // Arrange
            var router     = new Mock <IRouter>().Object;
            var path       = new PathString("/virtual path");
            var dataTokens = new RouteValueDictionary();

            dataTokens["TestKey"] = "TestValue";

            // Act
            var pathData = new VirtualPathData(router, path, dataTokens);

            // Assert
            Assert.Same(router, pathData.Router);
            Assert.Equal(path, pathData.VirtualPath);
            Assert.NotNull(pathData.DataTokens);
            Assert.Equal("TestValue", pathData.DataTokens["TestKey"]);
            Assert.Equal(1, pathData.DataTokens.Count);
            Assert.NotSame(dataTokens, pathData.DataTokens);
        }
Esempio n. 6
0
        public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
        {
            EnsureOptions(context.Context);

            // If we're using Best-Effort link generation then it means that we'll first look for a route where
            // the route values are validated (context.IsBound == true). If we can't find a match like that, then
            // we'll return the path from the first route to return one.
            var useBestEffort = _options.UseBestEffortLinkGeneration;

            if (!string.IsNullOrEmpty(context.RouteName))
            {
                var isValidated = false;
                VirtualPathData bestPathData = null;
                INamedRouter matchedNamedRoute;
                if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute))
                {
                    bestPathData = matchedNamedRoute.GetVirtualPath(context);
                    isValidated = context.IsBound;
                }

                // If we get here and context.IsBound == true, then we know we have a match, we want to keep
                // iterating to see if we have multiple matches.
                foreach (var unnamedRoute in _unnamedRoutes)
                {
                    // reset because we're sharing the context
                    context.IsBound = false;

                    var pathData = unnamedRoute.GetVirtualPath(context);
                    if (pathData == null)
                    {
                        continue;
                    }

                    if (bestPathData != null)
                    {
                        // There was already a previous route which matched the name.
                        throw new InvalidOperationException(
                            Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName));
                    }
                    else if (context.IsBound)
                    {
                        // This is the first 'validated' match that we've found.
                        bestPathData = pathData;
                        isValidated = true;
                    }
                    else
                    {
                        Debug.Assert(bestPathData == null);

                        // This is the first 'unvalidated' match that we've found.
                        bestPathData = pathData;
                        isValidated = false;
                    }
                }

                if (isValidated || useBestEffort)
                {
                    context.IsBound = isValidated;

                    if (bestPathData != null)
                    {
                        bestPathData = new VirtualPathData(
                            bestPathData.Router,
                            NormalizeVirtualPath(bestPathData.VirtualPath),
                            bestPathData.DataTokens);
                    }

                    return bestPathData;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                VirtualPathData bestPathData = null;
                for (var i = 0; i < Count; i++)
                {
                    var route = this[i];

                    var pathData = route.GetVirtualPath(context);
                    if (pathData == null)
                    {
                        continue;
                    }

                    if (context.IsBound)
                    {
                        // This route has validated route values, short circuit.
                        return new VirtualPathData(
                            pathData.Router,
                            NormalizeVirtualPath(pathData.VirtualPath),
                            pathData.DataTokens);
                    }
                    else if (bestPathData == null)
                    {
                        // The values aren't validated, but this is the best we've seen so far
                        bestPathData = pathData;
                    }
                }

                if (useBestEffort)
                {
                    return new VirtualPathData(
                        bestPathData.Router,
                        NormalizeVirtualPath(bestPathData.VirtualPath),
                        bestPathData.DataTokens);
                }
                else
                {
                    return null;
                }
            }
        }
Esempio n. 7
0
        public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
        {
            EnsureOptions(context.Context);

            // If we're using Best-Effort link generation then it means that we'll first look for a route where
            // the route values are validated (context.IsBound == true). If we can't find a match like that, then
            // we'll return the path from the first route to return one.
            var useBestEffort = _options.UseBestEffortLinkGeneration;

            if (!string.IsNullOrEmpty(context.RouteName))
            {
                var             isValidated  = false;
                VirtualPathData bestPathData = null;
                INamedRouter    matchedNamedRoute;
                if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute))
                {
                    bestPathData = matchedNamedRoute.GetVirtualPath(context);
                    isValidated  = context.IsBound;
                }

                // If we get here and context.IsBound == true, then we know we have a match, we want to keep
                // iterating to see if we have multiple matches.
                foreach (var unnamedRoute in _unnamedRoutes)
                {
                    // reset because we're sharing the context
                    context.IsBound = false;

                    var pathData = unnamedRoute.GetVirtualPath(context);
                    if (pathData == null)
                    {
                        continue;
                    }

                    if (bestPathData != null)
                    {
                        // There was already a previous route which matched the name.
                        throw new InvalidOperationException(
                                  Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName));
                    }
                    else if (context.IsBound)
                    {
                        // This is the first 'validated' match that we've found.
                        bestPathData = pathData;
                        isValidated  = true;
                    }
                    else
                    {
                        Debug.Assert(bestPathData == null);

                        // This is the first 'unvalidated' match that we've found.
                        bestPathData = pathData;
                        isValidated  = false;
                    }
                }

                if (isValidated || useBestEffort)
                {
                    context.IsBound = isValidated;

                    if (bestPathData != null)
                    {
                        bestPathData = new VirtualPathData(
                            bestPathData.Router,
                            NormalizeVirtualPath(bestPathData.VirtualPath),
                            bestPathData.DataTokens);
                    }

                    return(bestPathData);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                VirtualPathData bestPathData = null;
                for (var i = 0; i < Count; i++)
                {
                    var route = this[i];

                    var pathData = route.GetVirtualPath(context);
                    if (pathData == null)
                    {
                        continue;
                    }

                    if (context.IsBound)
                    {
                        // This route has validated route values, short circuit.
                        return(new VirtualPathData(
                                   pathData.Router,
                                   NormalizeVirtualPath(pathData.VirtualPath),
                                   pathData.DataTokens));
                    }
                    else if (bestPathData == null)
                    {
                        // The values aren't validated, but this is the best we've seen so far
                        bestPathData = pathData;
                    }
                }

                if (useBestEffort)
                {
                    return(new VirtualPathData(
                               bestPathData.Router,
                               NormalizeVirtualPath(bestPathData.VirtualPath),
                               bestPathData.DataTokens));
                }
                else
                {
                    return(null);
                }
            }
        }
Esempio n. 8
0
        private VirtualPathData NormalizeVirtualPath(VirtualPathData pathData)
        {
            if (pathData == null)
            {
                return pathData;
            }

            var url = pathData.VirtualPath;

            if (!string.IsNullOrEmpty(url) && (_options.LowercaseUrls || _options.AppendTrailingSlash))
            {
                var indexOfSeparator = url.IndexOfAny(new char[] { '?', '#' });
                var urlWithoutQueryString = url;
                var queryString = string.Empty;

                if (indexOfSeparator != -1)
                {
                    urlWithoutQueryString = url.Substring(0, indexOfSeparator);
                    queryString = url.Substring(indexOfSeparator);
                }

                if (_options.LowercaseUrls)
                {
                    urlWithoutQueryString = urlWithoutQueryString.ToLowerInvariant();
                }

                if (_options.AppendTrailingSlash && !urlWithoutQueryString.EndsWith("/"))
                {
                    urlWithoutQueryString += "/";
                }

                // queryString will contain the delimiter ? or # as the first character, so it's safe to append.
                url = urlWithoutQueryString + queryString;

                return new VirtualPathData(pathData.Router, url, pathData.DataTokens);
            }

            return pathData;
        }
Esempio n. 9
0
        /// <inheritdoc />
        public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
        {
            EnsureBinder(context.HttpContext);
            EnsureLoggers(context.HttpContext);

            var values = _binder.GetValues(context.AmbientValues, context.Values);
            if (values == null)
            {
                // We're missing one of the required values for this route.
                return null;
            }

            if (!RouteConstraintMatcher.Match(
                Constraints,
                values.CombinedValues,
                context.HttpContext,
                this,
                RouteDirection.UrlGeneration,
                _constraintLogger))
            {
                return null;
            }

            context.Values = values.CombinedValues;

            var pathData = OnVirtualPathGenerated(context);
            if (pathData != null)
            {
                // If the target generates a value then that can short circuit.
                return pathData;
            }

            // If we can produce a value go ahead and do it, the caller can check context.IsBound
            // to see if the values were validated.

            // When we still cannot produce a value, this should return null.
            var virtualPath = _binder.BindValues(values.AcceptedValues);
            if (virtualPath == null)
            {
                return null;
            }

            pathData = new VirtualPathData(this, virtualPath);
            if (DataTokens != null)
            {
                foreach (var dataToken in DataTokens)
                {
                    pathData.DataTokens.Add(dataToken.Key, dataToken.Value);
                }
            }

            return pathData;
        }