深入理解ASP.NET MVC(3)
URL是如何通过路由表生成的(outbound)
通常我们被推荐在view设计时使用Html.ActionLink(…)产生链接,这样做的优势就是,url可以根据路由表生成。路由机制的另一个职责便是根据路由表生成url,而不是由我们手动编写。接下来深入分析一下其原理。
类似Html.ActionLink的方法,最终都将通过查询路由表来生成url,跟inbound一样,路由表总是按顺序被依次遍历,直到匹配。每个Route的GetVirtualPath方法负责审查,该方法接受一个RouteValueDictionary参数,该参数实际上就是由相应的Helper提供的。当以下三个条件成立时,认为匹配成功:
一、每个由大括号定义的参数必须能够找到对应的值。按照优先顺序这些值将有下面三种来源:
1.RouteValueDictionary参数明确提供的。也就是我们在调用某些有生成url功能的Helper时提供的,比如ActionLink方法;
2.*从当前请求的上下文的RouteData中;关于这点有更特殊的情况,下面将详细讨论;
3.Route的Defaults中。
二、如果每个Defaults集合中的参数与RouteValueDictionary参数中的值都符合,而且这些值没有在url pattern中用大括号定义,那么认为匹配。听起来有点拗口,下面举个例子.
假如有如下规则:
|
1
2
3
4
|
routes.MapRoute( null, "manage/orders/{page}", new { controller = "Admin", action = "OrderManage", page = UrlParameter.Optional }); |
页面有如下链接:
|
1
|
<a href="<%:Url.Action("OrderManage", "Admin") %>">Order</a> |
最后生成的链接将是这样的(这里省略了前面的domain):
|
1
|
<a href="…/manage/orders">Order</a> |
Defaults中有两个参数controller和action,在url的pattern中没有类似{controller}和{action},而且Url.Action的参数同时提供了与Defaults设置一致的参数值(这已经够了),于是这个url是匹配的。
三、每个参数都符合Constraints的匹配规则。
满足上面三个条件后,GetVirtualPath就会将相应的参数填入url中,并最终返回url的字符串。需要强调的一点是:MVC框架的这种行为工作在懒惰模式下,一旦“该要的要到了”,那么就停止继续遍历。这也从另一个角度说明了,把特殊的往前放的黄金原则。
举个例子:
下面是两个有顺序的Route:
|
1
2
3
4
5
6
7
8
9
10
|
routes.MapRoute( null, "manage/car", new { controller = "Admin", action = "Car" } );routes.MapRoute( null, "manage/car/{operation}", new { controller = "Admin", action = "Car" } ); |
有一个链接表示:
|
1
|
<%: Html.ActionLink("Add Car", "Car","Admin", new { operation = "add" }, null )%> |
最后的结果是什么呢?是manage/car/add吗?
其实最后的结果是manage/car,为什么呢?对于第一个Route,它期望的是controller和action这两个参数,而上面的 ActionLink的确完整的提供了这两个参数,而且与Defaults设置一致(这满足规则的第二条),于是匹配了!即使还提供了operation 参数,框架也不管了。显然这不是希望的。只要把两个Route的位置换一下即可。这个例子只是一个演示。
*关于上面条件一的第二小点,其实是个很棒的特性,这里补充一个例子:
假设当前页面的url是:/Catalog/List/Purple/123
|
1
|
routes.MapRoute(null, "{controller}/{action}/{color}/{page}"); |
|
1
|
<%: Html.ActionLink("Click me", "List", "Catalog", new {page=789}, null) %> |
这个link能匹配这个route吗?也许你认为我没有提供color参数啊,怎么能匹配呢?事实上,结果确出人意料的是:
|
1
|
<a href="/Catalog/List/Purple/789">Click me</a> |
因为当前页面是/Catalog/List/Purple/123,此时的RouteData保存了color参数值,尽管在ActionLink中没有显示设置color,但是仍然从当前的RouteData中找到了color参数。
再看一个例子:
当前页面的url还是:/Catalog/List/Purple/123
|
1
|
routes.MapRoute(null, "{controller}/{action}/{color}/{page}"); |
|
1
|
<%: Html.ActionLink("Click me", "List", "Catalog", new {color="Aqua"}, null) %> |
这个link还能匹配这个route吗?也许你认为根据上面的规则应该能,但结果却是无法匹配,为什么呢?因为有个原则,RouteData中的数据只能用于填充url pattern中“靠前的参数”,最后一个参数是不能的!
最后关于outbound还有一个原则,Defaults提供的值,会尽可能的不出现在最终的url结果中。
URL设计原则
在MVC框架下,我们可以对URL做完全的控制,自然就想到要设计出优良的url,URL究竟该如何设计。由于本人web开发经验很少,以下是书中的内容,我做了些概括:
1.url要尽量通俗易懂,不要把技术的东西包含在里面,比如下面这样的:
/Website_v2/CachedContentServer/FromCache/AnnualReport
/my%20great%20article(使用/my-great-article为好)
2.有意义的文本总比ID数字让人感觉舒服
3.不要在url中带有后缀名
4.要有比较强的层次感,又要简短易记,比如:/Products/Menswear/Shirts/Red
5.url要大小写不敏感,并且尽量使用小写字母,mvc框架是大小写不分的
6.不要因为url的变更而弃用老的url,要使用跳转的方式
7.对于只读的操作使用get方式,对于要修改服务器数据的请求使用post方式;url要方便人们保存书签或分享网页,因此,对于分页显示的情况,分页要体现在url中
8.QueryString要尽量少用。当参数是为了参与某种算法,而不是为了直接的资源指向时,可以使用QueryString,因为用户此时不愿意手动输入url。比如page参数
301和302
同样是使客户端浏览器跳转,301是暗示永久跳转,可以暗示搜索引擎这个url将永久不用,当确实需要更形url时考虑;
302表示临时跳转,MVC的RedirectToRouteResult和RedirectResult使用302。
可以像下面这样进行301跳转:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public static class PermanentRedirectionExtensions{ public static PermanentRedirectToRouteResult AsMovedPermanently (this RedirectToRouteResult redirection) { return new PermanentRedirectToRouteResult(redirection); } public class PermanentRedirectToRouteResult : ActionResult { public RedirectToRouteResult Redirection { get; private set; } public PermanentRedirectToRouteResult(RedirectToRouteResult redirection) { this.Redirection = redirection; } public override void ExecuteResult(ControllerContext context) { // After setting up a normal redirection, switch it to a 301 Redirection.ExecuteResult(context); context.HttpContext.Response.StatusCode = 301; } }} |
|
1
2
3
4
|
public ActionResult MyActionMethod(){ return RedirectToAction("AnotherAction").AsMovedPermanently();} |
关于SEO(search engine optimization)
提高排名的技巧:
1.url使用关键字而不是数字
2.url使用较少的QueryString,不要使用下划线
3.单一内容单一url,不要多个url指向相同的内容
4.如果要多个url指向相同的内容,使用301跳转
5.网页的内容要可被“寻址”,要使用get方式,内容不要过于依赖post方式,或者js,flash,silverlight等客户端技术。
劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/11/08/details-asp-net-mvc-03.html
深入理解ASP.NET MVC(3)的更多相关文章
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...
- [转载]深入理解ASP.NET MVC之ActionResult
Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...
- 深入理解ASP.NET MVC Day1
深入理解ASP.NET MVC ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...
- 七天学会ASP.NET MVC ——深入理解ASP.NET MVC
七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...
- 深入理解ASP.NET MVC(6)
系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...
- 深入理解ASP.NET MVC(5)
系列目录 回顾 系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分.第2节中提到MvcRout ...
- 深入理解ASP.NET MVC(目录)
学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...
- [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC
个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...
- 理解ASP.NET MVC的路由系统
引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...
随机推荐
- python 爬虫数据准换时间格式
timeStamp = 1381419600 dateArray = datetime.datetime.utcfromtimestamp(timeStamp) otherStyleTime = da ...
- Linux 下各个目录的作用及内容
在 Linux 下,我们看到的是文件夹(目录): 在早期的 UNIX 系统中,各个厂家各自定义了自己的 UNIX 系统文件目录,比较混乱.Linux 面世不久后,对文件目录进行了标准化,于1994年对 ...
- 中国网建提供的SMS短信发送
一个简单的发送短信的小demo 第一步: 兄弟们,首先你们去中国网建的官网去注册一个账户:网址http://sms.webchinese.cn/reg.shtml 第二步: 注册完成之后会有免费的测试 ...
- JavaScript中的内置对象-8--1.Array(数组)-Array构造函数; 数组的栈方法; 数组的转换方法; 数组的操作方法; 删除-插入-替换数组项; ECMAScript为数组实例添加的两个位置方法;
JavaScript内置对象-1Array(数组) 学习目标 1.掌握任何创建数组 2.掌握数值元素的读和写 3.掌握数组的length属性 如何创建数组 创建数组的基本方式有两种: 1.使用Arra ...
- Go unitest
待测试: // add.go package util func Add(a int, b int) int { return a + b} 使用gotests工具,自动生成测试用例框架: https ...
- pprof进行golang程序性能分析
一.导入包 import _ "net/http/pprof" 二.启动监控routine go func() { http.ListenAndServe("0.0.0. ...
- jsp-servlet(2)响应HTML文档-书籍管理系统
基础知识预备: 目标: 构建一个书籍管理系统,实现以下功能. 功能: 1 图书信息查询,(查) 2 书籍管理:添加书籍 3 书籍管理:修改书籍信息 4 书籍管理:删除书籍 一.预备工作 Book{ ...
- Java栈的简单实现
* 数据结构与算法Java实现 栈 * * @author 小明 * */ public class MyStack { private Node top;// 头指针 int size;// 长度 ...
- 九度OJ1049题-去特定字符(和1111题特别像)
题目1049:字符串去特定字符 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:11329 解决:5169 题目描述: 输入字符串s和字符c,要求去掉s中所有的c字符,并输出结果. 输入: ...
- Windows编程___创建窗口
创建Windows窗口不难,可以简要的概括为: 1,# 注册一个窗口类 填充WNDCLASS结构 书写窗口消息处理函数WinProc 2,# 创建一个窗口 填写基本的窗口信息 3,# 显示窗口 4,# ...