惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
C
Check Point Blog
博客园_首页
B
Blog
D
Docker
U
Unit 42
量子位
I
InfoQ
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
GbyAI
GbyAI
L
LangChain Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
美团技术团队
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
Vercel News
Vercel News
Recent Announcements
Recent Announcements
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Google DeepMind News
Google DeepMind News

博客园 - maledong

如何通过反射调用扩展方法? JQuery学习笔记——nt-child的使用 - maledong - 博客园 求最大公约数与最小公倍数的算法 ASP.NET专题研究——角色和Profile ASP.NET专题研究——用户登录、注册和发送密码 NET基本探究——事件 ASP.NET专题研究——登录权限 C#4.0和VS2010新特性(三) C#4.0和VS2010新特性(二) C#4.0和VS2010新特性(一) F# 快乐之旅(一)——F#尝鲜 MVC专题研究(五)——数据验证 MVC专题研究(四)——Html中的扩展方法 MVC专题研究(三)——数据绑定和传送 MVC2专题研究(一)——用MVC组织管理您的家庭收入 典型算法及应用——“递归法”探究 ASP.NET专题研究——资源文件的使用 NET基本探究系列——委托 NET常见类系列探究——序列化和反序列化的应用
MVC专题研究(二)——神奇的URL
maledong · 2009-11-24 · via 博客园 - maledong

     在开始本章节之前,因为微软已经释放了MVC2Beta版本,作者已经将自己的项目升级成了Beta2的版本(删除了Default.aspx并修正了一些Bug)来运行本程序。不过在本章中为了衔接上一章节的内容,继续开始MVC2Preview2)的内容。至于Beta2和正式版的新增内容将在MVC的最后于大家阐述。

