asp.net MVC 的URL路由是一个非常强大的功能,而且有个优点:强大单不复杂。然而,目前我在网上看到的相关资料,却都仅仅提供一些示例,仅通过这些示例,初学者基本上不可能明白为什么要这么配置,更不用说灵活运用了。
这篇文章将采取循序渐进的方式,来解释MVC URL路由的配置方法,使初学者能够完全掌握MVC URL路由的配置方法。
阅读本文的用户必须有如下基础:
1、熟悉C#;
2、能够通过Visual Studio建立asp.net MVC项目;
3、能够在MVC项目中创建Model、Controller、Action和View。
4、对url的结构有明确的认识。

基于上述几点,本文的读者应该是熟悉Asp.net web开发的MVC初学者。如果阅读中发现有理解困难的地方,请自行补充上述知识。

本文使用Asp.net MVC4作为示例。
一、默认路由
项目的默认路由如下:
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
这条路由实际上是使用命名参数的方式调用routes这个对象的MapRoute方法。上述的代码也可以这么写:
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
这个方法有三个参数:name、url和defaults。
name这个参数表示本条路由信息的名称,必须为唯一,如果有重复,则网站启动时会出现以下错误:

图片1:路由名称重复

URL表示本条路由信息的URL模板。这里引入一个术语:URL模板。

"{controller}/{action}/{id}"这个URL模板表示url由三部分组成:controller、action和id,每一部分之间用斜杠(/)分割。对于一个形如:

http://www.xxx.com/aaa/bbb/cc 的url,aaa就表示controller,bbb就表示action,cc就表示id。如果有一个名为aaa的Controller,这个Controller中有一个名为bbb的Action,这个Action接收一个名为id的参数,那么当我们访问:

http://www.xxx.com/aaa/bbb/cc 这个url时,MVC就会调用aaaController中的bbb方法,并把cc作为参数id的值传递进去。
defaults表示如果模板中的某个项目缺失,则用指定的值来设置这个项的值。
例如:如果我们访问的URL如下:
http://www.xxx.com/aaa/bbb
也就是没有参数id,那么bbb这个方法的参数id就会用defaults中的值代替,这里一般为null。如果bbb的这个参数是值类型,那么就会报错:

图片:参数不能为null

为了防止这种情况,有以下两种处理方法:
1、路由中为值类型的参数设置默认值,而不是使用UrlParameter.Optional;
2、在action的定义中避免使用值类型的数据,如果必须使用,则使用此值类型的Nullable泛型。

如果我们访问的URL如下:
http://www.xxx.com/aaa
也就是同时没有了action和id,那么这两个项目都会用defaults中的值代替,也就是会访问aaaController中的Index方法,并传递一个null的id。
同理,如果仅仅输入域名,那么就会访问HomeController中的Index方法,并传递一个null的id。

