http://cache.baiducontent.com/c?m=9d78d513d98316fa03acd2294d01d6165909c7256b96c4523f8a9c12d52219564615fea662675513d3b23a2752fe1e08b9a1706537747ce0ddd5fb0b9fac925e53df6129035dc43d459566eb9a5125b740cd1daff445b2adf045c0ef9099&p=8a7bd215d9c041a807be9b7c425498&newp=8467c54ad5c346e82abe9b7c165c81231610db2151d09767&user=baidu&fm=sc&query=RegisterRoutes&qid=b0cb520300007c5e&p1=2

Asp.Net MVC 路由

原文链接:http://www.asp.net/learn/mvc/

在这篇教程中,我将为你介绍每个ASP.NET MVC应用程序都具有的一个重要功能,称作ASP.NET路由(ASP.NET Routing)。ASP.NET路由模块负责将即将到来的浏览器请求映射到特定的MVC控制器动作。学完这篇教程之后,你将会理解标准的路由表是如何将 请求映射到控制器动作的。

1. 理解默认路由表

当你创建一个新的ASP.NET MVC应用程序时,应用程序已经被配置为使用ASP.NET路由。ASP.NET路由在两个地方设置。

第一点,在你的应用程序Web配置文件(Web.config文件)中启用ASP.NET路由。在配置文件中有四个节点与路由有 关:sytem.web.httpModules节,system.web.httpHandlers 节,system.webserver.modules节,以及system.webserver.handlers节。特别要小心不要删除了这些节点, 因为没有它们路由将不能工作。

第二点,也是更为重要的一点,在应用程序的Global.asax文件中创建了一个路由表。Global.asax文件是一个特殊的文件,它包含了作用于ASP.NET应用程序生命周期事件的事件处理程序。路由表在Application Start事件期间创建。

代码清单1中的文件包含了一个ASP.NET MVC应用程序的默认Global.asax文件。

代码清单1 - Global.asax.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode,
    // visit http://go.microsoft.com/?LinkId=9394801

public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

"Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

}

protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

当一个MVC应用程序首次运行时,会调用Application_Start()方法。这个方法随后调用了RegisterRoutes()方法。RegisterRoutes()方法创建了路由表。

默认的路由表包含了一个路由(名叫Default)。Default路由将URL的第一部分映射到控制器名,URL的第二部分映射到控制器动作,第三个部分映射到一个叫做id的参数。

假设你在浏览器的地址栏输入了下面的URL:

/Home/Index/3

默认的路由将这个URL映射为下面的参数:

Controller = Home

Action = Index

id = 3

当你请求URL /Home/Index/3时,将会执行下面的代码:

HomeController.Index(3)

Default路由包含了所有三个参数的默认值。如果你不提供控制器,那么控制器参数默认值为Home。如果你不提供动作,动作参数默认为值Index。最后,如果你不提供id,id参数默认为空字符串。

让我们看看几个例子,Default路由是如何将URL映射到控制器动作的。设想你在浏览器地址栏输入了下面的URL:

/Home

由于Default路由参数的默认值,输入这个URL将会调用代码清单2中的HomeController类的Index()方法。

代码清单2 - HomeController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index(string id)
        {
            return View();
        }
    }
}

在代码清单2中,HomeController类包含了一个叫做Index()的方法,它接受一个叫做Id的参数。URL /Home将会导致调用Index()方法,并使用空字符串作为Id参数的值。

出于MVC框架调用控制器动作的方式,URL /Home也匹配代码清单3中HomeController类的Index()方法。

代码清单3 - HomeController.cs(不含参数的Index动作)

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

代码清单3中的Index()方法不接受任何的参数。URL /Home将会导致调用这个Index()方法。URL /Home/Index/3也会调用这个方法(Id被忽略)。

URL /Home也会匹配代码清单4中HomeController类的Index()方法。

代码清单4 - HomeController.cs(使用可空参数的Index动作)

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            return View();
        }
    }
}

在代码清单4中,Index()方法拥有一个整数参数。因为这个参数是一个可空参数(可以拥有Null值),因此可以调用Index()而不会引发错误。

