例子引入
先看看如下例子,你能完全明白吗?
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.Mvc;
6 using System.Web.Routing;
7
8 namespace MVCDemo
9 {
10 public class RouteConfig
11 {
12 public static void RegisterRoutes(RouteCollection routes)
13 {
14 routes.MapMvcAttributeRoutes();//特性路由
15
16 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//忽略资源文件
17
18 routes.MapRoute(
19 name: "Default",//路由名,唯一
20 url: "{controller}/{action}/{id}",//路由URL
21 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },//路由URL默认值
22 namespaces: new[] { "MVCDemo.Controllers" },//命名空间避免二义性
23 constraints: new { id = @"^\d*$" }//约束
24
25 );
26 }
27 }
28 }
注:该例子没有加入区域
1 URI、URL与URN
1.1 URI、URL和URN定义
URI(Uniform Resource Identifier)代表统一资源标识符,标识资源的字符串;
URL (Uniform Resource Locator)代表统一资源定位符,互联网上标准资源的地址;
URN(Uniform Resources Name)代表统一资源名称,互联网上资源的名称;
1.2 URI、URL和URN三者之间的关系图
1.3 对URI、URL和URN三者之间解析
本解析基于1.2 URI、URL和URN三者之间的关系图。
(1)从命名角度,URI标识资源且唯一,URL标识资源地址 ,URN标识资源名称;
(2)从数学关系:URI=URL+URN+URL∩URN;很容易看出,URL一定是URI,但URI不一定是URL,同理,URN一定是URI,但URI不一定是URN;
1.4 URL应具有特点
(1) 域名便于记忆和拼写;
(2) 简短;
(3) 便于输入;
(4) 可以反映出站点结构;
(5) 应该是“可破解的”,用户可以通过移除URL的末尾,进而到达更高层次的信息体系结构;
(6) 持久、不能改变
1.5 小结
通常情况下,URI代表同意资源标识符(Uniform Resource Identifier)。URI是标识了一个资源的字符串。从技术角度看,所有URL都是URI。W3C认为“URL是一个非正式的概念,但它非常有用:URL是URI的一种类型,它通过表示自身的主要访问机制来标识资源”,换句话说,URI是某种资源的标识符,而URL则为获取该资源提供了具体的信息。
注释:资源是一个抽象概念,既可以指一个文件,也可以指方法调用的结果或服务器上的一些其他内容。
2 路由概述(传统路由)
2.1 WebForm URL与Route URL
(1)WebForm中,对URL的传入请求通常映射到磁盘上的物理文件,如.aspx文件。例如对http://server/application/Product.aspx?id=4的请求映射到名为Products.aspx文件,该文件包含代码和标记用于呈现对浏览器的响应,一般请求示过程抽象如下:
(2)ASP.NET MVC中,通常地,URL映射并非映射到具体磁盘上的物理文件,这是基于ASP.NET路由特性,主要有两个过程,即URL映射和URL生成(接下来讲解)。在ASP.NET路由中,您可以定义URL模式,该模式包含在处理URL请求时使用的值的占位符。在运行时,运用程序名称后面的URL部分根据您所定义的URL模式分析为离散值。例如,在请求http://server/application/Products/show/beverages时,路由分析器可以将值Products、show和beverages传递给请求的处理程序。相反,在一个不由URL路由管理的请求中,/Products/show/beverages片段将被解释为运用程序中的一个文件的路径。
2.2 ASP.NET 路由与 URL 重写
ASP.NET 路由不同于其他 URL 重写方案。URL 重写通过在将请求发送到网页之前实际更改 URL 来处理传入请求。例如,一个使用 URL 重写的应用程序可能会将 URL 从 /Products/Widgets/ 更改为 /Products.aspx?id=4。此外,URL 重写通常没有相应的 API 来创建基于模式的 URL。在 URL 重写中,如果更改了 URL 模式,则必须手动更新包含原始 URL 的所有超链接。由于 ASP.NET 路由可以从 URL 提取值,所以处理传入请求时不更改 URL。如果必须创建一个 URL,则将参数值传递到为您生成 URL 的方法中。若要更改 URL 模式,请在某位置更改该模式,您在应用程序中创建的基于该模式的所有链接将自动使用新模式。
2.3 路由定义
A route is a URL pattern that is mapped to a handler. The handler can be a physical file, such as an .aspx file in a Web Forms application. A handler can also be a class that processes the request, such as a controller in an MVC application. To define a route, you create an instance of the Route class by specifying the URL pattern, the handler, and optionally a name for the route.
译文:路由是一种被映射到某个处理程序的URL模式。处理程序可能是一个物理文件,如在WebForms运用程序中的aspx文件。处理程序也可能是一个处理请求的类,如MVC应用程序中的控制器。要定义路由,您可以通过指定URL模式、处理程序和路径的名称来创建路由类的实例。
You add the route to the application by adding the Route object to the static Routes property of the RouteTable class. The Routes property is a RouteCollection object that stores all the routes for the application.You typically do not have to write code to add routes in an MVC application. Visual Studio project templates for MVC include preconfigured URL routes. These are defined in the MvcApplication class, which is defined in the Global.asax file.
译文:你可以通过将路由对象添加到RouteTable类的静态路由属性中的方式将路由添加到应用程序中。路由属性是一个为应用程序存储所有路由的路由对象。在MVC应用程序中,您通常不需要编写代码来添加路由。VS项目模板为MVC包含了预先配置的URL路由。这些都是在MvcApplication类中定义的,被定义在Global.asac 文件中。
2.4 URL Patterns(URL模式)
A URL pattern can contain literal values and variable placeholders (referred to as URL parameters). The literals and placeholders are located in segments of the URL which are delimited by the slash (/) character.
译文:URL模式可能包含文字值和变量占位符(称为URL参数)。文字和占位符位于URL的片段中,由斜杠(/)字符分隔。
When a request is made, the URL is parsed into segments and placeholders, and the variable values are provided to the request handler. This process is similar to the way the data in query strings is parsed and passed to the request handler. In both cases variable information is included in the URL and passed to the handler in the form of key-value pairs. For query strings both the keys and the values are in the URL. For routes, the keys are the placeholder names defined in the URL pattern, and only the values are in the URL.
译文:当发出请求时,URL被解析为片段和占位符,且变量值被提供给请求处理程序。这个过程类似于查询字符串中的数据被解析并传递给请求处理程序的方式。在这两种情况下,变量信息都包含在URL中,并以键值对的形式传递给处理程序。对于查询字符串,键和值都在URL中。对于路由,键是URL模式中定义的占位符名称,在URL中仅仅是值。
In a URL pattern, you define placeholders by enclosing them in braces ( { and } ). You can define more than one placeholder in a segment, but they must be separated by a literal value. For example, {language}-{country}/{action} is a valid route pattern. However, {language}{country}/{action} is not a valid pattern, because there is no literal value or delimiter between the placeholders. Therefore, routing cannot determine where to separate the value for the language placeholder from the value for the country placeholder.
译文:在URL模式中,通过将它们封装在括号(以及)中来定义占位符。您可以在一个段中定义多个占位符,但是必须用文字值分隔它们。例如,语言-国家/行动是一种有效的路线模式。然而,语言国家/action不是一个有效的模式,因为占位符之间没有文字值或分隔符。因此,路由不能决定将语言占位符的值与国家占位符的值分隔开。
The following table shows valid route patterns and examples of URL requests that match the patterns.
下表显示了有效的路由模式和与模式匹配的URL请求示例。
Typical URL Patterns in MVC Applications
译文:MVC运用程序中的经典模式
When a request is received, it is routed to the UrlRoutingModule object and then to the MvcHandler HTTP handler. The MvcHandler HTTP handler determines which controller to invoke by adding the suffix "Controller" to the controller value in the URL to determine the type name of the controller that will handle the request. The action value in the URL determines which action method to call.
译文:当接收到一个请求时,它被路由到UrlRoutingModule对象,然后发送到MvcHandler HTTP处理程序。MvcHandler HTTP处理程序通过向URL中的控制器值添加后缀“控制器”来确定要调用哪个控制器,以确定控制器的类型名称,该控制器将处理请求。URL中的操作值决定调用哪个操作方法。
For example, a URL that includes the URL path /Products is mapped to a controller named ProductsController. The value in the action parameter is the name of the action method that is called. A URL that includes the URL path /Products/show would result in a call to the Showmethod of the ProductsController class.
译文:例如,一个包含URL路径 /产品 的URL映射到一个名为ProductsController的控制器。action参数中的值是调用的操作方法的名称。一个包含URL路径 /产品/show 的URL会导致对ProductsController类的Showmethod的调用。
The following table shows the default URL patterns, and it shows examples of URL requests that are handled by the default routes.
译文:下表显示了默认的URL模式,它展示了由默认路由处理的URL请求的示例。
The route with the pattern {resource}.axd/{*pathInfo} is included to prevent requests for the Web resource files such as WebResource.axd or ScriptResource.axd from being passed to a controller.
For IIS 7.0, no file-name extension is needed. For IIS 6.0, you must add the .mvc file-name extension to the URL pattern, as in the following example:
译文:带有模式资源的路由axd/pathInfo,被用于防止Web资源文件的请求,例如WebResource,axd或ScriptResource传递到控制器。对于IIS 7.0,不需要任何文件名称扩展。对于IIS 6.0,您必须添加.mvc文件扩展名到URL模式中,如下面的例子:
如在VS2013使用MVC模板创建项目时,自动生成类RouteConfig.
2.5 Adding Routes to a Web Forms Application(添加路由到WebForm运用程序)
In a Web Forms application, you create routes by using the MapPageRoute(String, String, String) method of the RouteCollection class. The MapPageRoute method creates a Route object and adds it to the RouteCollection object. You specify properties for the Route object in parameters that you pass to the MapPageRoute method.
译文:在Web Forms应用程序中,您可以使用路由选择类的MapPageRoute(字符串、字符串、字符串)方法创建路由。MapPageRoute方法创建一个路由对象并将其添加到RouteCollection对象。您可以在传递给MapPageRoute方法的参数中指定路由对象的属性。
Typically, you add routes in a method that is called from the handler for the Application_Start event in the Global.asax file. This approach makes sure that the routes are available when the application starts. It also enables you to call the method directly when you unit-test the application. If you want to call a method directly when you unit-test the application, the method that registers the routes must be static (Shared in Visual Basic) and must have a RouteCollection parameter.
译文:通常地,在全局Global.asax文件中,您可以在一个叫做Application_Start 方法里添加路由。该方法确保当应用程序启动时,路由是可以使用的。它还使您可以在对应用程序进行单元测试时直接调用该方法。如果您想在对应用程序进行单元测试时直接调用方法,那么注册路由的方法必须是静态的(在Visual Basic中是共享的),并且必须具有一个路由参数。
The following example shows code from a Global.asax file that adds a Route object that defines two URL parameters named action and categoryName. URLs that have the specified pattern are directed to the physical page named Categories.aspx.
译文:下面的示例展示了来自.Globalasax文件的代码,该代码添加了一个路由对象,该对象定义了两个名为action和类别名称的URL参数。具有指定模式的url被定向到名为分类.aspx的物理页面。
1
2
3
4
5
6
7
8
9
10
11
|
protected
void
Application_Start(
object
sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
public
static
void
RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute(
""
,
"Category/{action}/{categoryName}"
,
"~/categoriespage.aspx"
);
}
|
2.6 Adding Routes to an MVC Application
If you adopt the MVC convention of implementing controllers by creating classes that derive from the ControllerBase class and giving them names that end with "Controller", you do not need to manually add routes in an MVC application. The preconfigured routes will invoke the action methods that you implement in the controller classes.
译文:如果您通过创建从控制器基类派生的类来实现控制器的MVC约定,并给它们以“控制器”结尾的名称,那么您就不需要在MVC应用程序中手动添加路由了。预配置的路由将调用您在控制器类中实现的操作方法。
If you want to add custom routes in an MVC application, you use the MapRoute(RouteCollection, String, String) method instead of the MapPageRoute(String, String, String) method.
译文:如果您想在MVC应用程序中添加自定义路由,您可以使用MapRoute(RouteCollection、String、String)方法,而不是MapPageRoute(字符串、字符串、字符串)方法。
The following example shows the code that creates default MVC routes in the Global.asax file, as defined in the Visual Studio project template for MVC applications.
译文:下面的例子展示了在全局中创建默认MVC路由的代码。asax文件,正如在Visual Studio项目模板中定义的MVC应用程序。
public class MvcApplication : 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);
}
}
2.7 Setting Default Values for URL Parameters(为URL参数设置默认值)
When you define a route, you can assign a default value for a parameter. The default value is used if a value for that parameter is not included in the URL. You set default values for a route by assigning a dictionary object to the Defaults property of the Route class. The following example shows how to add a route that has default values, by using the MapPageRoute(String, String, String, Boolean, RouteValueDictionary) method.
译文:当您定义一个路由时,您可以为一个参数指定一个默认值。如果该参数的值没有包含在URL中,则使用默认值。通过将dictionary对象分配给route类的默认属性,可以为路由设置默认值。下面的例子展示了如何通过使用MapPageRoute(字符串、字符串、字符串、布尔值、RouteValueDictionary)方法添加具有默认值的路由。
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("",
"Category/{action}/{categoryName}",
"~/categoriespage.aspx",
true,
new RouteValueDictionary
{{"categoryName", "food"}, {"action", "show"}});
}
When ASP.NET routing handles a URL request, the route definition shown in the example (with default values of food for categoryName and showfor action) produces the results that are listed in the following table.
For MVC applications, overloads of the RouteCollectionExtensions.MapRoute method, such as MapRoute(RouteCollection, String, String, Object, Object), enable you to specify defaults.
2.8 Handling a Variable Number of Segments in a URL Pattern(在URL模式中处理可变数量的段)
Sometimes you have to handle URL requests that contain a variable number of URL segments. When you define a route, you can specify that if a URL has more segments than there are in the pattern, the extra segments are considered to be part of the last segment. To handle additional segments in this manner you mark the last parameter with an asterisk (*). This is referred to as a catch-all parameter. A route with a catch-all parameter will also match URLs that do not contain any values for the last parameter. The following example shows a route pattern that matches an unknown number of segments.
译文:有时您必须处理包含一个可变数量的URL段的URL请求,其中。当您定义一个路由时,您可以指定,如果一个URL的片段比模式中有更多的段,那么额外的段被认为是最后一部分的一部分。要以这种方式处理额外的段,您可以用星号(*)标记最后一个参数。这被称为一个笼统的参数。一个包含所有参数的路由也将匹配不包含最后一个参数的任何值的url。下面的示例展示了一个匹配未知数量的段的路由模式。
/ query / { queryname } { * queryvalues }
When ASP.NET routing handles a URL request, the route definition shown in the example produces the results that are listed in the following table.
译文:当ASP.NET路由处理一个URL请求时,示例中所示的路由定义产生了下表中列出的结果。
2.9 Adding Constraints to Routes(为路由添加约束)
In addition to matching a URL request to a route definition by the number of parameters in the URL, you can specify that values in the parameters meet certain constraints. If a URL contains values that are outside the constraints for a route, that route is not used to handle the request. You add constraints to make sure that the URL parameters contain values that will work in your application.
译文:除了通过URL中参数的数量来匹配URL请求外,还可以指定参数中的值满足特定的约束条件。如果一个URL包含的值超出了路由的约束,那么该路由就不会被用于处理请求。您添加了一些约束,以确保URL参数包含在您的应用程序中工作的值。
Constraints are defined by using regular expressions or by using objects that implement the IRouteConstraint interface. When you add the route definition to the Routes collection, you add constraints by creating a RouteValueDictionary object that contains the verification test. The key in the dictionary identifies the parameter that the constraint applies to. The value in the dictionary can be either a string that represents a regular expression or an object that implements the IRouteConstraint interface.
译文:约束是通过使用正则表达式或使用实现IRouteConstraint接口的对象来定义的。当将路由定义添加到路由集合时,通过创建一个包含验证测试的RouteValueDictionary对象来添加约束。字典中的键标识约束应用到的参数。字典中的值可以是表示正则表达式的字符串,也可以是实现IRouteConstraint接口的对象。
If you provide a string, routing treats the string as a regular expression and checks whether the parameter value is valid by calling the IsMatch method of the Regex class. The regular expression is always treated as case-insensitive. For more information, see .NET Framework Regular Expressions.
译文:如果您提供一个字符串,那么路由将字符串作为一个正则表达式来处理,并通过调用Regex类的IsMatch方法检查参数值是否有效。正则表达式总是被视为不区分大小写的。要了解更多信息,请参阅。净框架正则表达式。
If you provide an IRouteConstraint object, ASP.NET routing checks whether the parameter value is valid by calling the Match method of the IRouteConstraint object. The Match method returns a Boolean value that indicates whether the parameter value is valid.
译文:如果你提供一个IRouteConstraint对象,ASP.NET 路由通过调用IRouteConstraint对象的匹配方法, 以此来检查参数值是否有效。Match方法返回一个布尔值,该值表示参数值是否有效。
The following example shows how to use the MapPageRoute method to create a route that has constraints that limit what values can be included in the locale and year parameters. (In an MVC application, you would use the MapRoute method.)
译文:下面的示例展示了如何使用MapPageRoute方法创建一条路径,该路由限制了地区和年参数中可以包含的值。(在MVC应用程序中,您将使用map路由方法。)
1 public static void RegisterRoutes(RouteCollection routes)
2 {
3 routes.MapPageRoute("",
4 "Category/{action}/{categoryName}",
5 "~/categoriespage.aspx",
6 true,
7 new RouteValueDictionary
8 {{"categoryName", "food"}, {"action", "show"}},
9 new RouteValueDictionary
10 {{"locale", "[a-z]{2}-[a-z]{2}"},{"year", @"\d{4}"}}
11 );
12 }
When routing handles a URL request, the route definition shown in the previous example produces the results that are listed in the following table.
2.10 Scenarios When Routing Is Not Applied(不应用路由时的场景)
Under some circumstances, ASP.NET routing does not handle a request even when is enabled for the Web site. This section describes some scenarios in which routing does not handle the request.
译文:在某些情况下,即使在Web站点启用时,ASP.NET 路由也不处理请求。本部分描述了一些场景,其中路由不处理请求。
A Physical File is Found that Matches the URL Pattern(找到与URL模式匹配的物理文件)
By default, routing does not handle requests that map to an existing physical file on the Web server. For example, a request for http://server/application/Products/Beverages/Coffee.aspx is not handled by routing if a physical file exists at Products/Beverages/Coffee.aspx. Routing does not handle the request even if it matches a defined pattern, such as {controller}/{action}/{id}.
译文:默认情况下,路由不处理映射到Web服务器上现有物理文件的请求。例如,如果存在 Products/Beverages/Coffee.aspx.物理文件,请求http://server/application/Products/Beverages/Coffee.aspx 不被路由处理。即使它与已定义的模式相匹配,路由不处理请求,例如控制器/动作/id。
If you want routing to handle all requests, even requests that point to files, you can override the default behavior by setting the RouteExistingFiles property of the RouteCollection object to true. When you set this value to true, all requests that match a defined pattern are handled by routing.
译文:如果您想要路由处理所有请求,甚至指向文件的请求,您可以通过设置RouteCollection对象的属性RouteExistingFiles为true, 以此来覆盖默认值。当您将这个值设置为true时,匹配定义模式的所有请求都由路由处理。
Routing Is Explicitly Disabled for a URL Pattern(为URL模式显式禁用路由)
You can also specify that routing should not handle certain URL requests. You prevent routing from handling certain requests by defining a route and specifying that the StopRoutingHandler class should be used to handle that pattern. When a request is handled by a StopRoutingHandler object, the StopRoutingHandler object blocks any additional processing of the request as a route. Instead, the request is processed as an ASP.NET page, Web service, or other ASP.NET endpoint. You can use the RouteCollection.Ignore method
译文:您还可以指定路由不应该处理某些URL请求。通过定义一条路由,并指定StopRoutingHandler类应该用于处理该模式,从而避免了处理某些请求的路由。当一个StopRoutingHandler对象处理请求时,StopRoutingHandler对象会阻塞请求作为路由的任何附加处理。相反,请求是作为ASP.NET 页面来处理的,网络页面,Web服务,或其他ASP.NET端点。您可以使用 RouteCollection.Ignore方法。
1 public static void RegisterRoutes(RouteCollection routes)
2 {
3 routes.Ignore("{resource}.axd/{*pathInfo}");
4 }
2.11 How URLs Are Matched to Routes(url如何与路由匹配)
When routing handles URL requests, it tries to match the URL of the request to a route. Matching a URL request to a route depends on all the following conditions:
译文:当路由处理URL请求时,它尝试将请求的URL与路由匹配。将URL请求匹配到路由取决于以下条件:
The route patterns that you have defined or the default route patterns, if any, that are included in your project type.
Any constraints that you have provided for a route.
Whether you have defined routing to handle requests that match a physical file.
For example, suppose that you add routes with the following patterns:
译文:例如,假设您添加了以下模式:
Route 1 is set to {controller}/{action}/{id}
译文: 路径1设置为{controller}/{action}/{id}
Route 2 is set to products/show/{id}
译文:路线2设置为 products/show/{id}
Route 2 will never handle a request because Route 1 is evaluated first, and it will always match requests that could also work for Route 2. A request for http://server/application/products/show/bikes seems to match Route 2 more closely, but it is handled by Route 1 with the following values:
controller is products.
action is show.
id is bikes.
译文:
路由2永远不会处理请求,因为路由1首先被匹配,它总是匹配可能在2号路径上工作的请求。请求http://server/application/products/show/bikes似乎比赛路线2更紧密,但它是由路线1以下值:
控制器products.
行动是show.
id是bikes.
Default values are used if a parameter is missing from the request. Therefore, they can cause a route to match a request that you did not expect. For example, suppose that you add routes with the following patterns:
Route 1: {report}/{year}/{month}, with default values for year and month.
Route 2: {report}/{year}, with a default value for year.
Route 2 will never handle a request. Route 1 might be intended for a monthly report, and Route 2 might be intended for an annual report. However, the default values in Route 1 mean that it will match any request that could also work for Route 2.
译文:
如果请求中缺少一个参数,则使用默认值。因此,它们可以导致一条匹配您没有预料到的请求的路由。例如,假设您添加了以下模式:
路线1:报告/年/月,年和月默认值。
路线2:报告/年,年默认值。
路由2永远不会处理请求。第1条可能是针对每月报告的,而路由2可能是针对年度报告的。但是,路由1中的默认值意味着它将匹配任何可能用于路由2的请求。
You can avoid ambiguity in the patterns by including constants, such as annual/{report}/{year} and monthly/{report}/{year}/{month}.
If a URL does not match any Route object that is defined in the RouteTable collection, ASP.NET routing does not process the request. Instead, processing is passed to an ASP.NET page, Web service, or other ASP.NET endpoint.
译文:您可以通过包含常量来避免模式中的歧义,例如 annual/{report}/{year} and monthly/{report}/{year}/{month}。
如果URL不匹配在RouteTable集合中定义的任何路由对象,ASP.NET路由不处理请求。相反,处理被传递给一个ASP.NET Page ,Web服务,或其他ASP.NET端点。
2.12 路由二义性
只在同一个解决方案中,存在两个以及以上相同控制器下的相同action,当URL请求时,会出现二义性。
二义性Demo目录结构
RouteConfig.cs
/Controllers/RouteDemo
/Controllers/NewFolder1/RouteDemo
测试结果
3 路由概述(特性路由)
特性路由是在ASP.NET MVC 5中新增的,传统路由ASP.NET MVC 1中就有了。
从内容上来看,特性路由的内容与传统路由差不多,同样有路由URL、路由值、控制器路由、路由约束和路由默认值等。鉴于篇幅限制,在这里就简单的概述一下,不作详细论述,后期有时间或者有朋友需要,再论述。
定义:特性路由就是将路由URL定义在控制器上或控制器内的方法上,而不像传统路由将路由URL定义在RouteConfig.cs中。对比如下
3 路由生成URL
路由两个重要职责:匹配传入的URL请求和构造与特定路由对应的URL,概括之匹配URL和构造URL。在生成URL时,生成URL的情趣应该首先与选择用来生成URL的路由相匹配,这样路由就可以在处理传入或传出的URL时成为完整的双向系统。原则上,开发人员应该提供一组路由值,以便路由系统从中选中第一个能够匹配URL的路由。
3.1 URL生成的高层系概述
路由的核心是一个非常简单的算法,该算法基于一个由RouteCollection类和RouteBase类组成的简单抽象对象。可以采用多种方法来生成URL,但这些方法都以调用RouteCollection.GetVirtualPath的一个重载方法而结束。RouteCollection.GetVirtulPath方法公有两个重载版本,下面的代码展示它们的方法签名:
1 public VirtualPathData GetVirtualPath(RequestContext requestContex,RouteValueDictionary values)
2
3 public VirtualPathData GetVirtualPath(RequestContext requestContex,string name,RouteValueDictionary values)
第一个重载版本接受当前的RequestContext,以及由用户指定的路由值(字典)。
(1)路由集合通过RouteBase.GetVirtualPath方法遍历每个路由并访问:“可以生成给定参数的URL吗”,这个过程类似于在路由与传入请求匹配时所运用的匹配逻辑。
(2)如果一个路由可以应答上面的问题(即匹配),那么它就会返回一个包含了URL的VirTualPathData实例以及其他匹配的信息。否则,它就返回空值,路由机制移向列表中的下一个路由。
第二个重载接受三个参数,其中第二个参数是路由名称。在路由集合中路由名称是唯一的,也就是说,没有两个不同的路由具有相同的名称。当指定了路由名称时,路由集合就不需要循环遍历每个路由,相反,它可以立即找到指定名称的路由,并移向上面的步骤(2)。如果找到的路由不能匹配指定的参数,该方法就会返回空值,并且不再匹配其他路由。
3.2 URL生成详解
(1)开发人员调用像Html.ActionLink或Url.Action之类的方法,这些方法反过来再调用RouteCollection.GetVirtualPath方法,并向它传递一个RequestContext对象、一个包含值的字典以及用来选择生成URL的路由名称(可选参数)。
(2)路由机制查看要求的路由参数(即没有提供路由参数的默认值),并确保提供的路由值字典为每一个要求的参数提供一个值,否则,URL生成程序就会立即停止,并返回空值。
(3)一些路由可能包含没有对应路由参数的默认值。如路由可能为category键提供默认值“pastries”,但是cateory不是路由URL的一个参数,这种情况下,如果用户传入的路由值字典为category提供了一个值,那么该值必须匹配category的默认值。
(4)然后路由系统应用路由约束。
(5)路由匹配成!现在可以通过查看每一个路由参数,并尝试利用字典中的对应值填充相应参数,进而生成URL。
可以概括为如下流程图:
4 路由绑定到操作
在这一章节,主要分析URL绑定到控制器操作的底层细节,分析底层原理,理解ASP.NET请求管道。注意,目前路由不仅仅只是ASP.NET MVC的一个特性了,它已经超过这个范围,如ASP.NET Dynamic Data。路由既不包括MVC的内部知识,也不依赖于MVC。
4.1 高层次请求的路由管道
当ASP.NET 处理请求时,路由管道主要由以下几步组成:
(1)UrlRoutingModule尝试使用在RouteTable中注册的路由匹配当前请求。
(2)如果RouteTable中有一个路由成功匹配,路由模块就会从匹配成功的路由中获取IRouteHandler接口对象。
(3)路由模块调用IRouteHandler接口的GetHandler方法,并返回用来处理请求的IHttpHandler对象。
(4)调用HTTP处理程序中的ProcessRequest方法,然后把要处理的请求传递给它
(5)在ASP.NET MVC中,IRouteHandler是MvcRouteHandler类的一个实例,MvcRouteHandler转而返回一个实现了IHttpHandler接口的MvcHandler对象。返回的MvcHandler对象主要用来实例化控制器,并调 用该实例化的控制器上的操作方法。
4.2 路由数据
调用GetRouteData方法会返回RouteData的一个实例。RouteData中包含了关于匹配请求的路由信息。
如URL:{Controller}/{action}/{id}。当请求/albums/list/123传入时,该路由就会尝试匹配传入的请求,如果匹配成功,它就创建一个字典,其中包含了从URL中解析出的信息。确切地讲,路由还会向Values字典中为URL中的每个路由参数添加一个键;对于传统路由{Controller}/{action}/{id},Values字典中应该至少包含三个键,分别是Controller,action和id,如果传入的URL是对/albums/list/123的请求,路由就会解析该请求的URL,并为字典的键提供值。本例中,字典中“Controller”键的值为albums,"action"键的值为“list”,"id"键的值是“123”;对于特性路由MVC使用DataTokens字典来存储更精确的信息,而不是操作名称字符串。具体来说,它包含一个操作描述符列表,这些描述符直接指向路由匹配时可能使用的操作方法。对于控制器级别的特性路由,列表中将有不止一个操作。在整个MVC中都有用到的RequestContext的RouteData属性保存着外界路由值。
5 路由调试
使用RouteDebugger调试,启用RouteDebugger后,它会用一个DebuggerRouteHandler替换所有路由处理程序,DebugRouteHandler截获所有传入的请求,并查询路由表中的每一个路由,以便在页面底部显示路由的诊断数据和参数。为使用RouteDebugger,只需在VS的Package Manager Console窗口中使用NuGet安装即可,命令Install-Package routedebugger.。RouteDebugger包在添加Route Debugger程序集的同时。也在web.config文件的appSettings节点中添加一个设置,用来开启或禁用路由调试。
" RouteDebugger:Enable" value="true'>
只要启用RouteDebugger,它就显示从(在地址栏中)当前请求URL中提取的路由数据。如此,可以在地址栏中输入各种URL,并查看输入的URL能与哪个路由匹配,在页面底部,它还会展示一个包含应用程序定义的所用路由列表,这样可以查看定义的哪个路由能够与当前URL相匹配。
安装教程如下:
视图=>其他窗口=>程序包管理控制台
在窗口中输入:Install-Package routedebugger
或者也可以使用NuGet很方便的安装RouteDebugger,在项目上面右键-"Manage NuGet Packages"-"Online"输入"RouteDebugger"然后"Install".
当然, 你也可以自己下载RouteDebugger.dll, 引用到web项目中, 然后手动在web.config中加入
" RouteDebugger:Enabled" value="true" />
测试结果
RouteConfig.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.Mvc;
6 using System.Web.Routing;
7
8 namespace MVCDemo
9 {
10 public class RouteConfig
11 {
12 public static void RegisterRoutes(RouteCollection routes)
13 {
14 routes.MapMvcAttributeRoutes();//
15
16 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
17
18 routes.MapRoute(
19 name: "Default",
20 url: "{controller}/{action}/{id}",
21 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
22 );
23 }
24 }
25 }
RouteDemoController
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.Mvc;
6
7 namespace MVCDemo.Controllers
8 {
9 public class RouteDemoController : Controller
10 {
11 //
12 // GET: /RouteDemo/
13 public ActionResult Index()
14 {
15 return View();
16 }
17 }
18 }
Index
1 @inherits System.Web.Mvc.WebViewPage
2
3 RouteDebugger调试
6 与路由相关的关键命名空间和类
6.1 路由涉及的命名空间
6.2 Class Reference( 路由涉及到的关键类)