Asp.net MVC Route初探
2010-09-05 20:42 空逸云 閱讀(735) 評論(1) 收藏 舉報Asp.net MVC天生就有著漂亮的Url.但是卻有別于Asp.net的UrlRewriter.那么其的實現原理是怎樣的呢?這就要說到Route了.
Asp.Net MVC生命周期
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
1: public class MvcApplication : System.Web.HttpApplication
2: {
3: public static void RegisterRoutes(RouteCollection routes)
4: {
5: routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
6:
7: routes.MapRoute(
8: "Default", // Route name
9: "{controller}/{action}/{id}", // URL with parameters
10: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
11: new { controller = @"[^\.]*"}
12: );
13:
14: routes.MapRoute(
15: "Defalut",
16: "{controller}/Blog/{date}",
17: new { action = "Blog" },
18: new { date = @"^\d{4}\.\d{2}\.\d{2}" }
19: );
20: }
21:
22: protected void Application_Start()
23: {
24: AreaRegistration.RegisterAllAreas();
25:
26: RegisterRoutes(RouteTable.Routes);
27:
28: //RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
29: }
30: }
在此,我們聲明了兩個Route.
在MVC1中.我們必須
1: routes.Add(new Route("User/Login", new RouteValueDictionary(new { controller = "User", action = "Login" }), new MvcRouteHandler()));
2: routes.Add(new Route("User/Logout", new RouteValueDictionary(new { controller = "User", action = "Logout" }), new MvcRouteHandler()));
3: routes.Add(new Route("User/Signup", new RouteValueDictionary(new { controller = "User", action = "Signup" }), new MvcRouteHandler()));
這樣添加.但在.Net3.5中.我們卻可以直接利用匿名類直接New一個.這是因為.Net3.5中擴展了一個MapRoute方法.該方法利用反射.進行背后的添加
1: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
2: if (routes == null) {
3: throw new ArgumentNullException("routes");
4: }
5: if (url == null) {
6: throw new ArgumentNullException("url");
7: }
8:
9: Route route = new Route(url, new MvcRouteHandler()) {
10: Defaults = new RouteValueDictionary(defaults),
11: Constraints = new RouteValueDictionary(constraints),
12: DataTokens = new RouteValueDictionary()
13: };
14:
15: if ((namespaces != null) && (namespaces.Length > 0)) {
16: route.DataTokens["Namespaces"] = namespaces;
17: }
18:
19: routes.Add(name, route);
20:
21: return route;
22: }
UrlRoutingMoudle請求攔截
按照MS慣例,一般會在WebConfig留下些蛛絲馬跡,打開WebConfig.不出其然.我們發現HttpMoudle中有
1: <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
利用Reflector打開UrlRoutingModule類.
1: protected virtual void Init(HttpApplication application)
2: {
3: application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
4: application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
5: }
6:
7:
Routing engine確定route
可以看到.在application的events中注冊了PostResolveRequestCache 和PostMapRequestHandler 事件.
PostResolveRequestCache
1: public virtual void PostResolveRequestCache(HttpContextBase context)2: {3: RouteData routeData = this.RouteCollection.GetRouteData(context);4: if (routeData != null)5: {6: IRouteHandler routeHandler = routeData.RouteHandler;7: if (routeHandler == null)8: {9: throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));10: }11: if (!(routeHandler is StopRoutingHandler))12: {13: RequestContext requestContext = new RequestContext(context, routeData);14: IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);15: if (httpHandler == null)16: {17: throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));18: }19: context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };20: context.RewritePath("~/UrlRouting.axd");21: }22: }23: }24:25:
這里.首先通過RouteCollection.GetRouteData得到當前的RouteData,
UrlRoutingModule.RouteCollection
1: public RouteCollection RouteCollection
2: {
3: get
4: {
5: if (this._routeCollection == null)
6: {
7: this._routeCollection = RouteTable.Routes;
8: }
9: return this._routeCollection;
10: }
11: set
12: {
13: this._routeCollection = value;
14: }
15: }
16:
module中的RouteCollection只是很簡單的引用了RouteTable中的靜態實例Routes而已.
RouteTable
1: public class RouteTable
2: {
3: // Fields
4: private static RouteCollection _instance = new RouteCollection();
5:
6: // Properties
7: public static RouteCollection Routes
8: {
9: get
10: {
11: return _instance;
12: }
13: }
14: }
RouteCollection.GetRouteData
這是獲取RouteDate的核心實現.
1: public RouteData GetRouteData(HttpContextBase httpContext)
2: {
3: if (httpContext == null)
4: {
5: throw new ArgumentNullException("httpContext");
6: }
7: if (httpContext.Request == null)
8: {
9: throw new ArgumentException(RoutingResources.RouteTable_ContextMissingRequest, "httpContext");
10: }
11: if (!this.RouteExistingFiles)
12: {
13: string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
14: if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
15: {
16: return null;
17: }
18: }
19: using (this.GetReadLock())//線程鎖
20: {
21: foreach (RouteBase base2 in this)//遍歷當前集合中的所有RouteBase
22: {
23: RouteData routeData = base2.GetRouteData(httpContext); //調用RouteBase的RouteData.此處傳入的Class是Route.
24: if (routeData != null)
25: {
26: return routeData;
27: }
28: }
29: }
30: return null;
31: }
32:
Route
Route繼承至RouteBase.Route中提供了MVC的Route信息.
可以看到最后承載Route數據的容器是RouteVallueDictionary.Route中包含了該Dictionary
RouteData
RouteData的實現很簡單.就提供了幾個基本的字段而已.主要用于描述當前Route數據的信息.如此一來.我們可以得到當前Url所匹配的Route.
1: public class RouteData2: {3: // Fields4: private RouteValueDictionary _dataTokens;5: private IRouteHandler _routeHandler;6: private RouteValueDictionary _values;7:8: // Methods9: public RouteData();10: public RouteData(RouteBase route, IRouteHandler routeHandler);11: public string GetRequiredString(string valueName);12:13: // Properties14: public RouteValueDictionary DataTokens { get; }15: public RouteBase Route { get; set; }16: public IRouteHandler RouteHandler { get; set; }17: public RouteValueDictionary Values { get; }18: }
RouteHandler創建相關的IHttpHandler實例
RouteHandler
得到RouteData之后.獲取RouteData之中的RouteHandler.根據RouteHandler獲取相關的IHttpHandler.這樣.MVC的Route隱射階段就已經完成
1: RequestContext requestContext = new RequestContext(context, routeData);2: IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
后面就是Controller的確定和執行了.
出處:http://kongyiyun.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
浙公網安備 33010602011771號