对于一个ASP.NET MVC应用来说,针对HTTP请求的处理实现在目标 Controller 类型的某个Action方法中,每个HTTP请求不再像ASP.NET Web Forms 应用一样是针对一个物理文件,而是针对某个Controller的某个Action方法。目标 Controller 和Action 的名称由 HTTP请求的URL来决定,当ASP.NETMVC接收到抵达的请求后,其首要任务就是通过当前HTTP请求的解析得到目标 Controller和Action 的名称,这个过程是通过ASP.NET MVC的路由系统来实现的。我们通过如下几个对象构建了一个简易的路由系统。
- RouteData
ASP.NET 定义了一个全局的路由表,路由表中的每个 Route 对象包含一个路由模板。目标Controller 和Action的名称可以通过路由变量以占位符(比如“(controller)”和“[action”)的形式定义在模板中,也可以作为路由对象的默认值(无须出现在路由模板中)。对于每一个抵达的HTTP请求,路由系统会遍历路由表并找到一个具有与当前请求URL 模式相匹配的 Route对象,然后利用它解析出以 Controller 和 Action名称为核心的路由数据。在我们自建的 ASP.NETMVC框架中,通过路由解析得到的路由数据通过具有如下定义的 RouteData类型表示。
public class RouteData
{
public IDictionary<string, object> Values { get; private set; )
public IDictionary<string, object > DataTokens {get; private set; }
public IRouteHandler RouteHandler{ get; set;)
public RouteBase Route{get;set;}
public RouteData()
{
this.Values = new Dictionary<string, object>();
this.DataTokens= newDictionary<string, object>();
this.DataTokens.Add("namespaces", newList<string>());
}
public string Controller
{
get
{
obiect controllerName = string.Empty;
this.Values.TryGetValue ("controller", out controllerName);
return controllerName.ToString();
}
}
public string ActionName
{
get
{
object actionName = string.Empty;
this.Values.TryGetValue("action", out actionName);
return actionName.ToString();
如上面的代码片段所示,RouteData定义了两个字典类型的属性 Values和DataTokens,它们代表具有不同来源的路由变量,前者由对请求URL实施路由解析获得。表示 Controller 和Action名称的属性(Controller和ActionName)直接从 Values属性表示的字典中提取,对应的Key分别为“controller”和“action”。
我们之前已经提到过ASP.NET MVC本质上是由两个自定义的ASP.NET组件来实现的,一个是自定义的 HttpModule,另一个是自定义的HttpHandler,后者从 RouteData 对象的RouteHandler属性获得。RouteData的RouteHandler属性类型为IRouteHandler接口,如下面的代码片段所示,该接口具有一个唯一的_GetHttoHandler_方法返回真正用于处理 HNTP_请求的HttpHandler对象。
public interface IRouteHandler
{
IHttpHandler GetittpHandler(RequestContext requestContext);
}
IRouteHandler接口的GetHttpHandler方法具有一个类型为 RequestContext的参数。顾名思义,RequestContext表示当前(HTTP)请求的上下文,其核心就是对当前 HttpContext和 RouteData 的封装,这可以通过如下的代码片段看出来。
public class RequestContext
{
public virtual HttpContextBase HttpContext ( get; set; )
public virtual RouteData RouteData ( get; set;)
}