【转】Asp.Net MVC4 之Url路由
MVC4常见路由的处理方式
//直接方法重载+匿名对象
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
); //构造路由然后添加
Route myroute = new Route("{controller}/{action}", new MvcRouteHandler());
routes.Add("MyRoute0", myroute); //跨命名空间路由
routes.MapRoute(
"AddContollerRoute",
"Home/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.AdditionalControllers" }
);
routes.MapRoute(
"MyRoute1",
"{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.Controllers" }
); //可变长度路由 + 正则表达式匹配路由
routes.MapRoute(
"MyRoute2",
"{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^H.*", action = "^Index$|^About$" },
new[] { "URLsAndRoutes.Controllers" }
); //指定请求方法
routes.MapRoute("MyRoute3", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^H.*", action = "Index|About", httpMethod = new HttpMethodConstraint("GET") },
new[] { "URLsAndRoutes.Controllers" }
);
先来看下面两个个url,对比一下:
- http://xxx.yyy.com/Admin/UserManager.aspx
- http://xxx.yyy.com/Admin/DeleteUser/1001
对于第1个Url,假设它与服务器上的文件有直接的关系,那么服务器在接受客户端请求并将对应的文件传送给客户端。我们大概可以猜到它是对用户管理的一个页面,它的物理文件UserManager.aspx在网站根目录下面的Admin文件夹中。而第2个url,在不知道Mvc路由以及Url重写时,很难猜到这个Url背后具体有些什么,前提条件是基于.Net框架开发的Web项目。 那么在这里,我们引入Asp.Net Mvc Url路由这个概念,也正是本文所要阐述的主题,Url路由模块是负责映射从浏览器请求到特定的控制器动作。
基于上面提到的Url路由以及其作用,我们就大概能猜到第2个Url背后有些啥了。 自然而然的Admin就是控制器了,DeleteUser是控制器里面的动作及Action了,1001就是Action的参数。到这里我们对Url路由有一个简单的认识,那么接着看下面一组url,假设Home是控制器,Index是控制器里面的Action,至于1001或者2345这类数据我们暂且约定为参数:
- http://xxx.yyy.com
- http://xxx.yyy.com/Home/1001
- http://xxx.yyy.com/Index/1001
- http://xxx.yyy.com/Home/Index/1001/2345
- http://xxx.yyy.com/System/Home/Index/1001
按照约定,从上面的几组Url中可以看出,有的缺控制器,有的缺Action,有的带有好几个参数,有的又莫名的多出了控制器、Action、参数之外的东西,那么他们能正确的访问吗?
注册路由
在vs2012里面新建一个asp.net mvc4 web 应用程序项目,可以在项目的根目录下App_Start里面看到RouteConfig文件,在这个文件里面就可以添加url路由了。在文件里面可以看到MapRoute 这个方法,它是RouteCollection的扩展方法,并且含有多个重载,下面看看MapRoute方法的参数,这里选参数最多的那个:
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);
从上面的代码片段大概可以看出该方法含有路由名称、路由的Url、默认值、约束、首先查找路由所在的命名空间,该方法是返回对映射路由的引用。不过在RouteConfig文件中我们可以看到添加路由的代码:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
稍微分析一下这段代码可以知道,在路由集合里面添加了一个名为"Default"的路由,并且有一个默认的路由指向,指向名称为Home的控制器,并且Action为Index,可以明显的看到这里 "id = UrlParameter.Optional" 的写法,它的意思就是说Action的参数可以不需要用户来指定,可以缺省。
多个参数如何传递
之前在一个QQ群里面见到一兄弟在问,类似这样的Url“http://xxx.yyy.com/Home/Index/1001/2345/tauruswu”在路由里面怎么配置?其实这个也很简单,我们只需要将路由配置、以及Action稍作调整。
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
这个是调整之后的路由配置,只需要在Url后面再加上"{*catchall}"即可,那么Action调整之后如下
public ActionResult Index(string id,string catchall)
{
ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View();
}
在Action里面定义了一个参数"catchall"用来接收Url中除了Id之外其他所有的参数值,那么上面那个Url中接收的参数就是“2345/tauruswu”,这样看起来好不好了,不过我觉得怪怪的,有没有更好的解决方法了?Url有必要写成那么长吗?这个问题在后续文章中会涉及到。
你也许会犯的错误
不知各位兄弟在刚刚接触MVC的时候,有没有碰到过这样的问题,如下图
那么这个错误是如何引起的了?代码是这么写的

namespace MvcDebug.Controllers
{
public class HomeController : Controller
{
public ActionResult Index(string id,string catchall)
{
ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View();
}
}
} namespace MvcDebug.Controllers.Tauruswu
{
public class HomeController : Controller
{
public ActionResult Index(string id, string catchall)
{
ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View();
}
}
}

