《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

时间: 2024-10-08 08:16:11

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

ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

首页 头条 文章 频道                         设计频道 Web前端 Python开发 Java技术 Android应用 iOS应用 资源 小组 相亲 频道 首页 头条 文章 小组 相亲 资源 设计 前端 Python Java 安卓 iOS 登录 注册 首页 最新文章 经典回顾 开发 Web前端 Python Android iOS Java C/C++ PHP .NET Ruby Go 设计 UI设计 网页设计 交互设计 用户体验 设计教程 设计职场 极客 IT技术

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎. Razor在减少代码冗余.增强代码可读性和Visual Studio智能感知方面,都有着突出的优势.Razor一经推出就深受广大ASP.Net开发者的喜爱. 1.2 Razor的语法 (1)Razor文件类型:Razor支持两种文件类型,分

ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归.所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然. 但是,如果手写Html标签效率又比较低,可重用度比较低.这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码: <input name="UserName&quo

ASP.Net MVC开发基础学习笔记(1):走向MVC模式

链接地址:http://blog.jobbole.com/84992/ 一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/blog/index.aspx的URL,那么我们的WebForm程序会到网站根目录下去寻找blog目录下的index.aspx文件,然后由index.aspx页面的CodeBehind文件(.CS文件)进行逻辑处理,其中或许也包括到

ASP.Net MVC开发基础学习笔记:一、走向MVC模式

一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/blog/index.aspx的URL,那么我们的WebForm程序会到网站根目录下去寻找blog目录下的index.aspx文件,然后由index.aspx页面的CodeBehind文件(.CS文件)进行逻辑处理,其中或许也包括到数据库去取出数据(其中的经过怎样的BLL到DAL这里就不谈了),然后再由

ASP.NET MVC Web API 学习笔记---第一个Web API程序

http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html 1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有

ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步

一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新的区域,可以让我们的项目不至于太复杂而导致管理混乱.有了区域后,每个模块的页面都放入相应的区域内进行管理很方便.例如:上图中有两个模块,一个是Admin模块,另一个是Product模块,所有关于这两个模块的控制器.Model以及视图都放入各自的模块内.可以从上图中看出,区域的功能类似一个小的MVC项

【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序

1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有一定的区别:Web API服务是通过一般的 HTTP公开了,而不是通过更正式的服务合同 (如SOAP)  2. ASP.NET

ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法

一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归.所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然. 但是,如果手写Html标签效率又比较低,可重用度比较低.这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码: 1 <input name="UserName&q

【转载】ASP.NET MVC Web API 学习笔记---联系人增删改查

本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系人 说明:为了方便数据不使用真正的数据库,而是通过内存数据模拟 1.       Web API中包含的方法 Action HTTP method Relative URI GetAllContact GET /api/contact GetContact GET /api/contact /id