/// <summary>
        /// Improve SEO by stopping duplicate URL's due to case differences or trailing slashes.
        /// See http://googlewebmastercentral.blogspot.co.uk/2010/04/to-slash-or-not-to-slash.html
        /// </summary>
        /// <param name="routeOptions">The routing options.</param>
        private static void ConfigureRouting(RouteOptions routeOptions)
        {
            // TODO: AppendTrailingSlash does not yet exist but will be added in the next version of MVC.
            // All generated URL's should append a trailing slash.
            // routeOptions.AppendTrailingSlash = true;

            // All generated URL's should be lower-case.
            routeOptions.LowercaseUrls = true;

            // TODO: IgnoreRoute does not yet exist in MVC 6.

            //            // IgnoreRoute - Tell the routing system to ignore certain routes for better performance.
            //            // Ignore .axd files.
            //            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            //            // Ignore everything in the Content folder.
            //            routes.IgnoreRoute("Content/{*pathInfo}");
            //            // Ignore everything in the Scripts folder.
            //            routes.IgnoreRoute("Scripts/{*pathInfo}");
            //            // Ignore the Forbidden.html file.
            //            routes.IgnoreRoute("Error/Forbidden.html");
            //            // Ignore the GatewayTimeout.html file.
            //            routes.IgnoreRoute("Error/GatewayTimeout.html");
            //            // Ignore the ServiceUnavailable.html file.
            //            routes.IgnoreRoute("Error/ServiceUnavailable.html");
            //            // Ignore the humans.txt file.
            //            routes.IgnoreRoute("humans.txt");
        }
예제 #2
0
        public void GetVirtualPath_NoBestEffort_NoMatch()
        {
            // Arrange
            var route1 = CreateRoute(accept: false, match: true, matchValue: "best");
            var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
            var route3 = CreateRoute(accept: false, match: true, matchValue: "bad");

            var routeCollection = new RouteCollection();

            routeCollection.Add(route1.Object);
            routeCollection.Add(route2.Object);
            routeCollection.Add(route3.Object);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = false,
            };

            var virtualPathContext = CreateVirtualPathContext(options: options);

            // Act
            var path = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Null(path);

            // All of these should be called
            route1.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Once());
            route2.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Once());
            route3.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Once());
        }
예제 #3
0
        public void GetVirtualPath_BestEffort_FirstValidatedValuesWins_ShortCircuit()
        {
            // Arrange
            var route1 = CreateRoute(accept: false, match: true, matchValue: "bad");
            var route2 = CreateRoute(accept: true, match: true, matchValue: "best");
            var route3 = CreateRoute(accept: true, match: true, matchValue: "bad");

            var routeCollection = new RouteCollection();

            routeCollection.Add(route1.Object);
            routeCollection.Add(route2.Object);
            routeCollection.Add(route3.Object);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext(options: options);

            // Act
            var pathData = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Equal(new PathString("/best"), pathData.VirtualPath);
            Assert.Same(route2.Object, pathData.Router);
            Assert.Empty(pathData.DataTokens);

            route1.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Once());
            route2.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Once());
            route3.Verify(r => r.GetVirtualPath(It.IsAny <VirtualPathContext>()), Times.Never());
        }
예제 #4
0
        public void GetVirtualPath_NamedRoute_BestEffort_FirstRouteWins()
        {
            // Arrange
            var bestMatch = CreateNamedRoute("Match", accept: false, matchValue: "best");
            var noMatch   = CreateNamedRoute("NoMatch", accept: false, matchValue: "bad");

            var routeCollection = new RouteCollection();

            routeCollection.Add(noMatch);

            var innerRouteCollection = new RouteCollection();

            innerRouteCollection.Add(bestMatch);
            routeCollection.Add(innerRouteCollection);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext("Match", options: options);

            // Act
            var pathData = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Equal(new PathString("/best"), pathData.VirtualPath);
            var namedRouter = Assert.IsAssignableFrom <INamedRouter>(pathData.Router);

            Assert.Equal("Match", namedRouter.Name);
            Assert.Empty(pathData.DataTokens);
        }
예제 #5
0
        public void GetVirtualPath_AmbiguousRoutes_RequiresRouteValueValidation_Error()
        {
            // Arrange
            var namedRoute = CreateNamedRoute("Ambiguous", accept: false);

            var routeCollection = new RouteCollection();

            routeCollection.Add(namedRoute);

            var innerRouteCollection = new RouteCollection();

            innerRouteCollection.Add(namedRoute);
            routeCollection.Add(innerRouteCollection);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext("Ambiguous", options: options);

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => routeCollection.GetVirtualPath(virtualPathContext));

            Assert.Equal("The supplied route name 'Ambiguous' is ambiguous and matched more than one route.", ex.Message);
        }