我们再看英文提示大概就是说匹配出了多个控制器为"Home"的类型,在它的提示中也告诉了我们解决方法,说在MapRoute方法中使用"namespaces"这个参数,我们先将这个放在一边,将抛出这个错误的源码给找出来,具体的源码在DefaultControllerFactory这个类中,看类名就能猜出它的作用是什么了。

private Type GetControllerTypeWithinNamespaces(RouteBase route, string controllerName, HashSet<string> namespaces)
{
// Once the master list of controllers has been created we can quickly index into it
ControllerTypeCache.EnsureInitialized(BuildManager); ICollection<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
switch (matchingTypes.Count)
{
case 0:
// no matching types
return null; case 1:
// single matching type
return matchingTypes.First(); default:
// multiple matching types
throw CreateAmbiguousControllerException(route, controllerName, matchingTypes);
}
}

上面粗体标出的代码,因为我们在路由中没有配置“namespaces”这个参数,这段代码的意思就是通过控制器名称获取所匹配的控制器类型集合,当获取到集合数据之后就开始Case了,很明显,这里集合的数目是2,自然就抛错了。
问题出来了,该如何解决?在错误提示中说要用到“namespaces”这个参数,我们能不能告诉MVC解析引擎,在解析控制器名称时,能不能对某些命名空间进行优先处理,事实上是可以的,只需要在配置路由的地方稍微调整一下
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MvcDebug.Controllers.Tauruswu" }
);
上面标粗的代码的意思是说优先解析“MvcDebug.Controllers.Tauruswu”这个命名空间里面的控制器。
路由约束
对于路由约束,我个人觉得这个可能在实际开发中用的不是很多,既然MapRoute方法提供了constraints这个参数及约束,那么在某些特定的场合肯定能发挥它的作用。在MVC中提供了三种路由约束方案,分别是: 1)正则表达式 ,2)http方法 ,3)自定义约束 。下面我们分别介绍下这三种约束的使用方法。
1)正则表达式 ,在路由配置中,我们做了这样的规则,只匹配Controller名称以H开头的

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional },
constraints: new { controller = "^H.*" },
namespaces: new[] { "MvcDebug.Controllers.Tauruswu" }
);

2) http方法 ,我们将路由配置稍作修改

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint("POST"), },
namespaces: new[] { "MvcDebug.Controllers.Tauruswu" }
);

然后在对应的Action上面打个标记

[HttpGet]
public ActionResult Index()
{
ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View();
}

你们说这样行不行了?
3) 自定义约束,如果说上面两种需求还是不能满足你,那么我们可以自定义约束。我们翻看HttpMethodConstraint这个类,可以看到它是继承IRouteConstraint这个接口,其定义是
public interface IRouteConstraint
{
bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
}
里面只有一个布尔类型的方法,关于这个例子,是从网上借鉴过来的,如下

public class CustomConstraint : IRouteConstraint
{
private string requiredAgent; public CustomConstraint(string agentArgs)
{
this.requiredAgent = agentArgs;
} public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(requiredAgent);
} }

这段代码的意思就是检查客户端请求的UserAgent属性值,看它是否含有一个被传递给构造函数的值。那么我们将路由作如下修改

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{*catchall}",
defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional },
constraints: new { customConstraint = new CustomConstraint("IE"), },
namespaces: new[] { "MvcDebug.Controllers.Tauruswu" }
);

很显然,这个只能在IE游览器下面游览。
如何创建自定义路由处理程序
在翻阅MapRoute方法源码的时候,看到了这么一段

Route route = new Route(url, new MvcRouteHandler())
{
Defaults = CreateRouteValueDictionary(defaults),
Constraints = CreateRouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
}; .....
routes.Add(name, route);

