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,对比一下:

  1. http://xxx.yyy.com/Admin/UserManager.aspx
  2. 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这类数据我们暂且约定为参数:

  1. http://xxx.yyy.com
  2. http://xxx.yyy.com/Home/1001
  3. http://xxx.yyy.com/Index/1001
  4. http://xxx.yyy.com/Home/Index/1001/2345
  5. 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路由的更多相关文章

  1. Asp.Net MVC4 之Url路由

    先来看下面两个个url,对比一下: http://xxx.yyy.com/Admin/UserManager.aspx http://xxx.yyy.com/Admin/DeleteUser/1001 ...

  2. Asp.Net MVC2.0 Url 路由入门---实例篇

    本篇主要讲述Routing组件的作用,以及举几个实例来学习Asp.Net MVC2.0 Url路由技术. 接着上一篇开始讲,我们在Global.asax中注册一条路由后,我们的请求是怎么转到相应的Vi ...

  3. Asp.Net MVC2.0 Url 路由入门---实例篇 【转】

    本篇主要讲述Routing组件的作用,以及举几个实例来学习Asp.Net MVC2.0 Url路由技术. 接着上一篇开始讲,我们在Global.asax中注册一条路由后,我们的请求是怎么转到相应的Vi ...

  4. ASP.NET MVC4学习笔记路由系统概念与应用篇

    一.概念 1.路由是计算机网络中的一个技术概念,表示把数据包从一个网段转发至另一网段.ASP.NET中的路由系统作用类似,其作用是把请求Url映射到相应的"资源"上,资源可以是一段 ...

  5. ASP.NET MVC 的URL路由介绍

    在这个教程中,向你介绍每个ASP.NET MVC一个重要的特点叫做URL路由.URL路由模块是负责映射从浏览器请求到特定的控制器动作. 在教程的第一部分,你将学习标准路由表如何映射到控制器的动作.在教 ...

  6. ASP.NET MVC4学习笔记路由系统实现

    一.路由实现 路由系统实际是一个实现了ASP.NET IHttpModule接口的模块,通过注册HttpApplication的PostResolveRequestCache 事件对Url路由处理.总 ...

  7. ASP.NET MVC4实现URL伪静态

    1.在Web.config添加节点配置: <system.webServer> <modules runAllManagedModulesForAllRequests="t ...

  8. ASP.NET MVC5(一)—— URL路由

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  9. IIS 7.5 + asp.net MVC4 设置路由处理URL请求

    使用asp.net MVC4开发的网站,在本地的VS012环境下运行,一切正常.但当发布到Windows 2008 R2(IIS7.5 + Framework4.5)上时,访问相关网页时,出现有下面的 ...

随机推荐

  1. Java实现归并排序(转)

    Java实现归并排序  本文转自https://www.cnblogs.com/of-fanruice/p/7678801.html 归并排序 (merge sort) 是一类与插入排序.交换排序.选 ...

  2. Delphi-Cross-Socket

    Delphi-Cross-Socket GITHUB:https://github.com/winddriver/Delphi-Cross-Socket # Delphi 跨平台 Socket 通讯库 ...

  3. Unity3d操作的一些技巧知识点和BUG解决方案

    自己记录一些东西,转载请良心注明出处.     1.如何同时打开两个UNITY3D项目. 有时候需要对比,或者需要添加另一个项目的某资源到目前项目,同时打开两个项目看起来会比较明了.如果直接打开的话, ...

  4. arcgis连接excel出现数据库失败 外部数据库驱动程序意外错误

    微软搞事情,删除以下更新就行:win7 KB4041678 KB4041681SERVER 2008 R2 KB4041678 KB4041681WIN10 KB4041676 KB4041691SE ...

  5. dwz 刷新当前navtab

    List.jsp 其navtabId为TradingStrategy_31: <form method="post" action="${contextPath}/ ...

  6. Tomcat 7 的七大新特性

    英文原文:Top 7 Features in Tomcat 7: The New and the Improved Tomcat的7引入了许多新功能,并对现有功能进行了增强.很多文章列出了Tomcat ...

  7. Gson全解析(下)-Gson性能分析

    前言 在之前的学习中,我们在Gson全解析(上)Gson使用的基础到分别运用了JsonSerializer和JsonDeserializer进行JSON和java实体类之间的相互转化. 在Gson全解 ...

  8. ORA-12560: TNS: 协议适配器错误的解决方法

    ORA-12560: TNS: 协议适配器错误的解决方法 造成ORA-12560: TNS: 协议适配器错误的问题的原因有三个: 1.监听服务没有起起来.windows平台个一如下操作:开始---程序 ...

  9. C语言:通过函数指针来完成两个数的加减乘除(函数指针当做参数使用)

    // //  main.c //  Function_pointer // //  Created by mac on 15/8/2. //  Copyright (c) 2015年. All rig ...

  10. LZO 使用和介绍

    LZO说明 摘要 LZO 是一个用 ANSI C 语言编写的无损压缩库.他能够提供非常快速的压缩和解压功能.解压并不需要内存的支持.即使使用非常大的压缩比例进行缓慢压缩出的数据,依然能够非常快速的解压 ...