예제 #6
0
 private void EnsureOptions(HttpContext context)
 {
     if (_options == null)
     {
         _options = context.RequestServices.GetRequiredService <IOptions <RouteOptions> >().Value;
     }
 }
예제 #7
0
        private static RouteContext CreateRouteContext(
            string requestPath,
            ILoggerFactory loggerFactory = null,
            RouteOptions options         = null)
        {
            if (loggerFactory == null)
            {
                loggerFactory = NullLoggerFactory.Instance;
            }

            if (options == null)
            {
                options = new RouteOptions();
            }

            var request = new Mock <HttpRequest>(MockBehavior.Strict);

            request.SetupGet(r => r.Path).Returns(new PathString(requestPath));

            var optionsAccessor = new Mock <IOptions <RouteOptions> >(MockBehavior.Strict);

            optionsAccessor.SetupGet(o => o.Value).Returns(options);

            var context = new Mock <HttpContext>(MockBehavior.Strict);

            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
            .Returns(loggerFactory);
            context.Setup(m => m.RequestServices.GetService(typeof(IOptions <RouteOptions>)))
            .Returns(optionsAccessor.Object);
            context.SetupGet(c => c.Request).Returns(request.Object);

            return(new RouteContext(context.Object));
        }
예제 #8
0
        private static VirtualPathContext CreateVirtualPathContext(
            string routeName             = null,
            ILoggerFactory loggerFactory = null,
            RouteOptions options         = null)
        {
            if (loggerFactory == null)
            {
                loggerFactory = NullLoggerFactory.Instance;
            }

            if (options == null)
            {
                options = new RouteOptions();
            }


            var request = new Mock <HttpRequest>(MockBehavior.Strict);

            var optionsAccessor = new Mock <IOptions <RouteOptions> >(MockBehavior.Strict);

            optionsAccessor.SetupGet(o => o.Options).Returns(options);

            var context = new Mock <HttpContext>(MockBehavior.Strict);

            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
            .Returns(loggerFactory);
            context.Setup(m => m.RequestServices.GetService(typeof(IOptions <RouteOptions>)))
            .Returns(optionsAccessor.Object);
            context.SetupGet(c => c.Request).Returns(request.Object);

            return(new VirtualPathContext(context.Object, null, null, routeName));
        }
 /// <summary>
 /// Adds filters which help improve search engine optimization (SEO).
 /// </summary>
 private static void ConfigureSearchEngineOptimizationFilters(ICollection<IFilter> filters, RouteOptions routeOptions)
 {
     filters.Add(new RedirectToCanonicalUrlAttribute(
          appendTrailingSlash: true, // TODO: Add routeOptions.AppendTrailingSlash when it is added.
          lowercaseUrls: routeOptions.LowercaseUrls,
          ignoreControllers: new string[]
          {
             ControllerName.Elmah,
             ControllerName.Error
          }));
 }
예제 #10
0
        private static RouteOptions GetRouteOptions(
            bool lowerCaseUrls = false,
            bool useBestEffortLinkGeneration = true,
            bool appendTrailingSlash         = false)
        {
            var routeOptions = new RouteOptions();

            routeOptions.LowercaseUrls = lowerCaseUrls;
            routeOptions.UseBestEffortLinkGeneration = useBestEffortLinkGeneration;
            routeOptions.AppendTrailingSlash         = appendTrailingSlash;

            return(routeOptions);
        }
        /// <summary>
        /// Improve SEO by stopping duplicate URL's due to case differences or trailing slashes.
        /// See http://googlewebmastercentral.blogspot.co.uk/2010/04/to-slash-or-not-to-slash.html
        /// </summary>
        /// <param name="routeOptions">The routing options.</param>
        private static void ConfigureRouting(RouteOptions routeOptions)
        {
            // All generated URL's should append a trailing slash.
            routeOptions.AppendTrailingSlash = true;

            // All generated URL's should be lower-case.
            routeOptions.LowercaseUrls = true;

            // TODO: IgnoreRoute does not yet exist in MVC 6.

            // // IgnoreRoute - Tell the routing system to ignore certain routes for better performance.
            // // Ignore .axd files.
            // routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            // // Ignore everything in the Content folder.
            // routes.IgnoreRoute("Content/{*pathInfo}");
            // // Ignore the humans.txt file.
            // routes.IgnoreRoute("humans.txt");
        }
