本文章将关注定义路由,并使用它们去处理URL,使用户能够到达控制器和动作。
文章非常长,可以对路由机制有较初步的了解。首先创建示例项目,项目名为UrlAndRoutes,如下图所示:
然后是创建示例控制器和示例视图,有三个控制器,分别为Admin控制器,Home控制器,Customer控制器,一个命名为ActionName示例视图。这三个控制器都返回ActionName视图。代码如下图所示:
namespace UrlsAndRoutes.Controllers
{
public class AdminController : Controller
{
// GET: Admin
public ActionResult Index()
{
ViewBag.Controller = "Admin";
ViewBag.Action = "Index";
return View("ActionName");
}
}
}
namespace UrlsAndRoutes.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
ViewBag.Controller = "Home";
ViewBag.Action = "Index";
return View("ActionName");
}
}
}
namespace UrlsAndRoutes.Controllers
{
public class CustomerController : Controller
{
// GET: Customer
public ActionResult Index()
{
ViewBag.Controller = "Customer";
ViewBag.Action = "Index";
return View("ActionName");
}
public ActionResult List()
{
ViewBag.Controller = "Customer";
ViewBag.Action = "List";
return View("ActionName");
}
}
}
ActionName.cshtml视图的代码很简单,就是返回调用它的control和ActionName的名称,如下图所示:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>ActionName</title>
</head>
<body>
<div> the control is @ViewBag.Controller</div>
<div> the action is @ViewBag.Action</div>
</body>
</html>
测试示例代码,启动默认路由,显示页面没有问题,如下图所示:
URL模式简介
路由系统由一组路由来实现它的功能。这些路由共同组成了应用程序的URL架构。这种URL架构是应用程序能够识别并能对之做出响应的一组URL。
URL可以分成几个片段。除主机名和查询字符串之外,这些URL的组成部分都用"/"字符进行分割,如下所示:
第一个片段含有单词“Admin”,第二个片段含有单词“Index”。很显然,第一个片段和控制器有关,第二个片段和动作有关。以下是做这件事的一个URL模式:{ controller } / { action }
当处理一个输入请求时,路由系统的工作是将这个请求URL与一个模式进行匹配,然后从此URL为这个模式中定义的片段变量提取出相应的值。片段变量用花括号 “ { ” 和 “ } ”字符表示。上述示例模式有两个片段变量,其名称分别为“controller”和“action”,因此,controller片段的值是Admin,而action片段的值是Index。
所谓“与一个模式”匹配是指,一个MVC应用程序通常会有几条路由,而路由系统会把输入URL逐一与每条路由的URL模式相比较,直到能找到一条匹配的路由为止。
默认情况下,一个URL模式将匹配具有正确片段的的任何URL。例如,模式{controller} / {action}将匹配任何具有两个片段的URL,如下图所示:
请求URL | 片段变量 |
http://mysite.com/Admin/Index | controller = Admin action = Index |
http://mysite.com/Index/Admin | controller = Index action = Admin |
http://mysite.com/Apples/Orange | controller = Apples action = Orange |
http://mystie.com/Admin | 不匹配,片段太少 |
http://mysite/Admin/Index/Soccer | 不匹配,片段太多 |
上图突出了URL模式的两个关键行为:
1、URL模式是保守的,因此只匹配与模式具有相同片段的URL。你可以从表中第四个,第五个例子看到这种情况(片段数不同就是不匹配)。
2、URL模式是宽松的,如果一个URL正好是具有正确的片段数,该模式就用来为片段变量提取值,而不管这个值是什么。
创建并注册一条简单路由
路由是在RouteConfig.cs文件中进行定义的,该文件位于项目的App_start文件夹中。 代码如下图所示:
namespace UrlsAndRoutes
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
先删掉上图中RegisterRoutes方法中其他代码,以便更加关注重点,如下图所示:
namespace UrlsAndRoutes
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("MyRoute","{controller}/{action}");
}
}
}
运行代码,可以看到如下报错界面:
但是如果导航到一个与{controller} / {action } 匹配的URL时,将看到正确显示。如下图,就导航到了/Home/Index:
定义默认值
当请求应用程序的默认值时,出现错误的原因是它不匹配已经定义的路由。前面说过,URL是保守的,他们只匹配指定片段的URL。改变这种行为的一个方式是使用默认值。修改RegisterRoutes方法如下图所示:
namespace UrlsAndRoutes
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("MyRoute","{controller}/{action}",
new { action = "Index"});
}
}
}
上述代码中为action片段提供了一个默认值,该路由也将匹配单片段URL。当处理单片段URL时,路由系统将从唯一的URL片段中提取controller的值,并对action变量使用默认值。于是,可以请求http://localhost:29802/home