Asp.net MVC天生就有着漂亮的Url.但是却有别于Asp.net的UrlRewriter.那么其的实现原理是怎样的呢?这就要说到Route了.
Asp.net MVC的生命周期由8个步骤组成:
1.RouteTable(路由表)的创建
2.UrlRoutingMoudle请求拦截
3.Routing engine确定route
4.RouteHandler创建相关的IHttpHandler实例
5.IHttpHandler实例确定Controller(控制器)
6.Controller执行
7.视图引擎创建
8.视图呈现
这里主要讲解前4个.
RouteTable(路由表)的创建
打开Global.asax
class MvcApplication : System.Web.HttpApplication
2: {
void RegisterRoutes(RouteCollection routes)
4: {
);
6:
7: routes.MapRoute(
// Route name
// URL with parameters
// Parameter defaults
}
12: );
13:
14: routes.MapRoute(
,
,
},
}
19: );
20: }
21:
void Application_Start()
23: {
24: AreaRegistration.RegisterAllAreas();
25:
26: RegisterRoutes(RouteTable.Routes);
27:
//RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
29: }
30: }
在此,我们声明了两个Route.
在MVC1中.我们必须
new MvcRouteHandler()));
new MvcRouteHandler()));
new MvcRouteHandler()));
这样添加.但在.Net3.5中.我们却可以直接利用匿名类直接New一个.这是因为.Net3.5中扩展了一个MapRoute方法.该方法利用反射.进行背后的添加
string[] namespaces) {
null) {
);
4: }
null) {
);
7: }
8:
new MvcRouteHandler()) {
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints),
new RouteValueDictionary()
13: };
14:
null) && (namespaces.Length > 0)) {
] = namespaces;
17: }
18:
19: routes.Add(name, route);
20:
return route;
22: }
UrlRoutingMoudle请求拦截
按照MS惯例,一般会在WebConfig留下些蛛丝马迹,打开WebConfig.不出其然.我们发现HttpMoudle中有
/>
利用Reflector打开UrlRoutingModule类.
void Init(HttpApplication application)
2: {
this.OnApplicationPostResolveRequestCache);
this.OnApplicationPostMapRequestHandler);
5: }
6:
7:
Routing engine确定route
可以看到.在application的events中注册了PostResolveRequestCache 和PostMapRequestHandler 事件.
PostResolveRequestCache
void PostResolveRequestCache(HttpContextBase context)2: {this.RouteCollection.GetRouteData(context);null)5: {6: IRouteHandler routeHandler = routeData.RouteHandler;null)8: {object[0]));10: }is StopRoutingHandler))12: {new RequestContext(context, routeData);14: IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);null)16: {object[] { routeHandler.GetType() }));18: }new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };);21: }22: }23: }24:25:
这里.首先通过RouteCollection.GetRouteData得到当前的RouteData,
UrlRoutingModule.RouteCollection
public RouteCollection RouteCollection
2: {
3: get
4: {
null)
6: {
this._routeCollection = RouteTable.Routes;
8: }
this._routeCollection;
10: }
11: set
12: {
value;
14: }
15: }
16:
module中的RouteCollection只是很简单的引用了RouteTable中的静态实例Routes而已.
RouteTable
class RouteTable
2: {
// Fields
new RouteCollection();
5:
// Properties
static RouteCollection Routes
8: {
9: get
10: {
return _instance;
12: }
13: }
14: }
RouteCollection.GetRouteData
这是获取RouteDate的核心实现.
public RouteData GetRouteData(HttpContextBase httpContext)
2: {
null)
4: {
);
6: }
null)
8: {
);
10: }
this.RouteExistingFiles)
12: {
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
15: {
null;
17: }
18: }
//线程锁
20: {
//遍历当前集合中的所有RouteBase
22: {
//调用RouteBase的RouteData.此处传入的Class是Route.
null)
25: {
return routeData;
27: }
28: }
29: }
null;
31: }
32:
Route
Route继承至RouteBase.Route中提供了MVC的Route信息.
可以看到最后承载Route数据的容器是RouteVallueDictionary.Route中包含了该Dictionary
RouteData
RouteData的实现很简单.就提供了几个基本的字段而已.主要用于描述当前Route数据的信息.如此一来.我们可以得到当前Url所匹配的Route.
class RouteData2: {// Fieldsprivate RouteValueDictionary _dataTokens;private IRouteHandler _routeHandler;private RouteValueDictionary _values;7:// Methodspublic RouteData();public RouteData(RouteBase route, IRouteHandler routeHandler);string valueName);12:// Propertiespublic RouteValueDictionary DataTokens { get; }public RouteBase Route { get; set; }public IRouteHandler RouteHandler { get; set; }public RouteValueDictionary Values { get; }18: }
RouteHandler创建相关的IHttpHandler实例
RouteHandler
得到RouteData之后.获取RouteData之中的RouteHandler.根据RouteHandler获取相关的IHttpHandler.这样.MVC的Route隐射阶段就已经完成
new RequestContext(context, routeData);2: IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
后面就是Controller的确定和执行了.