系列目录

请求是如何进入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. axis2的WebService无法注入Service层类

    package com.vrv.paw.axiswebservices; import org.springframework.web.context.ContextLoader; import or ...

  2. synchronized锁普通方法和锁静态方法

    1.对象锁钥匙只能有一把才能互斥,才能保证共享变量的唯一性 2.在静态方法上的锁,和 实例方法上的锁,默认不是同样的,如果同步需要制定两把锁一样. 3.关于同一个类的方法上的锁,来自于调用该方法的对象 ...

  3. linux和window是文件挂载

    1. 首先在windows下面创建share文件夹并设置共享(右键->属性->共享)2. 确认ubuntu安装了mount.cifs,apt-get install mount.cifs ...

  4. kill prefix meta,milli,kilo input

    1● meta 超过,改变   2● milli 1/1000   3● kilo 1000      

  5. laravel 连接同一服务器上多个数据库操作 、 连接多个不同服务器上的不同数据库操作以及多个数据库操作的事务处理

    !注意:标红的要注意区分开 第一步.配置.env文件(同一服务器上多个数据库) DB_CONNECTION=pgsqlDB_HOST=IP(例如:127.0.0.1)DB_PORT=端口号(例如:54 ...

  6. docker 部署 flask(一)配置环境及测试

    简介: flask也是要部署的.不能老在我们的pycharm里面跑测试服务器. 各种配置linux,我看就算了吧.我们用docker部署. 也就两三行命令. 一:选择基础镜像 GitHub repo: ...

  7. Django(四)模板文件中的循环

    编辑views.py from django.shortcuts import render from django.shortcuts import HttpResponse #此行增加 # Cre ...

  8. The "Double-Checked Locking is Broken" Declaration

    双重检查锁定在延迟初始化的单例模式中见得比较多(单例模式实现方式很多,这里为说明双重检查锁定问题,只选取这一种方式),先来看一个版本: public class Singleton { private ...

  9. python学习:变量与字符串

    counter = # 赋值整型变量 miles = 1000.0 # 浮点型 name = "John" # 字符串 print counter print miles prin ...

  10. vs2010将写好的软件打包安装包经验

    (1) 用VS2010打开已经编写好准备做安装包的软件程序,右击解决方案,添加新建项目. (2) 在“新建项目”对话框中,选择“其他项目类型”,再选择“安装和部署”,然后在模板中选择“安装项目” (3 ...