下面对默认路由进行一点点改动,改动后如下:
    routes.MapRoute(
        name: "Default",
        url: "{action}/{controller}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
问题一:请写出访问如下URL时,访问了哪个controller的哪个action,传递了什么参数。
1、http://www.xxx.com/aaa/bbb/cc
2、http://www.xxx.com/aaa/bbb
3、http://www.xxx.com/aaa
4、http://www.xxx.com
答案在本文最后。

简单总结一下:
当用户输入的URL和某条路由规则中的url模式匹配时,根据这个url模式在输入的URL中查找url模式中的项目,如果查找不到,则用默认值代替。

二、参数传递
1、基本类型的参数传递。
如果在aaaController中有一个叫做ddd的action,方法定义如下:
public ActionResult ddd(string dParam)
这个action并不接收参数id,而是接收一个叫做dParam的string型参数。如果要访问这个action,则url应该如下:
http://www.xxx.com/aaa/ddd?dParam=xxx
这样,ddd这个action中的dParam参数的值就会被设置为字符串xxx。
如果我们访问的url如下

如果我们访问的url如下:
http://www.xxx.com/aaa/ddd?dParam=xxx&cParam=yyy
这里url中多了一个名为cParam的值,但是ddd这个action的定义中并不包含这个参数,那么路由系统就会把cParam这个参数忽略。

再看一个url:
http://www.xxx.com/aaa/ddd
这个url后面没有带任何参数,那么ddd这个action中所需的参数dParam就会被设置为null。

2、对象类的参数传递。
再看一种情况。如果在aaaController中有一个叫做ObjectParam的action,方法定义如下:
public ActionResult ObjectParam(ObjectModel objModel)
ObjectModel的定义如下

public class ObjectModel
    {
        int ObjParamInt { get; set; }

string ObjParamString { get; set; }
    }

如果我们访问如下url:
http://www.xxx.com/aaa/ObjectParam?ObjParamInt=10&ObjParamString=xxx
那么,在ObjectParam这个方法中,参数objModel中对应属性的值就会被设定为url中对应的值。但是如果url中的值类型和对象中的对应字段的类型不一致,则会忽略url中的值。
例如,如果我们访问如下url:
http://www.xxx.com/aaa/ObjectParam?ObjParamInt=def&ObjParamString=xxx
那么参数objModel中ObjParamInt这个属性就不会被赋值,它的值就是int型数据的默认值:0。

另外,还要注意一点,url参数中的各个项目的大小写必须和对象中的一致。
 请回答下面问题:
问题二:在默认路由情况下,请写出访问如下URL时,参数的状态。
http://www.xxx.com/aaa/ObjectParam
答案在本文最后。

三、特殊路由
我们把默认路由修改为如下所示:
    routes.MapRoute(
        name: "Default",
        url: "{controller}-{action}-{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

也就是把默认路由中的斜杠“/”换成了减号“-”。先用如下URL测试:
http://www.xxx.com/aaa-bbb-ccc
这时就会访问aaaController中的bbb这个action,同时把ccc作为参数id的值传递进去。
还记的第一部分的总结吗:当用户输入的URL和某条路由规则中的url模式匹配时,根据这个url模式在输入的URL中查找url模式中的项目,如果查找不到,则用默认值代替。
我们试验一下修改后的路由如果在url中省略某个参数会是什么情况:
http://www.xxx.com/aaa-bbb
访问后出现如下错误:


图片3:找不到文件

同样,如果用以下URL,也找不到aaaController中的Index方法:
http://www.xxx.com/aaa
也会出现上述错误。
出现这个错误的原因是,在默认路由中,各项目之间的分割符是斜杠“/”,而修改后的路由中,分割符是减号“-”。但是在MVC的路由系统中,只认为斜杠是分隔符,其他任何字符都仅仅作为模式字符串。当我们用这两个URL

访问的时候,路由系统认为找不到合适的路由模式,所以就把这个URL作为一个静态请求传递出去,当然这个路径是不存在的。这里“合适的路由模式”应该是三个字符串用减号连接,而且三个字符串中的任意一个都不能为空。

所以如果我们设计的路由没有用斜杠作为分隔符,那么URL模式中项目就无法使用defaults中的默认值。

四、进阶版
先把我总结出来的URL模板规则写出来:
1、花括号对“{}”之间的字符串为路由项目;
2、斜杠“/”为分隔符;
3、其它任何字符都是固定字符,必须在固定的位置出现。
先用这三条来验证默认的路由:
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
可以看到,默认路由中有三个被花括号包裹起来的项目,他们是:controller、action和id
这三项之间用斜杠分割。

再验证一下修改后的路由:
    routes.MapRoute(
        name: "Default",
        url: "{controller}-{action}-{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
这条路由中有三个被花括号包裹起来的项目,他们是:controller、action和id,他们之间各有一个固定字符减号“-”。
那么既然花括号中的字符串都为路由项目,那么,controller和action这两个项目和其他项目相比就没有任何特殊之处,也就意味着,这两个项目也不是必须的。那么我们可以这么定义一条路由规则:
    routes.MapRoute(
        name: "AboutUs",
        url: "AboutUs.html",
        defaults: new { controller = "Home", action = "AboutUs" }
    );
这条路由意味着如果用户访问AboutUs.html这个文件,将执行HomeController中的AboutUs这个action。
看到了吗?这就是利用url路由实现的伪静态。
问题三:假设我们NewsCenterController中有一个NewsDetail的action,这个action定定义如下:
public ActionResult NewsDetail(long newsID)
请试着定义一条路由规则,实现用如下url访问NewsDetail这个action:
http://www.xxx.com/NewsContent_100.html
其中数字100是newsID。
答案在本文最后。

五、路由顺序
在MVC的路由系统中,可以定义多条路由规则,多条路由规则的name属性,如下:

routes.MapRoute(
        name: "AboutUs",
        url: "AboutUs.html",
        defaults: new { controller = "Home", action = "AboutUs" }
    );

routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

当MVC的路由系统接收到一个url时,路由系统就会按照书写的顺序,对每一条路由规则中的路由模式进行匹配,只要发现某一条路由规则中的模式符合当前url时,就使用这条路由规则来处理当前url,后面的路由规则在此次处

理中就会忽略。
假设我们的路由规则中有如下两条:

routes.MapRoute(
        name: "Default1",
        url: "{action}/{controller}/{id}",
        defaults: new { controller = "Home", action = "AboutUs" }
    );

routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
那么,后面一条路由无论何时都不会被使用。

问题答案:
问题一:
这个问题的路由配置如下:
    routes.MapRoute(
        name: "Default",
        url: "{action}/{controller}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
由于这个问题的路由配置中,路由模式为:{action}/{controller}/{id},所以第一个项目是action,第二个项目为controller,第三个项目为id,因此答案如下:
1、http://www.xxx.com/aaa/bbb/cc  访问了bbbController的aaa这个action,传递给参数id的值为cc
2、http://www.xxx.com/aaa/bbb 访问了bbbController的aaa这个action,传递给参数id的值为null
3、http://www.xxx.com/aaa 访问了bbbController的Index这个action,传递给参数id的值为null
4、http://www.xxx.com 访问了HomeController的Index这个action,传递给参数id的值为null

问题二:
这个问题使用的url如下:
http://www.xxx.com/aaa/ObjectParam
这个url访问了aaaController的ObjectParam这个action,但是没有传递任何参数,所以ObjectParam参数中ObjectModel这个对象的值均为默认值,即:
ObjParamInt = 0
ObjParamString = null

问题三:
路由应该如下配置:
    routes.MapRoute(
        name: "NewsContents",
        url: "NewsContent_{newsID}.html",
        defaults: new { controller = "NewsCenter", action = "NewsDetail", newsID = 0 }

asp.net MVC URL路由入门指南的更多相关文章

  1. ASP.NET MVC——URL路由

    在MVC之前,ASP.NET假设请求的URL与服务器上的文件之间有关联,服务器接受请求,并输出相应的文件.而在引入MVC后,请求是由控制器的动作方法来处理的.为了处理URL,便引入了路由系统. 首先我 ...

  2. Asp.Net MVC2.0 Url 路由入门---实例篇

    本篇主要讲述Routing组件的作用,以及举几个实例来学习Asp.Net MVC2.0 Url路由技术. 接着上一篇开始讲,我们在Global.asax中注册一条路由后,我们的请求是怎么转到相应的Vi ...

  3. ASP.NET MVC URL重写与优化(1)-使用Global路由表定制URL

    ASP.NET MVC URL重写与优化(1)-使用Global路由表定制URL 引言--- 在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流量. ...

  4. ASP.NET MVC 自定义路由中几个需要注意的小细节

    本文主要记录在ASP.NET MVC自定义路由时,一个需要注意的参数设置小细节. 举例来说,就是在访问 http://localhost/Home/About/arg1/arg2/arg3 这样的自定 ...

  5. 理解ASP.NET MVC的路由系统

    引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...

  6. ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase

    原文地址:http://www.51csharp.com/MVC/882.html   ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL 引言-- 在初级篇中,我们 ...

  7. 返璞归真 asp.net mvc (2) - 路由(System.Web.Routing)

    原文:返璞归真 asp.net mvc (2) - 路由(System.Web.Routing) [索引页] [源码下载] 返璞归真 asp.net mvc (2) - 路由(System.Web.R ...

  8. ASP.NET MVC URL重写与优化(初级篇)-使用Global路由表定制URL

    ASP.NET MVC URL重写与优化(初级篇)-使用Global路由表定制URL 引言--- 在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流 ...

  9. ASP.NET SignalR 2.0入门指南

    ASP.NET SignalR 2.0入门指南 介绍SignalR ASP.NET SignalR 是一个为 ASP.NET 开发人员的库,简化了将实时 web 功能添加到应用程序的过程.实时Web功 ...

随机推荐

  1. IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

    进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispa ...

  2. 通过dbcc page来查看表中的数据

    --1.先建表 CREATE TABLE test(idd INT NOT NULL,name VARCHAR(10) NULL) INSERT INTO TEST SELECT 1,'abcdefg ...

  3. ASP .Net提交时禁用Button

    转自:http://gaterking.blog.51cto.com/69893/301691/ 今天遇到一种小情况,想要在.net的服务器控件asp:button按下去时通过OnClientClic ...

  4. 用EPOLL进行压力测试

    在以前的博客中提到的一个服务端,在以前压力测试的过程中,发现单核CPU最多能达到1000TPS 还以为是服务端性能不够好,所以一直想着怎么去优化它. 但优化的思路明显不多,所以就考虑换一种压力测试的方 ...

  5. Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数

    条款17 在operator=中检查给自己赋值的情况 1 2 3 class  X { ... }; X a; a = a;  // a 赋值给自己 >赋值给自己make no sense, 但 ...

  6. IOS 图片阴影,圆角等处理

    一直以来,为IOS添加图片的特殊效果都是通过跟美工的配合,比如,要加阴影,就从美工那边获得一张阴影效果图,在界面上画两个UIImageView,将阴影放在下面,图像放上上面,错开一定角度.有比如想做圆 ...

  7. 新浪旗下的SAE云服务入门

    前言: 云服务已经火热很多年了,到了现在已经基本进入稳定期,稍微有实力的公司都会推出免费的云存储,像百度的还几个T,速度也不错.如果不担心数据安全问题,代替平时的U盘还是没有问题.而SAE是新浪在20 ...

  8. [Effective C++ --012]复制对象时勿忘其每一个成分

    引言: 在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成. A(const A& r); // 形式有多种,在这里只列出一个 因此,在值传递的应用场景里,我们可以 ...

  9. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) 上一篇主 ...

  10. git svn 5点区别

    如果你在读这篇文章,说明你跟大多数开发者一样对GIT感兴趣,如果你还没有机会来试一试GIT,我想现在你就要了解它了. GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等.如果 ...