《ASP.NET MVC 4 实战》学习笔记 10:路由(下)

六、调试路由:

1.安装Route Debugger:

  在NuGet包管理器控制台输入:

install-package routedebugger

2.使用Route Debugger:
  一旦安装了Route Debugger对RouteDebugger.dll的引用便被添加到项目中,web.config也会添加一条新的应用程序设置:

<add key="RouteDebugger:Enabled" value="true" />

注:在部署应用程序之前要确保禁用了Route Debugger,即将RouteDebugger:Enabled设为false。

启动调试,进入ProductsByCategory页面,可以看到:

“Route Debugger”部分显示了与当前请求匹配的路由参数;“Data Tokens”部分显示了与该路由关联在一起的任意自定义数据标记;“All Routes”部分通过在“Matches CurrentRequest”列显示True表示哪些路由可能潜在地与当前请求匹配,该列为True的第一条路由是被选来处理当前请求的路由。

我们修改“ProductsByCategory”路由为:

            routes.MapPageRoute(
                "ProductsByCategory",
                "products/ByCategory/{category}",
                "~/ProductsByCategory.aspx",
                checkPhysicalUrlAccess: true,
                defaults: new RouteValueDictionary(new { category = "All" }));
            routes.MapRoute("404-catch-all", "{*catchall}", new { Controller = "Error", Action = "NotFound" });

然后访问/Products/ByCategory,会报错:

从图中我们可以看到有好几条与/Products/ByCategory地址匹配的路由,但匹配的第一条路由是“products”,用户被带到产品信息页而不是ProductsByCategory页。

3.使用路由约束:

上例中为了不让任何输入都与“products”路由的“productCode”片段匹配,我们可以用一个正则表达式来限制什么内容能与这一参数匹配:

            routes.MapRoute("product", "products/{productCode}/{action}",
                            new { controller = "Catalog", action = "Show" },
                            new { productCode="(?!ByCategory).*"});

此例我们使用正则表达式排除了字符串ByCategory。我们也可以使用自定义约束来代替正则表达式:

namespace RoutingSample
{
    public class NotEqualConstraint : IRouteConstraint
    {
        private string _input;

        public NotEqualConstraint(string input)
        {
            _input = input;
        }

        public bool Match(HttpContextBase httpContext, //HTTP上下文的引用
            Route route, //约束的路由
            string parameterName, //被约束的路由参数名
            RouteValueDictionary values, //当前路由值集合
            RouteDirection routeDirection //指明该路由是用来匹配输入请求还是用于生成URL
            )
        {
            object matchingValue;

            if (values.TryGetValue(parameterName, out matchingValue))
            {
                if (_input.Equals((string)matchingValue, StringComparison.OrdinalIgnoreCase))
                {
                    return false;
                }
            }

            return true;
        }
    }
}
            routes.MapRoute("product", "products/{productCode}/{action}",
                            new { controller = "Catalog", action = "Show" },
                            new {productCode=new NotEqualConstraint("ByCategory")});

七、测试路由行为:[我又晕了。。。]
1.测试入站路由:

1)测试路由的硬方式:
  首先引入NUnit:

install-package nunit -version 2.6.3

   添加测试:

namespace RoutingSample.Tests
{
    [TestFixture]
    public class NotUsingTestHelper
    {
        [Test]
        public void root_matches_home_controller_index_action()
        {
            const string url = "~/";
            // 建立模仿请求
            var request = MockRepository.GenerateStub<HttpRequestBase>();
            request.Stub(x => x.AppRelativeCurrentExecutionFilePath)
                .Return(url).Repeat.Any();

            request.Stub(x => x.PathInfo)
                .Return(string.Empty).Repeat.Any();

            var context = MockRepository
                .GenerateStub<HttpContextBase>();

            context.Stub(x => x.Request)
                .Return(request).Repeat.Any();
            // 注册路由
            RouteTable.Routes.Clear();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            
            var routeData = RouteTable.Routes.GetRouteData(context);// 获取用于请求的路由
            Assert.That(routeData.Values["controller"], Is.EqualTo("Home"));// 断言控制器正确
            Assert.That(routeData.Values["action"], Is.EqualTo("Index")); //断言动作正确
        }
    }
}

2)使用MvcContrib的路由测试扩展:
  首先安装MvcContrib.TestHelper程序集:

install-package mvccontrib.mvc3.testhelper-ci

  添加测试:

        [TestFixtureSetUp]
        public void FixtureSetup()
        {
            RouteTable.Routes.Clear();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        [Test]
        public void root_maps_to_home_index()
        {
            "~/".ShouldMapTo<HomeController>(x => x.Index());// 断言URL映射到动作
        }

3)测试示例路由:

namespace RoutingSample.Tests
{
    [TestFixture]
    public class UsingTestHelper
    {
        [TestFixtureSetUp]
        public void FixtureSetup()
        {
            RouteTable.Routes.Clear();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        [Test]
        public void root_maps_to_home_index()
        {
            "~/".ShouldMapTo<HomeController>(x => x.Index());// 断言URL映射到动作
        }

        [Test]
        public void privacy_should_map_to_home_privacy()
        {
            "~/privacy".ShouldMapTo<HomeController>(x => x.Privacy());
        }

        [Test]
        public void products_should_map_to_catalog_index()
        {
            "~/products".ShouldMapTo<CatalogController>(x => x.Index());
        }

        [Test]
        public void product_code_url()
        {
            "~/products/product-1".ShouldMapTo<CatalogController>(x => x.Show("product-1"));
        }

        [Test]
        public void product_buy_url()
        {
            "~/products/product-1/buy".ShouldMapTo<CatalogController>(x => x.Buy("product-1"));
        }

        [Test]
        public void basket_should_map_to_catalog_basket()
        {
            "~/basket".ShouldMapTo<CatalogController>(x => x.Basket());
        }

        [Test]
        public void checkout_should_map_to_catalog_checkout()
        {
            "~/checkout".ShouldMapTo<CatalogController>(x => x.CheckOut());
        }

        [Test]
        public void _404_should_map_to_error_notfound()
        {
            "~/404".ShouldMapTo<ErrorController>(x => x.NotFound());
        }

        [Test]
        public void ProductsByCategory_MapsToWebFormPage()
        {
            "~/Products/ByCategory".ShouldMapToPage("~/ProductsByCategory.aspx");
        }
    }
}

2.测试出站路由:

namespace RoutingSample.Tests
{
    [TestFixture]
    public class OutboundUrlTests
    {
        [TestFixtureSetUp]
        public void FixtureSetup()
        {
            RouteTable.Routes.Clear();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        [Test]
        public void Generate_home_url()
        {
            OutBoundUrl.Of<HomeController>(x => x.Index())
                .ShouldMapToUrl("/");
        }

        [Test]
        public void Generates_products_url()
        {
            OutBoundUrl.Of<CatalogController>(x => x.Show("my-product-code"))
                .ShouldMapToUrl("/products/my-product-code");
        }
    }
}

源码下载 密码:mh5o

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。