最后,使用URL /Home 调用代码清单5中的Index()方法将会引发一个异常,因为Id参数并非一个可空参数。如果你试图调用Index()方法,那么你将会获得一个图1中所示的错误。

代码清单5 - HomeController.cs(含有Id参数的Index动作)

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index(int id)
        {
            return View();
        }
    }
}

图01: 调用一个期望参数值的控制器动作

另一方面,URL /Home/Index/3 能够与代码清单5中的Index控制器动作很好地工作。/Home/Index/3请求将会引发调用含有一个Id的Index()方法,且该Id值为3.

这篇教程的目的是为你提供一个ASP.NET路由的简短介绍。我们仔细查看了默认的路由表,它在你创建新的ASP.NET MVC应用程序时获得。你学习了默认的路由表如何将URL映射到控制器动作。

2.创建自定义路由

在这篇教程中,你会学习到如何为ASP.NET MVC应用程序添加自定义路由。你会学习如何将Global.asax文件中的默认路由表修改为自定义路由。

对于简单的ASP.NET MVC应用程序,默认的路由表已经可以很好的完成工作了。然而,你可能发现会存在特定的路由需求。在这种情况下,你可以创建一个自定义路由。

设想一下,举个例子,你正在创建一个博客应用程序。你可能想要像这样处理即将到来的请求:

/Archive/12-25-2009

当用户输入这一请求,你想要返回对应于日期12/25/2009的博客条目。为了处理这种类型的请求,你需要创建一个自定义路由。

代码清单1中的Global.asax包含了一个新的自定义路由,命名为了Blog,它处理了类似/Archive/条目日期 这样的请求。

代码清单1 - Global.asax(含有自定义路由)

using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1
{

public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

"Blog",                                           // Route name
                "Archive/{entryDate}",                            // URL with parameters
                new { controller = "Archive", action = "Entry" }  // Parameter defaults
            );

"Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

}

protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

添加到路由表中的路由顺序非常重要。我们的新自定义Blog路由在现有的Default路由前面。如果你将这个顺序颠倒过来,那么Default路由将总是被调用,而不是自定义路由。

自定义Blog路由匹配任何以/Archive/作为开始的请求。因此,它匹配所有下面的URL:

/Archive/12-25-2009

/Archive/10-6-2004

/Archive/apple

自定义路由将即将到来的请求映射到名为Archive的控制器,并且调用了Entry()动作。当调用Entry()方法时,条目日期作为entryDate参数进行了传递。

代码清单2 - ArchiveController.cs

using System;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class ArchiveController : Controller
    {

public string Entry(DateTime entryDate)
        {
            return "You requested the entry from " + entryDate.ToString();
        }

}
}

注意到代码清单2中的Entry()方法接受一个DateTime类型的参数。MVC框架非常的聪明,足以自动地将URL中的条目日期转换为DateTime值。如果URL中的条目日期参数不能转换为DateTime,将会引发错误(如图1)。

图1 - 转换参数时的错误

这篇教程的目的是演示如何创建自定义路由。你学习了如何在Global.asax文件的路由表中添加自定义路由,该路由代表着博客条目。我们讨论了如何将对博客条目的请求映射到名为ArchiveController的控制器,和名为Entry()的控制器动作上。

3.创建路由约束

你可以使用路由约束来限制匹配特定路由的浏览器请求。可以使用正则表达式来指定一个路由约束。

举个例子,假设你已经在Global.asax文件中定义了一个路由。

代码清单1 - Global.asax.cs

"Product",
    "Product/{productId}",
    new {controller="Product", action="Details"}
);

代码清单1包含一个叫做Product的路由。你可以使用Product路由将浏览器请求映射到代码清单2中的ProductController。

代码清单2 - Controllers\ProductController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Details(int productId)
        {
            return View();
        }
    }
}

注意到Product控制器公布的Details()动作接受一个叫做productId的参数。这个参数是一个整数参数。

定义在代码清单1中的路由将会匹配下面的任意URL:

  • /Product/23
  • /Product/7

不幸的是,路由也会匹配下面的URL:

  • /Product/blah
  • /Product/apple

因为Details()动作期望的是一个整数值,发起一个含有非整数值的请求将会导致错误。举个例子,如果你在浏览器中输入/Product/apple URL,那么你将会得到图1所示的错误页。

