我们关注主要方法PostResolveRequestCache,这里有三个关键步骤。
步骤一. 获取RouteData
RouteData是对Route的包装,在后续的处理中使用。它的获取是通过RouteCollection获得的,这个和上面注册用到的RouteTable.Routes是同一个集合对象。调用RouteCollection的GetRouteData会遍历它的每一个项,也就是Route对象,然后调用Route对象的GetRouteData方法(MVC内部很多集合都用到了这种设计)。如下代码:
public RouteData GetRouteData(HttpContextBase httpContext) {
using (GetReadLock()) {
foreach (RouteBase route in this) {
RouteData routeData = route.GetRouteData(httpContext);
if (routeData != null) {
return routeData;
}
}
}
return null;
}
Route对象的GetRouteData方法如下:
public override RouteData GetRouteData(HttpContextBase httpContext) {
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
//结合默认值,匹配url
RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults);
if (values == null) {
return null;
}
//包装成RouteData,这里为什么不放在if后面呢?
RouteData routeData = new RouteData(this, RouteHandler);
//匹配约束
if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) {
return null;
}
//RouteData的Values和DataTokens都来自于Route
foreach (var value in values) {
routeData.Values.Add(value.Key, value.Value);
}
if (DataTokens != null) {
foreach (var prop in DataTokens) {
routeData.DataTokens[prop.Key] = prop.Value;
}
}
return routeData;
}
可以看到,Route对象的GetRouteData方法会匹配url模式,和检查约束条件,如何不符合会返回null。如果匹配,则new一个RouteData。
步骤二、获取IRouteHandler接口对象
上面创建RouteData,参数分别是当前Route对象和它的RouteHandler属性。RouteHandler是一个IRouteHandler,这是一个重要接口,它的定义如下:
public interface IRouteHandler {
IHttpHandler GetHttpHandler(RequestContext requestContext);
}
很明显,它是用于获取IHttpHandler的。那么Route对象的RouteHandler属性又是在哪里初始化的呢?我们回到开始的注册方法,routes.MapRoute,这个方法根据传递的参数创建一个Route对象,该方法的实现如下:
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
//创建一个Route对象,它的IRouteHandler为MvcRouteHandler
Route route = new Route(url, new MvcRouteHandler())
{
Defaults = CreateRouteValueDictionary(defaults),
Constraints = CreateRouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens["Namespaces"] = namespaces;
}
//将Route注册到RouteCollection中
routes.Add(name, route);
return route;
}








