URL 路由简介
在本教程中,将介绍对于每个 ASP.NET MVC 应用程序都非常重要的 URL 路由功能。URL 路由模型负责将进入的浏览器请求映射到特定的 MVC 控制器操作。
在本教程的第一部分中,我们将学习标准路由表如何将请求映射到控制器操作。在本教程的第二部分中,我们将学习如何使用自定义路由修改默认的路由表。
使用默认路由表
在创建新的 ASP.NET MVC 应用程序时,应用程序已配置好使用 URL 路由。URL 路由在两个位置设置。
第一,URL 路由在应用程序的 Web 配置文件(Web.config 文件)中启用。在配置文件中有 4 个部分与路由有关:system.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 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 应用程序第一次启动时,调用 Application_Start() 方法。此方法将调用 RegisterRoutes() 方法。RegisterRoutes() 方法创建路由表。
默认路由表包含一个路由(名称为 Default)。Default 路由将 URL 的第一段映射到控制器名称,将第二段映射到控制器操作,将第三段映射到名称为 id 的参数。
假设将下面的 URL 输入到 Web 浏览器的地址栏:
/Home/Index/3
Default 路由将此 URL 映射为下列参数:
controller = Home
action = Index
id = 3
在请求 URL /Home/Index/3 时,执行下面的代码:
HomeController.Index(3)
Default 路由包括三个参数的默认值。如果不提供控制器,则控制器参数默认为值 Home。如果不提供操作,则操作参数默认为值 Index。最后,如果不提供 id,则 id 参数默认为空字符串。
让我们看几个例子,了解 Default 路由将 URL 映射到控制器操作的方式。假设将下面的 URL 输入到 Web 浏览器的地址栏:
/Home
由于 Default 路由参数的默认值,输入此 URL 将导致调用程序清单 2 中的 HomeController 类的 Index() 方法。
程序清单 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(); } } }
在程序清单 2 中,HomeController 类包含名称为 Index() 的方法,此方法接受一个名称为 id 的参数。URL /Home 导致调用具有空字符串的 Index() 方法作为 id 参数的值。
由于 ASP.NET MVC Framework 激活控制器操作的方式,URL /Home 也可匹配程序清单 3 中的 HomeController 类的 Index() 方法。
程序清单 3 HomeController.cs(没有参数的 Index 操作)
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(); } } }
程序清单 3 中的 Index() 方法不接受任何参数。URL /Home 将导致调用 Index() 方法。URL /Home/Index/3 也激活此方法(忽略 Id)。
URL /Home 还可匹配程序清单 4 中的 HomeController 类的 Index() 方法。
程序清单 4 HomeController.cs(带有可以为空的参数的 Index 操作)
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(); } } }
在程序清单 4 中,Index() 方法有一个 Integer 参数。因为参数可以为空(值可以是 Nothing),所以可以在不引起错误的情况下调用 Index()。
最后,使用 URL /Home 激活程序清单 5 中的 Index() 方法将导致异常,因为 Id 参数不是可以为空的参数。如果试图激活 Index() 方法,则将得到如图 1 所示的错误页。
程序清单 5 HomeController.cs(带有 Id 参数的 Index 操作)
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:激活需要参数值的控制器操作( 单击查看大图)
另一方面,URL /Home/Index/3 可以与程序清单 5 中的 Index 控制器操作配合工作。请求 /Home/Index/3 导致调用带有值为 3 的 Id 参数的 Index() 方法。
创建自定义路由
对许多简单的 ASP.NET MVC 应用程序来说,使用默认的路由表就可以了。然而,您也可能会有特殊的路由需求。在这种情况下,应该创建自定义路由。
例如,假设正在创建博客应用程序。需要处理如下所示的进入请求:
/Archive/12-25-2009
当用户输入此请求时,想返回日期为 12/25/2009 的博客条目。为了处理这种类型的请求,需要创建自定义路由。
程序清单 6 中的 Global.asax 文件包含一个新的自定义路由,名称为 Blog,它处理形如 /Archive/条目日期的请求。
程序清单 6 Global.asax(使用自定义路由)
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); } } }
向路由表添加路由的顺序非常重要。新的自定义 Blog 路由添加在现有的 Default 路由之前。如果顺序相反,则将总是调用 Default 路由,而不会调用自定义路由。
自定义 Blog 路由匹配任何以 /Archive/ 开头的请求。所以,它匹配所有下列 URL:
/Archive/12-25-2009
/Archive/10-6-2004
/Archive/apple
自定义路由将进入的请求映射到名称为 Archive 的控制器并激活 Entry() 操作。当调用 Entry() 方法时,条目日期将作为名称为 entryDate 的参数进行传递。
可以将 Blog 自定义路由用在程序清单 7 中的控制器上。
程序清单 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(); } } }
请注意,程序清单 7 中的 Entry() 方法接受 DateTime 类型的参数。ASP.NET MVC Framework 可以智能地将 URL 中的条目日期自动转换为 DateTime 值。如果无法将 URL 中的条目日期转换为 DateTime,则将给出错误消息。
总结
本教程的目的是向读者简单介绍 URL 路由。首先,我们研究了新的 ASP.NET MVC 应用程序中的默认路由表。了解了默认路由如何将 URL 映射到控制器操作。
接下来,我们了解了如何创建自定义路由。学习了如何向表示博客条目的 Global.asax 文件添加自定义路由。我们讨论了如何将对博客条目的请求映射到名称为 ArchiveController 的控制器和名称为 Entry() 的控制器操作。