浅谈MVC中路由
引言
学习ASP.NET MVC 路由这一关是肯定必不可少的。这一节,我们就来简单介绍下MVC中的路由机制。简单的路由机制相信大家都已了解,这一节主要介绍路由中很少使用的部分。
使用静态URL片段
在一个路由中,并不是所有的URL片段都要求是动态的,也可以创建具有静态片段的模式。例如以下的路由:
routes.MapRoute("StaticRoute", "X{controller}/{action}",
new { controller = "Home", action = "Index" },
new string[] { "MyFirstMvcProject.Controllers" });
我们看到这条路由定义了第一个片段以字母X打头,controller的值是X字母以后的部分,第二个片段Action定义了默认值Index。这条路由将匹配任何X字母开头,controller值是取自第一个片段除字母X以外的部分。
一个有趣的例子:
设想下这样的场景,如果您的网站已经发布好久了,用户与网站之间已经形成了某种契约。例如。用户对于这个地址已经非常熟悉http://www.asp.net-example.com/Learn/Index。那么很显然控制器是Learn。如果现在您需要对程序进行重构,那么我们最好保留用户已经熟悉的链接地址。假设重构以后,新的控制器是Home。那么我们可以通过一条保留旧有URL地址的路由来实现这个功能。
routes.MapRoute("StaticRoute", "Learn/{action}",
new { controller = "Home", action = "Index" },
new string[] { "MyFirstMvcProject.Controllers" });
上面的路由,我们输入Learn/Index时,路由机制会自动匹配新的控制器Home。这样一方面没有打断网站与已有用户之间形成的契约,同时又对程序功能做了一个较好的迁移。我们在浏览器中运行如下:
我们看到,我们输入/Learn/Index。路由找到的是HomeController。
定义可变长路由
我们通过定义可变长度的路由来匹配任意长度的URL。我们通过设置一个*catchall片段变量可以定义对可变片段数量的支持。请看下面的路由
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyFirstMvcProject.Controllers" }
);
我们来看下面的例子:
从这个例子我们看出,我们输入的URL是Home/Index/Id/Do/Operation。我们通过{*catchall}片段变量来获取URL中的片段。我们看到catchall获取的是Do/Operation。说明任意长度的片段变量我们都可以获取到。只是在后续处理时,我们需要自行处理诸如Do/Opeartion这样的片段变量。
按命名空间来区分控制器执行顺序
从上面一个例子我们看到我们在路由里面设置了namespaces属性的值。如果我们不设置呢?看看会发生上面。请看下面的例子。
我们看到,我们的项目中存在两个HomeController控制器,浏览器路由机制解析出控制器名称是Home后,两个名称是Home的控制器,MVC框架不知道选择哪一个。这种情况下,我们需要设置下路由器的namespaces属性。这样MVC就会优先从这个命名空间下去寻找控制器。
定义自定义约束
MVC框架默认给我们提供了根据正则表达式和HTTP方法来约束路由。如果这些方法还是无法满足要求的话,我们可以通过实现IRouteConstraint接口来自定义路由约束。我们首先来看下IRouteConstraint的情况。
// 摘要:
// 确定 URL 参数是否包含此约束的有效值。
//
// 参数:
// httpContext:
// 一个对象,封装有关 HTTP 请求的信息。
//
// route:
// 此约束所属的对象。
//
// parameterName:
// 正在检查的参数的名称。
//
// values:
// 一个包含 URL 的参数的对象。
//
// routeDirection:
// 一个对象,指示在处理传入请求或生成 URL 时,是否正在执行约束检查。
//
// 返回结果:
// 如果 URL 参数包含有效值,则为 true;否则为 false。
bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
我们看到,这个接口就一个方法Match。MVC路由在匹配路由时会调用这个Match方法看请求的URL与当前路由是否匹配。下面我们还是通过一个例子来看一下把。请看以下例子:
public class UserAgentConstraint : IRouteConstraint
{
private string requestUserAgent; public UserAgentConstraint(string userAgent)
{
this.requestUserAgent = userAgent;
} public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
bool result = (httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(this.requestUserAgent));
return result;
}
}
我们写一条全新的路由来测试下,看看效果。如下:
routes.MapRoute("chromeRoute", "{controller}/{action}",
new { controller = "Home", action = "Index" },
new { customConstraint = new UserAgentConstraint("Chrome") });
这条路由使用了我们自定义的约束路由机制,我们看到我们传递了Chrome给自定义的路由匹配器。这样火狐浏览器和IE应该没法进行浏览,谷歌是可以的。打开浏览器试一下。
我们使用火狐浏览器来访问/Home/Index。会出现404的问题。
而我们使用谷歌浏览器访问时,是可以正常进行访问的。
对磁盘文件进行路由
我们知道对于所有的请求并不是都是针对控制器和动作的。也有很多是对静态文件的访问。例如图像,样式文件,JS代码文件等。默认情况下,路由系统在评估应用程序的路由之前,会考察一个URL是否匹配一个磁盘文件。如果匹配,该文件会用来对该请求进行服务。应用程序定义的路由就不会被使用。
我们可以通过设置routes.RouteExistingFiles = true来对MVC的默认机制进行修改。通过设置为true,意味着对已存在文件也进行路由。为了演示例子,我们还需要配置应用程序服务器,告诉IIS Express以便在请求到达MVC路由系统之前,不要拦截对磁盘文件的请求。请看下面的配置。
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
找到这一配置节点,将preCondition设置为""即可。
这时候我们在浏览器中输入Content/CustomerJS.js会看的下面这一幕。
我们看到,我们启用了对磁盘文件进行路由,这样MVC路由系统会设法找到名称为Content的控制器,这显然不是我们想要的。我们可以通过设置默认值来修复这个问题。
routes.MapRoute("StaticRoute", "Content/CustomerJS.js",
new { controller = "Home", action = "Index" },
new string[] { "MyFirstMvcProject.Controllers" });
绕过路由系统
通过使用routes.IgnoreRoute("Content/{filename}.js")我们可以对Content文件夹下的JS文件不进行路由,这样我们上面例子的时候,就会展示JavaScript代码了。
浅谈MVC中路由的更多相关文章
- 浅谈 MVC中的ViewData、ViewBag和TempData
ViewBag和TempData的区别 ViewData ViewBag 它是Key/Value字典集合 它是dynamic类型对像 从Asp.net MVC 1 就有了 ASP.NET MVC3 才 ...
- 浅谈MVC中的service层(转)
概述 mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层 ...
- 浅谈HTTP中GET、POST用法以及它们的区别
浅谈HTTP中GET.POST用法以及它们的区别 HTTP定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符.我们可以这样认为: 一 ...
- 浅谈 MVC 和 MTV
浅谈 MVC 和 MTV 一.MVC M:model,模型,就是数据模型,负责数据的存取: V:view,视图,负责页面的展示逻辑: C:controller,控制器,负责业务逻辑的处理: 二.MTV ...
- 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂
浅谈JS中的!=.== .!==.===的用法和区别 var num = 1; var str = '1'; var test = 1; test == num //tr ...
- 转:浅谈HTTP中Get、Post、Put与Delete的区别
1.GET请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改.增加数据,不会影响资源的内容,即该请求不会产生副作用.无论进行多少次操 ...
- [转]浅谈电路设计中应用DDR3处理缓存问题
本文转自:浅谈电路设计中应用DDR3处理缓存问题_若海人生的专栏-CSDN博客 DDR系列SDRAM存储芯片的高速率.高集成度和低成本使其理所当然成为存储芯片中的一霸.在PC和消费电子领域自是如此,它 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
随机推荐
- Object.observe将不加入到ES7
先请看 Object.observe 的 API Object.observe(obj, callback[, acceptList]) 它用来监听对象的变化,当给该对象添加属性,修改属性时都会被依次 ...
- Linux yum如何下载rpm包到本地
下载前先安装一个小插件 [root@wang yum.repos.d]# yum install -y yum-plugin-downloadonly 安装一个包的同时 加上 yum install ...
- android 项目中出现红色感叹号的解决方法
问题原因]:工程中classpath中指向的包路径错误 [解决办法]:右键项目名称 BuildPath ---> Configure Build Paht...中,然后上面有几个选项卡找到 Li ...
- 【2016-11-3】【坚持学习】【Day18】【Oracle 数据类型 与C#映射关系】
大部分类型的对应关系:原文:http://2143892.blog.51cto.com/2133892/499353 序号 Oracle数据类型 .NET类型 GetOracleValue类型 DbT ...
- 当我学完Python时我学了些什么
本文是本人学完Python后的一遍回顾,加深理解而已,Python大神请过~ 学习Python的这几天来,觉得Python还是比较简单,容易上手的,就基本语法而言,但是有些高级特性掌握起来还是有些难度 ...
- 洛谷P2158 [SDOI2008]仪仗队
题目描述 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图 ...
- 洛谷P1288 取数游戏II[博弈论]
题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...
- [No000071]C# 进制转换(二进制、十六进制、十进制互转)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- iOS Webview 实现修改javascript confirm 和 alert
贴代码: @interface UIWebView (JavaScriptAlert) -(void) webView:(UIWebView *)sender runJavaScriptAlertPa ...
- JSX语法简介
React的核心机制之一就是可以在内存中创建虚拟的DOM元素.React利用虚拟DOM来减少对实际DOM的操作从而提升性能. JSX简介 JSX就是Javascript和XML结合的一种格式.Reac ...