WebForm中路由的渊源
大多数做过.NET WEB FORM的人,第一次接触ASP.NET MVC, 对路由可能很陌生,在他们的潜意识里访问一个.Net Web 应用程序是这样的。
从访问地址我们能看出,对应的是一个物理地址Index.aspx文件,是一对一的物理关系。假如我们在后期更改文件名称或移动文件位置后,页面地址也会发生改变,用URL地址再访问时页面会失效,且报404页面不存在的错误。
其实路由并不是ASP.NET MVC特有的,其实在WEB.FORM开发里面就有了。只是我们没有去深究它。然而随着时间的推移,我们的URL不再是一个.aspx页面了,而是像{xxxx}/{xxx}的URL形式来对应一个aspx文件。
因此,我们可以知道路由可以解决URL与物理文件分离,它维系着URL与物理文件之间的关联映射,使URL和物理文件的改变,都不会受影响。
WEB FORM如何使用路由?
1. 新建一个ASP.NET WEB应用程序,然后选择空项目模板。并新建一个Dafault.aspx、Global.asax文件。
2. 打开Global文件,在Application_Start方法中添加路由信息。
1) “List‘”路由名称,可以理解为这个路由的名称是List,也就是路由的标识符。
2) “Blog/{Name}/{Category}”表示以一个什么样的URL格式访问default.aspx页面,其中{Name}和{Category}表示路由变量。
3) “Default.aspx”:要访问的实际页面,也就是访问URL实际要映射的物理文件。
4) “ new RouteValueDictionary() { { "Name", "*" }, { "Category", "*" } }:表示路由变量默认值。当我们在URL中没有指定Name和Category,那么将采用默认值*.
5) “ new RouteValueDictionary() { { "ID", "*" } }:路由的Token值,可以理解为一个附加的路由值。
3. 我们在路由集合中添加了一个名为“List”,访问格式为“Blog/{Name}/{Category}”的URL,实际访问页面为Default.aspx,默认路由变量Name="*",Category="*"的路由。当我们在浏览器中输入http://lcoalhost/Blog
源码分析
RouteTable.Routes.MapPageRoute背后到底发生了什么呢?下面我们来分析源码:
注:使用ILSpy工具进行源码解析:下载地址
RouteTable.cs
using System; using System.Runtime.CompilerServices; namespace System.Web.Routing { [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] public class RouteTable { private static RouteCollection _instance = new RouteCollection(); //单列模式 public static RouteCollection Routes //属性,返回RouteCollection对象集合 { get { return RouteTable._instance; } } } }
RouteCollection.cs类中的MapPageRoute方法
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens) { if (routeUrl == null) //路由格式不能为空,否则会报routeRul异常。上面例子中指的是 "Blog/{Name}/{Category}" { throw new ArgumentNullException("routeUrl"); }
// 实例一个路由对象,根据设置的路由信息,添加到路由集合RouteCollection中 Route route = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess)); this.Add(routeName, route); return route; }