http://www.cnblogs.com/artech/archive/2012/03/20/aspnet-routing-02.html
RouteTable<System.Web.Routing.RouteTable>
Routes<RouteCollection>
MapPageRoute()(其实就是添加一个Route:RouteBase对象)//可将一个ASPX页面映射到路由虚拟路径
GetRouteData()//返回有关集合中与指定值匹配的路由的信息。
GetVirtualPath()//如果具有指定的上下文和参数值,则返回与路由关联的 URL 路径的相关信息。
Ignore() //定义不需检查是否匹配路由的 URL 模式。
RouteExistingFiles //对已存在的文件和文件夹是否启用路由,大家千万不要忘记还有文件夹这个检查,同时文件和文件夹的检查结果默认是启用了缓存的。
AppendTrailingSlash //获取或设置指示的 value 尾部的反斜杠是否添加,在虚拟路径进行规范化时。
LowercaseUrls //获取或设置指示的 value URL 是否转换为小写,在虚拟路径进行规范化时。
RouteBase //匹配路由表类的基类 子类Route
GetRouteData //匹配成功返回一个RouteData
GetVirtualPath //如果匹配成功返回一个 替换了URL模板 的封装对象VirtualPathData
RouteData (Page.RouteData只读对象)
Values<RouteValueDictionary>//保存路由变量的字典 一般有"controller"和"action"KEY
DataTokens //附加到路由对象上的自定义变量 额外变量 , 一般用于存取命名空间 对应的Key为"Namespace"
/{filename}/{*pathinfo}
/abc/ccc/ddd DataTokens (ccc/ddd)
IRouteHandler
GetHttpHandler
约束 正则表达式/IRouteConstraint 接口
IRouteConstraint 实现类HttpMethodConstraint
ASP.NET路由系统的应用编程接口中定义了如下一个实现了IRouteConstraint接口的HttpMethodConstraint类型。顾名思义,HttpMethodConstraint提供针对HTTP方法(GET、POST、PUT、DELTE等)的约束。我们可以通过HttpMethodConstraint为路由对象设置一个允许的HTTP方法列表,只有方法名称在这个指定的列表中的HTTP请求才允许被路由。这个被允许被路由的HTTP方法列表对于HttpMethodConstraint的只读属性AllowedMethods,并在构造函数中初始化。
1: public class Global : System.Web.HttpApplication
2: {
3: protected void Application_Start(objectsender, EventArgs e)
4: {
5: var defaults = newRouteValueDictionary { { "areacode", "010" }, {"days", 2 } };
6: var constaints = newRouteValueDictionary { { "areacode", @"0\d{2,3}" }, {"days", @"[1-3]{1}" }, { "httpMethod", newHttpMethodConstraint("POST") } };
7: var dataTokens = newRouteValueDictionary { { "defaultCity", "BeiJing" }, {"defaultDays", 2 } };
8:
9: RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,constaints, dataTokens);
10: }
11: }
对现有文件的路由
var defaults = new RouteValueDictionary { { "areacode","010" }, { "days", 2 }};
var dataTokens = new RouteValueDictionary { { "defaultCity","BeiJing" }, { "defaultDays", 2 } };
RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,null, dataTokens);
注册路由忽略地址
如果将代表全局路由表的RouteTable的静态属性Routes的RouteExistingFiles属性设置为True,意味着ASP.NET针对所有抵达的请求都一视同仁,都按照注册的路由表进行注册。都按照注册的路由表进行注册,但这会代码一些问题。CSS文件的请求也被路由 直接请求文件变成了 请求weather.aspx的路由。
我们可以通过调用RouteCollection的Igore方法来注册一些需要让路由系统忽略的URL模板
RouteTable.Routes.RouteExistingFiles = true;
RouteTable.Routes.Ignore("{filename}.js/{*pathInfo}");
直接添加路由对象
var defaults = new RouteValueDictionary { { "areacode","010" }, { "days", 2 }};
var dataTokens = new RouteValueDictionary { { "defaultCity","BeiJing" }, { "defaultDays", 2 } };
1.
RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,null, dataTokens);
2.
Route route = new Route("{areacode}/{days}", defaults,constaints, dataTokens, new PageRouteHandler("~/weather.aspx",false));
RouteTable.Routes.Add("default", route);
根据路由规则生成URL GetVirtualPath()
1: public partial class Weather : Page
2: {
3: protected void Page_Load(object sender,EventArgs e)
4: {
5: RouteData routeData = newRouteData();
6: routeData.Values.Add("areaCode","0512");
7: routeData.Values.Add("days","1");
8: RequestContext requestContext= new RequestContext();
9: requestContext.HttpContext =new HttpContextWrapper(HttpContext.Current);
10: requestContext.RouteData =routeData;
12: RouteValueDictionary values = newRouteValueDictionary();
13: values.Add("areaCode","028");
14: values.Add("days","3");
16: Response.Write(RouteTable.Routes.GetVirtualPath(null,null).VirtualPath +"<br/>");
17: Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath + "<br/>");
18: Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath + "<br/>");
19: }
20: }
从上面的代码片断我们可以看到:第一次调用GetVirtualPath方法传输的requestContext和values参数均为Null;第二次则指定了一个手工创建的RequestContext对象,其RouteData的Values属性具有两个变量(areaCode=0512;days=1),而values参数依然为Null;第三次我们同时为参数requestContext和values指定了具体的对象,而后者包含两个参数(areaCode=028;days=3)。在浏览器上访问Weather.aspx页面会得到如下图所示的3个URL。这充分证实了上面提到的关于变量选择优先级的结论。
路由映射
我们手工创建了一个HttpRequest和HttpResponse对象,HttpRequest的请求的地址为“http://localhost:3721/0512/3”(3721是本Web应用对应的端口号)。根据这两个对象创建了HttpContext对象,并以此创建一个HttpContextWrapper对象。最终我们将其作为参数调用RouteTable的Routes属性的GetRouteData方法并返回。这个方法实际上就是模拟注册的路由表针对相对地址为“/0512/3”的HTTP请求的路由处理。
1: public partial class Default : System.Web.UI.Page
2: {
3: private RouteData routeData;
4: public RouteData GetRouteData()
5: {
6: if (null != routeData)
7: {
8: return routeData;
9: }
10: HttpRequest request = new HttpRequest("default.aspx", "http://localhost:3721/0512/3", null);
11: HttpResponse response = new HttpResponse(new StringWriter());
12: HttpContext context = new HttpContext(request, response);
13: HttpContextBase contextWrapper = new HttpContextWrapper(context);
14: return routeData = RouteTable.Routes.GetRouteData(contextWrapper);
15: }
16: }
我们通过调用RouteTable的Routes属性的MapRoute方法注册了一个采用“ {areacode}/{days}”作为URL模板的路由对象,并指定了默认变量、约束和命名空间列表。
1: public class Global : System.Web.HttpApplication
2: {
3: protected void Application_Start(object sender, EventArgs e)
4: {
5: object defaults = new { areacode = "010", days = 2, defaultCity="BeiJing", defaultDays=2};
6: object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}"};
7: string[] namespaces = new string[] { "Artech.Web.Mvc", "Artech.Web.Mvc.Html" };
8: RouteTable.Routes.MapRoute("default", "{areacode}/{days}", defaults, constraints, namespaces);
9: }
10: }
- 与调用RouteCollection的MapPateRoute方法进行路由映射不同的是,这个得到的RouteData对象的RouteHandler属性是一个System.Web.Mvc.MvcRouteHandler对象。
- 在MapRoute方法中通过defaults参数指定的两个与URL匹配无关的变量(defaultCity=BeiJing;defaultDays=2)体现在RouteData的Values属性中。这意味着如果我们没有在URL模板中为Controller和Action的名称定义相应的变量({controller}和{action}),也可以将它们定义成默认变量。
- DataTokens属性中包含一个Key值为Namespaces值为字符数组的元素,我们不难猜出它对应着我们指定的命名空间列表。
UrlParameter.Optional
在此默认路由中,controller 设置为“Home”,action 设置为“Index”,而 id 设置为 Optional。 如果没有为 id 传递任何值,则 MvcHandler 类将忽略 id 参数(RouteData.Values中不包含ID参数)。
Area的路由映射
* 1、新建 Area:右键 -> Add -> Area...* 2、继承 AreaRegistration,配置对应此 Area 的路由
* 3、在 Global 中通过 AreaRegistration.RegisterAllAreas(); 注册此 Area
* 4、有了 Area,就一定要配置路由的命名空间
AreaRegistration与AreaRegistrationContext
AreaRegistration定义了两个抽象的静态RegisterAllAreas方法重载,参数state用于传递给具体AreaRegistration的数据。当RegisterAllArea方法执行的时候,它先 遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到的编译Web应用所使用的程序集,通过反射得到所有实现了接口IController的类型,并通过反射创建相应的AreaRegistration对象。对于每个AreaRegistration对象,一个 AreaRegistrationContext对象被创建出来并作为参数调用它们的RegisterArea方法。AreaRegistration是一个抽象类,抽象只读属性AreaName返回当前Area的名称,而抽象方法RegisterArea用于实现基于当前Area的路由注册。
1: public abstract class AreaRegistration
2: {
3: public static void RegisterAllAreas();
4: public static void RegisterAllAreas(object state);
5:
6: public abstract void RegisterArea(AreaRegistrationContext context);
7: public abstract string AreaName { get; }
8: }
AreaRegistration定义了两个抽象的静态RegisterAllAreas方法重载,参数state用于传递给具体AreaRegistration的数据。当RegisterAllArea方法执行的时候,它先遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到的编译Web应用所使用的程序集,通过反射得到所有实现了接口IController的类型,并通过反射创建相应的AreaRegistration对象。对于每个AreaRegistration对象,一个AreaRegistrationContext对象被创建出来并作为参数调用它们的RegisterArea方法。
如下面的代码片断所示,AreaRegistrationContext的只读属性AreaName表示Area的名称,属性Routes是一个代表路由表的RouteCollection对象,而State是一个用户自定义对象,它们均通过构造函数进行初始化。具体来说,对于最初通过调用AreaRegistration的静态方法RegisterAllAreas创建的AreaRegistrationContext对象,AreaName来源于当前AreaRegistration对象的同名属性,Routes则对应着RouteTable的静态属性Routes表示的全局路由表,而在调用RegisterAllAreas方法指定的参数(state)作为AreaRegistrationContext对象的State参数。
1: public class AreaRegistrationContext
2: {
3: public AreaRegistrationContext(string areaName, RouteCollection routes);
4: public AreaRegistrationContext(string areaName, RouteCollection routes, object state);
5:
6: public Route MapRoute(string name, string url);
7: public Route MapRoute(string name, string url, object defaults);
8: public Route MapRoute(string name, string url, string[] namespaces);
9: public Route MapRoute(string name, string url, object defaults, object constraints);
10: public Route MapRoute(string name, string url, object defaults, string[] namespaces);
11: public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces);
12:
13: public string AreaName { get; }
14: public RouteCollection Routes { get; }
15: public object State { get; }
16: public ICollection<string> Namespaces { get; }
17: }
AreaRegistrationContext的只读属性Namespaces表示一组优先匹配的命名空间(当多个同名的Controller类型定义在不同的命名空间中)。当针对某个具体AreaRegistration的AreaRegistrationContext被创建的时候,如果AreaRegistration类型具有命名空间,那么会在这个命名空间基础上添加“.*”后缀并添加到Namespaces集合中。换言之,对于多个定义在不同命名空间中的同名Controller类型,会优先选择包含在当前AreaRegistration命名空间下的Controller。
AreaRegistrationContext定义了一系列的MapRoute用于进行路由映射注册,方法的使用以及参数的含义与定义在RouteCollectionExtensions类型中的同名扩展方法一致。在这里需要特别指出的是,如果MapRoute方法没有指定命名空间,则通过属性Namespaces表示的命名空间列表会被使用;反之,该属性中包含的命名空间被直接忽略。
当我们通过Visual Studio的ASP.NET MVC项目模版创建一个Web应用的时候,在的Global.asax文件中会生成如下的代码通过调用AreaRegistration的静态方法RegisterAllAreas实现对所有Area的注册,也就是说针对所有Area的注册发生在应用启动的时候。
public override void RegisterArea(AreaRegistrationContext context)
{
// 在 Area 中配置路由的时候,要设置命名空间(即本例中的第 4 个参数)
context.MapRoute(
"AsynchronousController_default",
"AsynchronousController/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "MVC20.Areas.AsynchronousController.Controllers" }
);
}
1: public class MvcApplication : System.Web.HttpApplication
2: {
3: protected void Application_Start()
4: {
5: AreaRegistration.RegisterAllAreas();
6: }
7: }
如果调用AreaRegistrationContext的MapRoute方法是显式指定了命名空间,或者说对应的AreaRegistration定义在某个命名空间下,这个名称为“UseNamespaceFallback”的DataToken元素的值为False;反之为True。进一步来说,如果在调用MapRoute方法时指定了命名空间列表,那么AreaRegistration类型所示在命名空间会被忽略。也就是说,后者是前者的一个后备,前者具有更高的优先级。
系统自动生成的 AdminAreaRegistration 类继承至抽象类 AreaRegistration,并重写了 AreaName 属性和 RegisterArea 方法。在 RegisterArea 方法中它为我们定义了一个默认路由,我们也可在这个方法中定义专属于Admin Area的的其他路由。但有一点要注意,在这如果要给路由起名字,一定要确保它和整个应用程序不一样。
AreaRegistrationContext 类的 MapRoute 方法和 RouteCollection 类的 MapRoute 方法的使用是一样的,只是 AreaRegistrationContext 类限制了注册的路由只会去匹配当前 Area 的 controller,所以,如果你把在 Area 中添加的 controller 的默认命名空间改了,路由系统将找不到这个controller 。
namespace MvcApplication1.Areas.Admin //系统自动生成
http://www.cnblogs.com/willick/p/3331519.html
Areas之间的调用
ASP.NET MVC中,经常需要在控制层的不同方法之间进行互相调用。如果没特别指定,则默认为同一个area中的action方法和控制器之间的调用。如果需要在不同的area之间进行互相调用,可以使用如下方法:
<%= Html.ActionLink("Main Area", "Index", "Home", new { area = "" }, null)%>
<br /><br />
<%= Html.ActionLink("Blog Area", "Index", "Home", new { area = "Blog" }, null)%>
<br /><br />
<%= Html.ActionLink("Help Desk Area", "Index", "Home", new { area = "HelpDesk" }, null)%>
<br /><br />
<%= Html.ActionLink("Shopping Area", "Index", "Home", new { area = "Shopping" }, null)%
可以看到,上面使用了ActionLink()方法产生链接,注意其中的第4个参数,使用new {area=“Blog”}这样形式的参数,指出调用的是哪一个area中action方法。
使用RedirectToAction
同样,我们经常要在某个area中的action方法去调用另外一个area方法中的action,这个时候要如何做呢?代码如下:
public ActionResult Index()
{
return RedirectToAction("Index", "Home", new { Area = "HelpDesk" });
}
1.理解默认路由表
1: public static class RouteCollectionExtensions
2: {
3: //其他成员
4: publicstaticvoid IgnoreRoute(this RouteCollection routes,string url);
5: public static void IgnoreRoute(this RouteCollection routes,string url,object constraints);
6:
7: public static Route MapRoute(this RouteCollection routes,string name,string url);
8: public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults);
9: public static Route MapRoute(this RouteCollection routes,string name,string url,string[] namespaces);
10: public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,object constraints);
11: public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,string[] namespaces);
12: public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,object constraints,string[] namespaces);
13: }
一、 实例演示:注册路由映射与查看路由信息
1: public partial class Default : System.Web.UI.Page
2: {
3: private RouteData routeData;
4: public RouteData GetRouteData()
5: {
6: if (null != routeData)
7: {
8: return routeData;
9: }
10: HttpRequest request =new HttpRequest("default.aspx","http://localhost:3721/0512/3",null);
11: HttpResponse response =new HttpResponse(new StringWriter());
12: HttpContext context =newHttpContext(request, response);
13: HttpContextBase contextWrapper =new HttpContextWrapper(context);
14: return routeData =RouteTable.Routes.GetRouteData(contextWrapper);
15: }
16: }
protected void Application_Start(object sender, EventArgse)
4: {
5: object defaults = new { areacode = "010", days = 2, defaultCity="BeiJing", defaultDays=2};
6: object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}"};
7: string[] namespaces = new string[] { "Artech.Web.Mvc", "Artech.Web.Mvc.Html" };
8: RouteTable.Routes.MapRoute("default","{areacode}/{days}", defaults, constraints, namespaces);
9: }
*.asp
<%foreach(var variable in GetRouteData().Values)
{%>
<li>
<%=variable.Key%>=<%=variable.Value%></li>
<% }%>
结果
Route: | System.Web.Routing.Route |
RouteHandler: | System.Web.Mvc.MvcRouteHandler |
Values: |
|
DataTokens: |
|
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller= "Home", action = "Index", id = "" } // Parameter defaults
);
/Home/Index/3
默认的路由将这个URL映射为下面的参数:
Controller= Home
Action= Index
id =3
/Home
由于Default路由参数的默认值,输入这个URL将会调用代码清单2中的HomeController类的Index()方法。
可空参数的Index动作
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResultIndex(int? id)
{
return View();
}
}
}
在代码清单4中,Index()方法拥有一个整数参数。因为这个参数是一个可空参数(可以拥有Null值),因此可以调用Index()而不会引发错误。
使用URL /Home 调用代码清单5中的Index()方法将会引发一个异常,因为Id参数并非一个可空参数。
2.创建自定义路由
routes.MapRoute(
"Blog", // Route name
"Archive/{entryDate}", // URL with parameters
new { controller= "Archive",action = "Entry" } // Parameter defaults
);
3.创建路由约束
9 : object defaults =new { areacode ="010", days = 2, defaultCity ="BeiJing", defaultDays = 2 };
10: object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}" };
11: context.MapRoute("weatherDefault","weather/{areacode}/{days}", defaults, constraints);
你可以使用路由约束来限制匹配特定路由的浏览器请求。可以使用正则表达式来指定一个路由约束。
举个例子,假设你已经在Global.asax文件中定义了一个路由。
代码清单1 - Global.asax.cs
routes.MapRoute(
"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
routes.MapRoute(
"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. 创建一个自定义路由约束
你可以通过实现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,
RouteValueDictionaryvalues,
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的请求将会失败。
routes.MapRoute(
"Admin",
"Admin/{action}",
new {controller="Admin"},
new {isLocal=new LocalhostConstraint()}
);
Localhost约束使用在了Admin路由的定义中。这个路由不会被远程浏览器请求所匹配。然而,应该意识到定义在Global.asax中的其他路由可能会匹配相同的请求。理解这一点很重要:约束阻止了特定路由匹配某一请求,而不是所有定义在Global.asax文件中的路由。
MVC区域
在路由没有指定名称空间的情况下,很容易产生二义性,即两个同名的控制器同时匹配一个路由,我们可以通过在项目中使用唯一的控制器名称来防止二义性,如下:对特定的路由指定一组用来定位控制器的名称空间
routes.MapRoute{"Default","{controller}/{action}/{id}",new{controller="Home",action="Index",id=""},new []{"AreasWeb.Controllers"});
第四个参数指定一个名称空间数组
9.2.5Catch-All 参数
Catch-all参数允许路由匹配具有任意数量的段的URL,参数中的值是不含查询字符串的URL剩余部分
如:
routes.MapRoute("CatchAllRoute","/query/{query-name}/{*extrastuff}");
匹配如下:
URL 参数值
/query/select/a/b/cextrastuff="a/b/c"
/query/select/a/b/c/extrastuff="a/b/c"
/query/select/extrastuff=""(路由仍然匹配,“catch-all捕获了空字符串
9.2.6 段中的多个URL参数
路由的URL中可以存在多个参数,如下:
l {title}-{artist}
l Album{title}and{artist}
l {filename}.{ext}
为避免二义性,参数不能临近,
如下:均为无效的URL
l {title}{atrist}
lDownLoad{filename}{ext}
路由URL在与传入的请求匹配时,它的字面值与请求精确匹配,而其中的URL参数是贪婪匹配,路由使每个URL参数尽可能的匹配更多的文本
如下:多参数路由匹配
路由URL 请求的URL 路由数据的结果
{finename}.{ext}/Foo.xml.aspx filename="Foo.xml" ext="aspx"
My{title}-{cat}/MyHouser-dwelling title="Houser" ext="dwelling"
{foo}xyz{bar}/xyzxyzxyzblah foo="xyzxyz" bar="blah"
9.2.7StopRoutingHandler和IgnoreRoute
默认情况下,路由机制将忽略那些映射到磁盘物理文件的请求。
方法如下:
public static voidRegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//第一种方法
routes.Add(newRoute("{resource}.axd/{@pathInfo}",new StopRoutingHandler()));//第二种方法
}
溢出参数
指在URL生成过程中使用、但是在路由定义中却没有指定的路由值。具体指的是路由的URL、默认的字典和约束字典
如:路由定义如下:
routes.MapRoute(
"Default",// 路由名称
"{controller}/{action}/{id}",// 带有参数的 URL
new
{
controller ="Home",
action ="Index",
id =UrlParameter.Optional
} // 参数默认值
);
上面路由的定义中不包括名为“page”的URL参数,下面我们使用Url.RouteUrl方法渲染了URL,而不是生成连接:
@Url.RouteUrl(new{controller="Report",action="List",page="123"});
5、该行代码生成的URL是:/Request/List?Page=2,但是我们指定的参数比需要的参数还要多,这个时候额外的参数会作为查询字符串附加在生成的URL之后,路由机制在选择匹配的路由时并不是精确的匹配,它只是选择足够的匹配的路由,只要指定的参数满足路由需要,额外参数无关紧要
6、Route类生成URL的若干示例
routes.MapRoute("report","reports/{year}/{month}/{day}", new{day = 1});
则GetVirtualPath方法调用示例如下:
参数返回URL 说明
Year=2007,month=1,day=1 /reports/2007/1/1 直接匹配
Year=2007,month=1 /reports/2007/1 默认day=1
Year=2007,month=1, /reports/2007/1/1?Category=123 溢出参数进入生成的URL
day=1,category=123
Year=2007 返回空值 因为没有提供足够的匹配参数
9.3 揭秘路由如何绑定到操作
9.3.1 高层次请求的路由管道
主要由以下几步组成:
① UrlRoutingModule 尝试使用在RouteTable中注册的路由匹配当前请求
② 如果一个路由匹配成功,那么路由模块将从匹配成功的路由中获取IRouteHandler接口对象
③ 路由模块由IRouteHandler接口的GetHandler方法,并返回用来处理请求的IHttpHandler对象
④ 调用HTTP处理程序中的ProcessRequest方法,将要处理的值传给它
⑤ 在ASP.NET MVC 中,IRouteHandler是MvcRouteHandler类的一个实例,MvcRouteHandler转而返回一个实现了IHttpHandler接口的MvcHandler对象,返回的MvcHandler对象主要用来实例化控制器,并调用该实例化控制器上的方法
9.3.2 路由数据
调用GetRouteData方法将返回一个RouteData的实例,RouteData包含了关于匹配请求的路由的信息,如果匹配成功则会创建一个字典,其中包含从URL中解析出的信息,并且路由还会为URL中的每一个参数向字典中添加一个键,如:{controller}/{action}/{id},所在的字典中至少包含三个键分别为controller、action、id
9.4自定义路由约束
之前我们讲过可以使用正则表达式对路由进行细粒度的匹配控制,除此之前路由机制提供了一个具有单一Match方法的IRouteConstraint接口,该接口定义如下:
public interfaceIRouteConstraint
{
boolMatch(HttpContextBase httpContext, Route route, string parameterName,RouteValueDictionary values, RouteDirection routeDirection);
}
当路由机制评估路由约束时,如果约束值实现了IRouteConstraint接口,那么这将导致路由机制引擎调用路由约束上的IRouteConstraint.Match方法,以确定约束是否满足给定的请求。
路由机制本身以HttpMethodConstraint类的形式提供了IRouteConstraint接口的一个实现。如下:定义一个路由只相应GET请求,其他请求不响应
routes.MapRoute("name","{controller}", null, new
{
httpMethod = newHttpMethodConstraint("GET")
});
HttpMethodConstraint("POST/GET/PUT/DELETE")
自定义的约束没有必要关联URL参数,因此可以提供一个基于多个URL参数或一些其他约束
3、外界路由值
在一些情形中,URL生成程序还可以利用那些不是通过调用GetVirtualPath方法显示提供的值
routes.MapRoute(
"controller",
"{controller}/{action}/{page}",
new {controller="Admin"},
new {action="index"}
);
@Html.ActionLink("Page2","List",new{controller="tasks",action="List",page=2})
@Html.ActionLink("Page 2","List",new{page 2})//外界路由值
MapPageRoute指定页面
I realize I coulddo:我知道我可以做到:
routes.MapPageRoute("legacy-foo", "Foo.aspx","~/Legacy/Foo.aspx");
but I'm wonderingif there is a way to do that dynamically (using MVC routes)?但我想知道如果有一种方法做动态(使用MVC路由),? eg:例如:
routes.MapPageRoute("legacyroutes","{filename}.aspx", "~/Legacy/{filename}.aspx");
在视图中生成指向路由的超链接如下:
@Html.RouteLink("Test",new
{
controller ="section",
action ="Index",
id = 123
});
@Html.RouteLink("Default",new
{
controller ="Home",
action ="Index",
id ="123"
});
该方法不能指定由哪个路由来生成链接
为此我们做如下修改:
@Html.RouteLink(linkText:"Route:Test", routeName: "Test", new
{
controller ="section",
action ="Index",
id ="123"
});
@Html.RouteLink(linkText:"Route:Default", routeName: "Default", new
{
controller ="Home",
action ="Index",
id ="123"
});
这样我们便可以为生成的URL指定路由名来生成相应的URL
路由调试
<appSettings>
<AddKey="RouteDebugger:Enabled" value="true" />
</appSettings>