예제 #12
0
        private static VirtualPathContext CreateVirtualPathContext(
            RouteValueDictionary values,
            RouteOptions options = null,
            string routeName     = null)
        {
            var optionsAccessor = new Mock <IOptions <RouteOptions> >(MockBehavior.Strict);

            optionsAccessor.SetupGet(o => o.Value).Returns(options);

            var context = new Mock <HttpContext>(MockBehavior.Strict);

            context.Setup(m => m.RequestServices.GetService(typeof(IOptions <RouteOptions>)))
            .Returns(optionsAccessor.Object);
            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
            .Returns(NullLoggerFactory.Instance);

            return(new VirtualPathContext(
                       context.Object,
                       ambientValues: null,
                       values: values,
                       routeName: routeName));
        }
예제 #13
0
        private static RouteContext CreateRouteContext(
            string requestPath,
            ILoggerFactory loggerFactory = null,
            RouteOptions options = null)
        {
            if (loggerFactory == null)
            {
                loggerFactory = NullLoggerFactory.Instance;
            }

            if (options == null)
            {
                options = new RouteOptions();
            }

            var request = new Mock<HttpRequest>(MockBehavior.Strict);
            request.SetupGet(r => r.Path).Returns(new PathString(requestPath));

            var optionsAccessor = new Mock<IOptions<RouteOptions>>(MockBehavior.Strict);
            optionsAccessor.SetupGet(o => o.Value).Returns(options);

            var context = new Mock<HttpContext>(MockBehavior.Strict);
            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
                .Returns(loggerFactory);
            context.Setup(m => m.RequestServices.GetService(typeof(IOptions<RouteOptions>)))
                .Returns(optionsAccessor.Object);
            context.SetupGet(c => c.Request).Returns(request.Object);

            return new RouteContext(context.Object);
        }
예제 #14
0
        private static VirtualPathContext CreateVirtualPathContext(
            RouteValueDictionary values,
            RouteOptions options = null,
            string routeName = null)
        {
            var optionsAccessor = new Mock<IOptions<RouteOptions>>(MockBehavior.Strict);
            optionsAccessor.SetupGet(o => o.Value).Returns(options);

            var context = new Mock<HttpContext>(MockBehavior.Strict);
            context.Setup(m => m.RequestServices.GetService(typeof(IOptions<RouteOptions>)))
                .Returns(optionsAccessor.Object);
            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
                .Returns(NullLoggerFactory.Instance);

            return new VirtualPathContext(
                context.Object,
                ambientValues: null,
                values: values,
                routeName: routeName);
        }
예제 #15
0
        public void GetVirtualPath_BestEffort_FirstValidatedValuesWins_Nested()
        {
            // Arrange
            var route1 = CreateRoute(accept: false, match: true, matchValue: "bad");
            var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
            var route3 = CreateRoute(accept: true, match: true, matchValue: "best");

            var routeCollection = new RouteCollection();
            routeCollection.Add(route1.Object);

            var innerRouteCollection = new RouteCollection();
            innerRouteCollection.Add(route2.Object);
            innerRouteCollection.Add(route3.Object);
            routeCollection.Add(innerRouteCollection);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext(options: options);

            // Act
            var pathData = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Equal(new PathString("/best"), pathData.VirtualPath);
            Assert.Same(route3.Object, pathData.Router);
            Assert.Empty(pathData.DataTokens);

            // All of these should be called
            route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
            route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
            route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
        }
예제 #16
0
        public void GetVirtualPath_NoBestEffort_NoMatch()
        {
            // Arrange
            var route1 = CreateRoute(accept: false, match: true, matchValue: "best");
            var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
            var route3 = CreateRoute(accept: false, match: true, matchValue: "bad");

            var routeCollection = new RouteCollection();
            routeCollection.Add(route1.Object);
            routeCollection.Add(route2.Object);
            routeCollection.Add(route3.Object);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = false,
            };

            var virtualPathContext = CreateVirtualPathContext(options: options);

            // Act
            var path = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Null(path);

            // All of these should be called
            route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
            route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
            route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
        }
예제 #17
0
        public void GetVirtualPath_NamedRoute_BestEffort_FirstRouteWins()
        {
            // Arrange
            var bestMatch = CreateNamedRoute("Match", accept: false, matchValue: "best");
            var noMatch = CreateNamedRoute("NoMatch", accept: false, matchValue: "bad");

            var routeCollection = new RouteCollection();
            routeCollection.Add(noMatch);

            var innerRouteCollection = new RouteCollection();
            innerRouteCollection.Add(bestMatch);
            routeCollection.Add(innerRouteCollection);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext("Match", options: options);

            // Act
            var pathData = routeCollection.GetVirtualPath(virtualPathContext);

            Assert.Equal(new PathString("/best"), pathData.VirtualPath);
            var namedRouter = Assert.IsAssignableFrom<INamedRouter>(pathData.Router);
            Assert.Equal("Match", namedRouter.Name);
            Assert.Empty(pathData.DataTokens);
        }