图1:错误页

你实际想做的是只匹配包含合适整数productId的URL。当定义路由来限制与路由相匹配的URL时,你可以使用约束。代码3中的修改后的Product路由包含了一个正则表达式,它限制了只匹配数字。

代码清单3 - Global.asax.cs

"Product",
    "Product/{productId}",
    new {controller="Product", action="Details"},
    new {productId = @"\d+" }
 );

正则表达式\d+匹配一个或多个整数。这个限制使得Product路由匹配了下面的URL:

  • /Product/3
  • /Product/8999

但是不匹配下面的URL:

  • /Product/apple
  • /Product

这些浏览器请求将由另外的路由处理,或者,如果没有匹配的路由,将会返回一个“The resource could not be found”错误。

4. 创建一个自定义路由约束

这篇教程的目标是演示如何创建一个自定义路由约束。自定义路由约束允许你阻止某个路径被匹配,除非满足一些自定义的条件。

在这篇教程中,我们创建了一个Localhost路由约束。Localhost路由约束只匹配本地计算机发出的请求。通过互联网发出的远程请求不会被匹配。

你可以通过实现IRouteConstraint接口来实现一个自定义路由。这是一个极其简单的接口,它只描述了一个方法:

bool Match(
    HttpContextBase httpContext,
    Route route,
    string parameterName,
    RouteValueDictionary values,
    RouteDirection routeDirection
)

这个方法返回一个布尔值。如果返回了false,与约束相关联的路由将不会匹配浏览器请求。

Localhost约束包含在了代码清单1中。

代码清单1 - LocalhostConstraint.cs

using System.Web;
using System.Web.Routing;

namespace MvcApplication1.Constraints
{
    public class LocalhostConstraint : IRouteConstraint
    {
        public bool Match
            (
                HttpContextBase httpContext,
                Route route,
                string parameterName,
                RouteValueDictionary values,
                RouteDirection routeDirection
            )
        {
            return httpContext.Request.IsLocal;
        }

}
}

代码清单1中的约束利用了HttpRequest类公布的IsLocal属性。当发出请求的IP地址是127.0.0.1或者与服务器的IP地址相同时,这个属性返回true。

你在定义于Global.asax的路由中使用了自定义约束。代码清单2中的Global.asax文件使用了Localhost约束来阻止任何人
请求Admin页面,除非他们从本地服务器发出请求。举个例子,当请求来自远程服务器时,对于/Admin/DeleteAll的请求将会失败。

代码清单2 - Global.asax

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcApplication1.Constraints;

namespace MvcApplication1
{

public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

"Admin",
                "Admin/{action}",
                new {controller="Admin"},
                new {isLocal=new LocalhostConstraint()}
            );

////    "Default",                                              // Route name
            //    "{controller}/{action}/{id}",                           // URL with parameters
            //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            //);
        }

