五、URL Routing介绍
在这篇文章中我们将介绍ASP.NET MVC程序中的重要的概念――URL路由。URL 路由就是把入站请求映射到指定的MVC控制器动作上。
在这篇文章第一部分,我们将学习使用默认路由表把请求映射到控制器动作上。在第二部分,我们将学习修改默认路由表,实现自定义路由。
一、使用默认路由表
当我们创建ASP.NET MVC应用程序的时候,应用程序会自动配置URL路由。URL路由需要通过两个地方进行设置。
第一、 在应用程序的Web.Config文件中启用URL路由。在配置文件中有四个配置节与URL路由相关:
a) system.web.httpModules
b) system.web.httpHandlers
c) system.webserver.modules
d) system.webserver.handlers
注意不能删除这些配置节,因为没有这些配置节URL路由无法运行。
第二、路由表代码被放在应用程序的Global.asax文件中。Global.asax文件是一个特殊的文件,它包含了ASP.NET应用程序生命周期中特殊的事件。路由表就是在应用程序启动的时候生成的。
下面是ASP.NET MVC应用程序中的Global.asax文件的代码
Listing 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 MyApp
{
public class GlobalApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = ""}// Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
当ASP.NET MVC应用程序第一次运行的时候,Application_Start()方法被调用。这个方法中调用了RegisterRoutes()方法,最后在RegisterRoutes()方法中创建了路由表。
默认路由表中包含了一个URL路由(名子叫作Default),这个Default路由把入站的URL第一部分{controller}映射为控制器名称,第二部分{action}映射为控制器动作,第三部分映射为动作的输入参数,叫做id。
假设我们在浏览器地址栏中输入下列URL
/Home/Index/3
Default路由把URL地址进行如下映射
controller = Home
action = Index
id = 3
当我们在URL地址栏中发出下列请求时
URL /Home/Index/3
会执行HomeController.Index(3)这个控制器方法。
Default路由默认包含上面三个参数,如果我们客户端请求没有指定控制器,那控制器默认为HomeController,如果没有指定动作,那动作默认为Index动作,最后如果没有指定动作的输入参数,那默认的动作输入能数是空字符串。
我们来看一下Default路由如何把URL映射到控制器动作上的。假设我们在浏览器地址栏中输入URL如下:
/Home
因为Default路由有默认的参数,所以这个URL地址会调用HomeController类的Index()方法。
Listing 2 – HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(string Id)
{
return View();
}
}
}
在上面的代码中,HomeController类包含名子为Index()的方法,它只接收一个参数Id,URL地址/Home默认调用了Index()方法,并向其参数Id传入一个空字符串.
(原创:灰灰虫的家 http://hi.baidu.com/grayworm)
/Home还映射到下面的Index()方法
Listing 3 – HomeController.cs (Index action with no parameter)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
这里的Index()方法并不接收任何参数,所以/Home在调用/Home/Index/3的时候也会调用Index()方法,但这时的Id参数会被忽略掉。
/Home还映射到下面的Index()方法
Listing 4 – HomeController.cs (Index action with nullable parameter)
using System;
using System.Collections.Generic;
using System.Linq; using System.Web;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int? id)
{
return View();
}
}
}
上面的代码中接收int?型参数,因为此参数是个可为空的参数,所以在调用Index()方法时,不会发生任何异常。
最后如果/Home射到下面的Index()方法,会发生异常信息,因为Index()方法的Id参数是个不可以为空的参数。
Listing 5 – HomeController.cs (Index action with Id parameter)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int id)
{
return View();
}
}
}
《图1》
在上面的代码中,/Home/Index/3这种URL地址调用会执行很正常,因为会自动把3传递给参数Id。
二、创建自定义路由(原创:灰灰虫的家 http://hi.baidu.com/grayworm)
在大多数的情况下,默认路由会默满足我们的需求,但当遇到一些特殊的需情况下,则需要我们创建我们自己的路由。
假设我们要做一个博客程序,我们需处理的请求URL地址如下:
/Archive/12-25-2009
当用户在客户端输入后,想取根据日期12/25/2009取得博客实体内容,这样就需要我们自定义URL路由。
下面的Global.asax文件包含了一个名子为Blog的自定义的路由,该路由的请求类似于/Archive/entrydate
Listing 6 – Global.asax (with custom route)
using System.Web.Mvc;
using System.Web.Routing;
namespace MyApp
{
public class GlobalApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"blog",
"Archive/{entryDate}",
new {controller = "Archive", action = "Entry"}
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = ""} // Parameter defaults );
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
添加路由表的顺序是很重要的。我们自定义的路由表被添加在Default路由之前,如过添加次序倒过来的话,那总会先调用Default路由了。
我们自定义的Blog路由匹配任何以/Archive/开头的请求,因此它能够匹配以下URL
/Archive/12-25-2009
/Archive/10-6-2004
/Archive/apple
自定义路由匹配Archive控制器,并触发控制器的Entry()动作。当Entry()动作被调用的时候,日期就被以参数据形式传递Entry()方法。
Blog自定义路由对应的控制器代码如下:
Listing 7 – ArchiveController.cs
using System;
using System.Web.Mvc;
namespace MyApp.Controllers
{
public class ArchiveController : Controller
{
public string Entry(DateTime entryDate)
{
return "You requested the entry on " + entryDate.ToString();
}
}
}
上面的代码中,Entry()方法接收一个日期时间型参数,ASP.NET MVC框架能够自动把URL地址栏中的日期字符串值转换为日期时间型数据,如果转换失败就会产生异常。
三、总结
这篇文章主要介绍了URL路由,
首先我们测试ASP.NET MVC默认路由。知道了默认路由如何映射控制器动作
然后我们又学习如何创建自定义路由。知道了如何在Global.asax文件中添加自定义路由来操作博客实体。讨论了如何把博客实体请求映射到ArchiveController的Entry()动作上。