一、神奇的URL

     或许你在运行本项目的时候发现本项目没有任何起始页,但是在浏览器启动(或者是输入"http://localhost:端口号"的时候就已经进入了首页。这个在以往的程序中是无法做到的(因为以往的程序中URL地址中的页面必须在物理上有映射逻辑,比如:http://localhost/Default.aspx,意味着一定在根目录下存在着一个Default.aspx页面);然而在MVC中却并不如此。如果你尝试做一个实验,请输入以下地址:

http://localhost:端口号/FinanceManager/AddItem

您将会发现——页面神奇地跳转到到了AddItem页。但是按照原来的路径映射,您应该认为说“FinanceManager下根本没有任何页面,只是一个Controller而已!”或许你还会按照原思路作出这样的想法:http://localhost:端口号/Views/AddItem.aspx,但是遗憾的是,这种想法也是错误的。哦,MyGod……

其实这种URL路径已经和真实的文件映射已经没有很大的关系了。你仔细看过我的前面一篇文章对于该项目的介绍之后,再了解结构之后你应该清楚地知道:所有的视图页面都在Views文件夹中,而Controllers中只有一个控制器文件。并且你有心的话,会发觉你那个实验的URL中的FinanceManager恰好是该Controller中的文件名,而AddItem恰恰又是该Controllers中的一个函数名称;打开Views下文件夹你细细观察,其中就有一个文件夹叫做FinanceManager,而且还包含着一个被成为“AddItem”的页面……

啊?MVC那么神奇?竟然可以通过地址映射“自动寻找”对应的逻辑控制代码,而且返回Views中的某个页面?是的,您的猜想是对的。一般而言,一个MVCURL的标准格式如下:

根目录(http://域名:[端口号]/控制器名/逻辑函数名)

v  其中“控制器名”是位于Controllers文件夹下的一个文件“排除后缀”的名称,这就意味着您必须命名规范,Controller文件必须是“XXXXController”,而且是区分大小写的(不信?您可以试试: http://localhost:端口号/FinanceManager/addItem)。当输入这样一个URL以后,程序自动会搜索全部本工程根目录下(以及所有子目录)中带有Controller后缀名的文件,去除Controller并与“控制器名”进行完全匹配,直到找到(没有找到将报错,说页面找不到)。实际上,既然MVC会自动搜索,您当然大可不必死板地将Controller文件放到一个地方(比如示例程序的Controllers文件夹),但是便于管理,微软(包括我)也是推荐您这样做的

v  在找到这样一个与之匹配的Controller之后,接下来读取“逻辑函数名”,逻辑函数实质就是这个Controller函数中的某个公共函数,因为也是同名匹配,所以您不能进行重载(设想:如果重载,系统到底取哪个函数呢?糊涂了),而且不允许使用泛型类型(比如您不能定义诸如:public ActionResult XXX<T>(T param){……}之类的函数,理由很简单——因为一旦定义了未知类型,您在使用这个函数的头一件事情必须要告诉该函数的类型,但是Controller是自动解析的,你根本没有办法告诉它什么类型,至于说为什么可以使用“系统基本类型?”的形式,比如int?(本质也是泛型,等同于Nullable<int>…,是因为int?只有两种类型——要么int,要么null,这两种都可以被识别的,而且最关键的在于Nullable<int>已经自行定义给出了)。当然还有其它的一些限制,因为考虑读者最容易犯忌的往往是这两个,所以特别着重提出。至于其它的可以在网络上自行搜索,自己动脑好好思考为什么。

由此可见,微软内部默认的机制已经规定了MVCURL的映射处理的方式:从冒号后开始解析,遇到第一个“/”前的一串字符串就是映射Controller后缀的文件名,待找到以后深入找里边的某个方法名(从第一个“/”到第二个“/”之间的一串字符串)。这样看来,“约定胜于配置”是微软MVC项目的关键之处。

二、自定义我的URL——我的地盘我做主:

或许你对这种默认的规则还怀有好奇心,想找找微软究竟定义在何处了:来,打开你的Global.aspx文件,看看里边是不是有这样一个静态方法的定义?

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute("Default”,

"{controller}/{action}",

new { controller = "FinaceManager", action = "Index" }

);

}

你发现模板自行定义了一个{controller}/{action}的格式。一般说来,MVC2ControllerAction必须定义(也就是说无论如何,系统总得要找到ControllerAction),只不过你可以指定默认值,就像上面给出的例子一样。因为给出了controlleraction的默认值,因此你直接就可以http://localhost:[端口号],而不必指出具体的ControllerAction了。

实际上,URL完全可以被自定义,比如你可以这样指定一个URL

routes.MapRoute("Default”,

"FinanceManager/{action}",

new { controller = "FinaceManager", action = "Index" }

);

}

你仔细观察我的这个示例代码,你将发现那个{controller}已经不复存在了。但“不复存在”不代表没有,因为很明显在new{…}已经定义。注意,“FinanceManager”是一个常数字符串,这意味着您在URL输入的时候必须是:http://localhost/:[端口号]/FinanceManager/才可以,不能说此处的FinanceManager就是Controller名。您完全可以使用{controller}{action}指定URL的格式化,这就意味着您可以自定义格式,让系统知道什么地方是controller,什么地方是action,以便让系统自行解析。当然,在缺省{controller}或者{action}的任何一个(或者全部)的定义情况下,请务必指定默认值。总而言之,判断的标准是:按照您所指定的URL系统应该能够解析得到controlleraction,否则必须指定默认值。

当然,除了可以定义常量(如上面的FinanceManager常量字符串前缀,变量也可以定义到URL中去,看这个例子:

routes.MapRoute("Default”,

"{controller}/{action}/{id}",

new { controller = "FinaceManager", action = "Index",id=”” }

);

}

这是微软标准的一个URL的定义(默认的,您下载我的代码看到的那个我已经去除了id,因为项目用不着)。您按照这个URL输入的标准输入应该是http://localhost:[端口号]/ControllerName/ActionName/Id,此时即便没有Id,因为ControllerAction已经可以找到,所以不会有错误,但是考虑到id作为参数传入对应Action方法会抛出异常(此可以参考我以后的“参数自动绑定”后续文章)。因此您最好指定一个默认值