예제 #18
0
        public void GetVirtualPath_AmbiguousRoutes_RequiresRouteValueValidation_Error()
        {
            // Arrange
            var namedRoute = CreateNamedRoute("Ambiguous", accept: false);

            var routeCollection = new RouteCollection();
            routeCollection.Add(namedRoute);

            var innerRouteCollection = new RouteCollection();
            innerRouteCollection.Add(namedRoute);
            routeCollection.Add(innerRouteCollection);

            var options = new RouteOptions()
            {
                UseBestEffortLinkGeneration = true,
            };

            var virtualPathContext = CreateVirtualPathContext("Ambiguous", options: options);

            // Act & Assert
            var ex = Assert.Throws<InvalidOperationException>(() => routeCollection.GetVirtualPath(virtualPathContext));
            Assert.Equal("The supplied route name 'Ambiguous' is ambiguous and matched more than one route.", ex.Message);
        }
예제 #19
0
        private static ServiceCollection GetServiceCollection()
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddInstance<ILoggerFactory>(new NullLoggerFactory());

            var routeOptions = new RouteOptions();
            var accessor = new Mock<IOptions<RouteOptions>>();
            accessor
                .SetupGet(options => options.Value)
                .Returns(routeOptions);

            serviceCollection.AddInstance<IOptions<RouteOptions>>(accessor.Object);

            serviceCollection.AddInstance<IInlineConstraintResolver>(
                new DefaultInlineConstraintResolver(accessor.Object));

            return serviceCollection;
        }
예제 #20
0
 private void EnsureOptions(HttpContext context)
 {
     if (_options == null)
     {
         _options = context.RequestServices.GetRequiredService<IOptions<RouteOptions>>().Value;
     }
 }
예제 #21
0
        private static RouteOptions GetRouteOptions(
            bool lowerCaseUrls = false,
            bool useBestEffortLinkGeneration = true,
            bool appendTrailingSlash = false)
        {
            var routeOptions = new RouteOptions();
            routeOptions.LowercaseUrls = lowerCaseUrls;
            routeOptions.UseBestEffortLinkGeneration = useBestEffortLinkGeneration;
            routeOptions.AppendTrailingSlash = appendTrailingSlash;

            return routeOptions;
        }
 // $Start-RedirectToCanonicalUrl$
 /// <summary>
 /// Adds filters which help improve search engine optimization (SEO).
 /// </summary>
 private static void ConfigureSearchEngineOptimizationFilters(ICollection<IFilterMetadata> filters, RouteOptions routeOptions)
 {
     filters.Add(new RedirectToCanonicalUrlAttribute(
          appendTrailingSlash: routeOptions.AppendTrailingSlash,
          lowercaseUrls: routeOptions.LowercaseUrls));
 }
예제 #23
0
        private static DefaultInlineConstraintResolver CreateConstraintResolver()
        {
            var services = Mock.Of<IServiceProvider>();

            var options = new RouteOptions();
            var optionsMock = new Mock<IOptionsAccessor<RouteOptions>>();
            optionsMock.SetupGet(o => o.Options).Returns(options);

            return new DefaultInlineConstraintResolver(services, optionsMock.Object);
        }
예제 #24
0
        private static DefaultInlineConstraintResolver CreateConstraintResolver()
        {
            var options = new RouteOptions();
            var optionsMock = new Mock<IOptions<RouteOptions>>();
            optionsMock.SetupGet(o => o.Value).Returns(options);

            return new DefaultInlineConstraintResolver(optionsMock.Object);
        }
예제 #25
0
        private static VirtualPathContext CreateVirtualPathContext(
            string routeName = null,
            ILoggerFactory loggerFactory = null,
            RouteOptions options = null)
        {
            if (loggerFactory == null)
            {
                loggerFactory = NullLoggerFactory.Instance;
            }

            if (options == null)
            {
                options = new RouteOptions();
            }


            var request = new Mock<HttpRequest>(MockBehavior.Strict);

            var optionsAccessor = new Mock<IOptions<RouteOptions>>(MockBehavior.Strict);
            optionsAccessor.SetupGet(o => o.Options).Returns(options);

            var context = new Mock<HttpContext>(MockBehavior.Strict);
            context.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
                .Returns(loggerFactory);
            context.Setup(m => m.RequestServices.GetService(typeof(IOptions<RouteOptions>)))
                .Returns(optionsAccessor.Object);
            context.SetupGet(c => c.Request).Returns(request.Object);

            return new VirtualPathContext(context.Object, null, null, routeName);
        }