系列目录

请求是如何进入MVC框架的(inbound)

当一个URL请求到来时,系统调用一个注册的IHttpModulesUrlRoutingModule它将完成如下工作

一、在RouteTable.Route中从第一个Route开始查找第一个匹配当前URL的Route。需要同时满足下面的条件,才能算匹配:

1.URL匹配Route属性中Url的模型;

2.所有{}中定义的参数都可以在请求的URL中找到对应,或者参数在Route的Defaults中也有定义,当然Defaults中定义优先级低于URL中的定义,亦或者参数被设置成UrlParameter.Optional

3.参数满足Route的Constraints定义的匹配规则,规则可能是一个正则式,或是一个IRouteConstraint对象。

二、指定匹配的RouteBase将通过GetRouteData方法提供一个RouteData结构,RouteData包含如下四个属性:

1.Route:Route对象自己;

2.RouteHandler:一个实现了IRouteHandler的对象,MVC提供一个MvcRouteHandler类,从MapRoute的源码可以看出,总由MvcRouteHandler担任这个角色。MvcRouteHandler知道如何从RouteData中寻找Controller和Action。事实上MvcRouteHandler会寻找键值为"controller"和"action"参数,所以我们永远需要包含"controller"和"action"两个参数;

3.Values:保存URL中参数的值字典,参数包括{}定义的,Route.Defaults中的,以及从QueryString中获得的;

4.DataTokens:一个附加的字典,主要用于Areas机制,以后会详细讨论。

注:如果GetRouteData返回null的话,就无法进入MVC框架,常见的情况是有直接的静态物理文件能够匹配这个url,通常是一些资源文件,如css,image等文件。可以通过设置RouteCollection的RouteExistingFilestrue,使得用于不匹配静态文件(注意true是不匹配,这个命名和奇怪)。下面的代码是GetRouteData中的代码段,说明了这一机制是如何实现的。

1
2
3
4
5
6
7
8
if (!this.RouteExistingFiles)
{
    string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
    if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
    {
        return null;
    }
}

三、调用RouteData中的RouteHandler,同时为RouteHandler提供包括RouteDataHttpContextBase对象等上下文变量,并封装成一个叫requestContext的参数传递给RouteHandler。如果使用MvcRouteHandler,那么至此,就进入了MVC框架

几点注意点:

1.由于上面提到的UrlRoutingModule的搜索行为,Route在RouteCollection中添加的顺序就十分重要了。记住:优先添加形式特殊的Route

2.MvcRouteHandler在调用Controller的Action的时候会自动为Action提供 参数。参数来源于RouteData的键值对,MvcRouteHandler会自动将键名和Action的参数名比较,这种比较是大小写敏感的,所以在 Action中写参数名的时候要注意了,关于这点以后会详细展开;

3.如果希望URL中的参数是可选的,要设置参数为UrlParameter.Optional。

自定义参数匹配规则

Route的Constraints定义URL中参数匹配规则,规则可能是一个正则式,或是一个IRouteConstraint对象。 熟悉的情况是,通过MapRoute的简化API设置Constraints为一个正则式。但如果我们的匹配规则较复杂呢?事实上,我们可以自己实现一个 IRouteConstraint对象,IRouteConstraint只有一个Match方法,所以并不困难。我之前一篇文章ASP.NET MVC的全球化方案中有一个IRouteConstraint的实现。

还有个例子,MVC框架有个HttpMethodConstraint实现了IRouteConstraint,我们可以像下面这样使用:

1
2
3
4
routes.MapRoute(null, "Articles/{id}",
 new { controller = "Articles", action = "Show" },
 new { httpMethod = new HttpMethodConstraint("GET") }
 );

这表示只有以GET方式请求的URL才能匹配这个Route。需要注意的是,我们常常会在Action上加上[HttpGet]或 [HttpPost]来做类似的限定,但两者完全不同,这里的限定是在MVC框架外的,而[HttpGet]是在框架内的,显然这种方法高效些。

劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/11/02/details-asp-net-mvc-02.html

深入理解ASP.NET MVC(2)的更多相关文章

  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. iframe刷新父页面

    iframe页面是内嵌到父页面的,当点击iframe页面的服务器控件时,默认只刷新iframe页面,父页面是不会刷新的.若想刷新父页面,可以使用js来实现,如 1. parent.location.r ...

  2. Eclipse重命名项目名后如何彻底修改工程名

    背景:在Eclipse中当我们修改了一个Web项目名称后,在再次运行该项目,发现使用新的名称无法正常的浏览,而用旧的名称去可以 解决方案: 1:修改该项目目录下:.project文件 <?xml ...

  3. 让个人域名下GithubPage完美支持https

    让个人域名下GithubPage完美支持https 欢迎访问完美HTTPS支持的GithubPage个人博客 : https://zggdczfr.cn/ 前言 最近笔记本挂了送去维修,耽误了我的学习 ...

  4. PHP:第二章——PHP中的equire与incude语句

    <?php header("Content-Type:text/html;charset=utf-8"); /* include: include_once//include ...

  5. React教程-组件

    在React中创建一个组件非常简单(React组件有2种,一个非状态组件,一个有状态组件) 首先我们来看看ES6里面如何写构造函数 class App{ constructor(){ } event( ...

  6. 网络协议栈学习(二)创建 socket

    下面通过学习linux 1.2.13源码进一步理解socket通信机制.对该版本源码的学习主要参考<Linux内核网络栈源代码情景分析>(曹桂平 编著). 要理解socket的本质,就要理 ...

  7. 微软IE团队发布《逃离XP》浏览器小游戏

    微软IE团队今天发布了一个有趣的小游戏<逃离Windows XP>,这款游戏可以工作在所有现代浏览器下,简单的街机风格可以让你尽情对XP施展破坏欲.微软发布XP及提供支持服务已经史无前例地 ...

  8. 框架流程图绘制工具OmniGraffle 7 for Mac

    1.官网下载地址 https://www.omnigroup.com/omnigraffle 2.激活方法 Omnigraffle Pro 7注册码/许可证 名字:Appked 序列号:MFWG-GH ...

  9. MAC OS下使用OpenSSL生成私钥和公钥的方法

    MAC OS自带了OpenSSL,所以不用去编译那一坨跟SHIT一样的源码.直接在命令行里使用OPENSSL就可以. 打开命令行工具,然后输入 openssl打开openssl,接着只要三句命令就可以 ...

  10. 修改类不重启tomcat 自动加载项目

    可以修改类不用重启Tomcat加载整个项目(手工启动)     配置reloadable=true(自动重载)     使用Debug模式,前提是仅限于局部修改.(修改类不用重启--热加载) Tomc ...