在Route实例化的时候,它是用到了“MvcRouteHandler“这个类,该类继承”IRouteHandler“接口,如果我们不用系统里面已经定义好的路由处理方案,我们要自己来实现一套?改怎么下手,此时只需要继承”IRouteHandler“这个接口并实现”GetHttpHandler“方法即可。
最后在添加路由时,像这样操作
routes.Add(new Route("DemoUrl",new DemoRouteHandler());
当我们在游览器里面请求/DemoUrl这个地址时,就会用到我们自定义的处理程序,在实际开发当中,如果真的要用到自定义路由处理程序,那么我们就要实现很多原本框架所实现的空能,虽然这给我们带来了很大的扩展空间,但是又不可控。
总结
Url路由系统是通过请求地址进行解析从而得到以目标Controller/Action名称为核心的路由数据,Url路由系统是建立在Asp.net 之上,我们在调试System.Web.Routing的源码时候可以得知。在这里我们由浅入深的了解了路由系统,接下来我们会讲到控制器以及Action,也是最为核心的东西。
转发处:http://www.cnblogs.com/wucj/p/3113878.html
【转】Asp.Net MVC4 之Url路由的更多相关文章
- Asp.Net MVC4 之Url路由
先来看下面两个个url,对比一下: http://xxx.yyy.com/Admin/UserManager.aspx http://xxx.yyy.com/Admin/DeleteUser/1001 ...
- Asp.Net MVC2.0 Url 路由入门---实例篇
本篇主要讲述Routing组件的作用,以及举几个实例来学习Asp.Net MVC2.0 Url路由技术. 接着上一篇开始讲,我们在Global.asax中注册一条路由后,我们的请求是怎么转到相应的Vi ...
- Asp.Net MVC2.0 Url 路由入门---实例篇 【转】
本篇主要讲述Routing组件的作用,以及举几个实例来学习Asp.Net MVC2.0 Url路由技术. 接着上一篇开始讲,我们在Global.asax中注册一条路由后,我们的请求是怎么转到相应的Vi ...
- ASP.NET MVC4学习笔记路由系统概念与应用篇
一.概念 1.路由是计算机网络中的一个技术概念,表示把数据包从一个网段转发至另一网段.ASP.NET中的路由系统作用类似,其作用是把请求Url映射到相应的"资源"上,资源可以是一段 ...
- ASP.NET MVC 的URL路由介绍
在这个教程中,向你介绍每个ASP.NET MVC一个重要的特点叫做URL路由.URL路由模块是负责映射从浏览器请求到特定的控制器动作. 在教程的第一部分,你将学习标准路由表如何映射到控制器的动作.在教 ...
- ASP.NET MVC4学习笔记路由系统实现
一.路由实现 路由系统实际是一个实现了ASP.NET IHttpModule接口的模块,通过注册HttpApplication的PostResolveRequestCache 事件对Url路由处理.总 ...
- ASP.NET MVC4实现URL伪静态
1.在Web.config添加节点配置: <system.webServer> <modules runAllManagedModulesForAllRequests="t ...
- ASP.NET MVC5(一)—— URL路由
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- IIS 7.5 + asp.net MVC4 设置路由处理URL请求
使用asp.net MVC4开发的网站,在本地的VS012环境下运行,一切正常.但当发布到Windows 2008 R2(IIS7.5 + Framework4.5)上时,访问相关网页时,出现有下面的 ...
随机推荐
- 安装wp8sdk 当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内。
安装wp8sdk 当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内. [1404:0090][2015-06-12T08:00:53]: Error 0x800b0101: Failed ...
- JAVA自定义注解SpringAOP
原文:https://my.oschina.net/wangnian/blog/801348 前言:Annotation(注解)是JDK5.0及以后版本引入的,它的作用就是负责注解其他注解.现在开发过 ...
- Kafka分布式环境搭建 (二)赞
这篇文章将介绍如何搭建kafka环境,我们会从单机版开始,然后逐渐往分布式扩展.单机版的搭建官网上就有,比较容易实现,这里我就简单介绍下即可,而分布式的搭建官网却没有描述,我们最终的目的还是用分布式来 ...
- 经典数独游戏+数独求解器—纯C语言实现
"心常乐数独小游戏"(下面简称"本软件")是一款windows平台下的数独游戏软件. 本软件是开源.免费软件. 本软件使用纯C语言编写,MinGW编译,NSIS ...
- dubbo培训文档
培训文档 1.<服务框架实践与探索> 主题:QCon2011杭州主题演讲,分享Dubbo服务框架的实践历程.主讲:钱霄,梁飞课件:Service Framework Practices.p ...
- 15、高可用 PXC(percona xtradb cluster) 搭建
安装环境: 集群名 pxc_lk 节点1: 192.168.1.20 节点2: 192.168.1.21 节点3: 192.168.1.22 所有节点安装 wget http://www.perc ...
- 【BestCoder】【Round#41】
枚举+组合数?+DP+数学问题 http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=582 QAQ许久没打过比赛,来一发BC,结果还是只 ...
- 用java查询HBase中某表的一批数据
java代码如下: package db.query; import java.io.IOException; import org.apache.hadoop.conf.Configuration; ...
- 第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程
注意:本文主要参考自<深入理解Java虚拟机(第二版)> 说明:查看本文之前,推荐先知道JVM内存结构,见<第一章 JVM内存结构> 1.内存回收的区域 堆:这是GC的主要区域 ...
- 如何在Linux上面安装GCC 4.1.2
安装步骤: 1.首先下载GCC 4.1.2的source code package: $ wget http://mirrors.ustc.edu.cn/gnu/gcc/gcc-4.1.2/gcc-4 ...