系列目录

URL是如何通过路由表生成的(outbound)

通常我们被推荐在view设计时使用Html.ActionLink(…)产生链接,这样做的优势就是,url可以根据路由表生成。路由机制的另一个职责便是根据路由表生成url,而不是由我们手动编写。接下来深入分析一下其原理。

类似Html.ActionLink的方法,最终都将通过查询路由表来生成url,跟inbound一样,路由表总是按顺序被依次遍历,直到匹配。每个RouteGetVirtualPath方法负责审查,该方法接受一个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)的更多相关文章

  1. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  2. [转载]深入理解ASP.NET MVC之ActionResult

    Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...

  3. 深入理解ASP.NET MVC Day1

    深入理解ASP.NET MVC   ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...

  4. 七天学会ASP.NET MVC ——深入理解ASP.NET MVC

    七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC   系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...

  5. 深入理解ASP.NET MVC(6)

    系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...

  6. 深入理解ASP.NET MVC(5)

    系列目录 回顾 系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分.第2节中提到MvcRout ...

  7. 深入理解ASP.NET MVC(目录)

    学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...

  8. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...

  9. [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC

    个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...

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

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

随机推荐

  1. shell开源跳板机sshstack

    笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 源码地址: https://github.com/sshstack/sshstack 为什么要写shell跳板机? ...

  2. 重启uwsgi脚本备份

    NAME="identifyImg_uwsgi.init" if [ ! -n "$NAME" ];then echo "no arguments&q ...

  3. 微软Power BI 每月功能更新系列——12月Power BI 新功能学习

    Power BI Desktop12月产品功能摘要 Power BI 作为实力宠粉达人每月更新不来点新花样,怎么对得起翘首期待的实力铁粉您嘞!一起来看看这一次的Power BI版本的更新又给我们带来了 ...

  4. ajax跨域(No 'Access-Control-Allow-Origin' header is present on the requested resource)

    问题 在某域名下使用Ajax向另一个域名下的页面请求数据,会遇到跨域问题.另一个域名必须在response中添加 Access-Control-Allow-Origin 的header,才能让前者成功 ...

  5. Linux关闭透明大页配置

      一.为何要关闭透明大页 A--MOS获取 . #翻译 由于透明超大页面已知会导致意外的节点重新启动并导致RAC出现性能问题,因此Oracle强烈建议禁用透明超大页面. 另外,即使在单实例数据库环境 ...

  6. centos6安装opencv2

    环境 centos6.5 opencv2.4 python2.6(centos自带的) 下载 opencv可从GitHub下载https://github.com/opencv/opencv/tree ...

  7. C++学习(十七)(C语言部分)之 指针

    复习 数组定义格式 类型 数组名[数组大小]数组名+下标 int arr[2][3]={{1,2,3},{4,5,6}}; int arr[][3]={1,2,3,4,5,6};//二维数组定义的时候 ...

  8. 实验吧—隐写术——WP之 Fair-Play

    首先,我们读题发现题目是Playfair​,其实我也不知道这是什么,那么就百度一下啊 Playfair解密算法: 首先将密钥填写在一个5*5的矩阵中(去Q留Z),矩阵中其它未用到的字母按顺序填在矩阵剩 ...

  9. 普林斯顿数学指南(第二卷) (Timothy Gowers 著)

    第IV部分 数学的各个分支 IV.1 代数数 IV.2 解析数论 IV.3 计算数论 IV.4 代数几何 IV.5 算术几何 IV.6 代数拓扑 IV.7 微分拓扑 IV.8 模空间 IV.9 表示理 ...

  10. kettle的资源库创建及修改密码

    在kettle中的转换或者作业等资源的存储的仓库称为资源库:分为文件资源库.数据库资源库. 一个转换或者作业可以属于某个资源库或者一个单独的文件形态存在. 一.数据库资源库 1.1在mysql中创建一 ...