protected void Application_Start(){
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

Localhost约束使用在了Admin路由的定义中。这个路由不会被远程浏览器请求所匹配。然而,应该意识到定义在Global.asax中的
其他路由可能会匹配相同的请求。理解这一点很重要:约束阻止了特定路由匹配某一请求,而不是所有定义在Global.asax文件中的路由。

注意到Default路由在代码清单2中的Glabal.asax文件中被注释掉了。如果你包含Default路由,那么Default路由将会匹
配对Admin控制器的请求。在这种情况下,远程用户仍然可以调用Admin控制器的动作,即使他们的请求不匹配Admin路由。

Asp.Net MVC 路由 - Asp.Net 编程 - 张子阳的更多相关文章

  1. ASP.NET MVC 路由(三)

    ASP.NET MVC路由(三) 前言 通过前两篇的学习会对路由系统会有一个初步的了解,并且对路由系统中的Url规则有个简单的了解,在大家的脑海中也有个印象了,那么路由系统在ASP.NETMVC中所处 ...

  2. ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 路由 前两章节中,我们提到 ASP.NET Core 支持 MVC 开发 ...

  3. ASP.NET MVC 路由(一)

    ASP.NET MVC路由(一) 前言 从这一章开始,我们即将进入MVC的世界,在学习MVC的过程中在网上搜索了一下,资料还是蛮多的,只不过对于我这样的初学者来看还是有点难度,自己就想看到有一篇引导性 ...

  4. ASP.NET MVC 路由(二)

     ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...

  5. ASP.NET MVC 路由(四)

    ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...

  6. ASP.NET MVC 路由(五)

    ASP.NET MVC 路由(五) 前言 前面的篇幅讲解了MVC中的路由系统,只是大概的一个实现流程,让大家更清晰路由系统在MVC中所做的以及所在的位置,通过模糊的概念描述.思维导图没法让您看到路由的 ...

  7. AngularJS html5Mode与ASP.NET MVC路由

    AngularJS html5Mode与ASP.NET MVC路由共存 前言 很久之前便听说AngularJS,非常酷,最近也比较火,我也在持续关注这个技术,只是没有认真投入学习.前不久公司找我们部门 ...

  8. Asp.Net MVC路由调试好帮手RouteDebugger

    Asp.Net MVC路由调试好帮手RouteDebugger 1.获取方式 第一种方法: 在程序包控制台中执行命令 PM> Install-Package routedebugger 安装成功 ...

  9. ASP.NET MVC路由(5)

    ASP.NET MVC路由(五) 前言 前面的篇幅讲解了MVC中的路由系统,只是大概的一个实现流程,让大家更清晰路由系统在MVC中所做的以及所在的位置,通过模糊的概念描述.思维导图没法让您看到路由的实 ...

随机推荐

  1. 纯 CSS 创建一个三角形

    [要求]:用纯CSS创建一个三角形的原理是什么? ♪ 答: 把上.左.右三条边隐藏掉(颜色设为 transparent) [实现]: #demo { width: 0; height: 0; bord ...

  2. 在Linux上使用web2py_uwsgi_nginx搭建web服务器

    本文介绍在Linux使用Python+Nginx+web2py+uWSGI搭建一个web服务器的过程. Python 2.7.11 解压安装包 tar -zxvf Python-2.7.11.tgz ...

  3. VGA DVI HDMI区别

    VGA,DVI,HDMI是目前常用的3种不同显示接口的名称.在树莓派的边缘既有HDMI的接口,也有RCA的接口,而显示器上也是既有DVI,又有VGA.上个月买连接线,没有仔细检查买了一根HDMI对VG ...

  4. CSS基础知识点(二)——选择器

    在这一篇中,主要总结一下CSS中的选择器. 参考:http://www.cnblogs.com/webblog/archive/2009/07/07/1518274.html CSS中的选择器主要包括 ...

  5. uestc1888 Birthday Party    组合数学,乘法原理

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=25539#problem/G 题目意思: 有n个人,每个人有一个礼物,每个人能拿 ...

  6. nginx和apache下的url rewrite

    将服务器上面的数据同步到本地之后,发现打开首页显示不正常,本地服务器是apache,经过打开url rewrite之后本地首页正常显示. 原因是phpwind本身支持了url rewrite的功能,但 ...

  7. 解决dede搜索页面只能显示10条信息解决方案

    解决dede搜索页面只能显示10条信息解决方案,感觉显示的信息太少,这时就要想办法去解决一下.看看有什么好办法来解决一下这个问题. dede搜索页模板中,默认只能显示10条记录. 打开dede搜索页模 ...

  8. HDU-1828 Picture(扫描线)

    题目大意:给若干个矩形,求轮廓边长. 题目分析:与求面积类似.按从下往上扫描,仍然是底边添加,上边删除.但要同时维护竖边的数目,每次扫描对答案的贡献为扫描线上总覆盖长度的变化量加上竖边的增量.总覆盖长 ...

  9. kuangbin_ShortPath K (POJ 3159)

    很简单的模板题 放在K那么后的位置的原因大概是 光看题意并不是很容易想到是用最短路解吧 奈何kuangbin分在了最短路专题 一发水过 #include <iostream> #inclu ...

  10. WaitAny, WaitAll 和 SignalAndWait

    除了Set 和 WaitOne方法外,在类WaitHandle中还有一些用来创建复杂的同步过程的静态方法. WaitAny, WaitAll 和 SignalAndWait使跨多个可能为不同类型的等待 ...