RouteData虽然属于Routing组件,但却贯穿mvc的整个流程。不可谓不重要。
先看,RouteData是在何时怎样被使用的。
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
}
context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };
context.RewritePath("~/UrlRouting.axd");
}
}
}
从这里可以看到,RouteData由RouteCollection.GetRouteData方法从HttpContextBase上下文解析出来。
RouteData里面除了放置RouteHandler以外,还根据Route规则解析url后取得的key-vaule对:比如controller,action之类
然后与HttpContextBase一起封装进RequestContext。交由IHttpHandler(默认是mvcHandler)。
再将httpHandler和Request.Path封装进RequestData放入HttpContextBase里。其构成如下。
![](http://hi.csdn.net/attachment/201202/22/0_1329877871O4QR.gif)
下面是从RouteCollection中取得RouteData的方法。可以看出它遍历Collection里的所有Route,返回第一个符合规则RouteData
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: }
这是Route(继承于RouteBase)的GetRouteData实现
084 | public override RouteData GetRouteData (HttpContextBase httpContext) |
086 | var path = httpContext.Request.AppRelativeCurrentExecutionFilePath; |
087 | var pathInfo = httpContext.Request.PathInfo; |
089 | if (!String.IsNullOrEmpty (pathInfo)) |
090 | throw new NotImplementedException (); |
094 | if (Url != path && path.Substring (0, 2) != "~/" ) |
096 | path = path.Substring (2); |
098 | var values = url.Match (path, Defaults); |
102 | RouteValueDictionary constraints = Constraints; |
103 | if (constraints != null ) |
104 | foreach (var p in constraints) |
105 | if (!ProcessConstraint (httpContext, p.Value, p.Key, values, RouteDirection.IncomingRequest)) |
108 | var rd = new RouteData ( this , RouteHandler); |
109 | RouteValueDictionary rdValues = rd.Values; |
111 | foreach (var p in values) |
112 | rdValues.Add (p.Key, p.Value); |
114 | RouteValueDictionary dataTokens = DataTokens; |
115 | if (dataTokens != null ) { |
116 | RouteValueDictionary rdDataTokens = rd.DataTokens; |
117 | foreach (var token in dataTokens) |
118 | rdDataTokens.Add (token.Key, token.Value); |
关于更具体的代码,可以参照
http://www.cnblogs.com/Wind-Eagle/archive/2008/12/05/1348374.html