在 Asp.net MVC 中,开发人员要花费大量的心思在 Controller 的设计上;当用户发起 Http 请求时,Controller 首先获得响应。
试想:用户发出请求 http://hostname:80/AzureApps/BookStore
问自己以下两个问题:
1). MVC 是怎样定位 ZureAppsController 的 ?
2). URI 里确实指明了Controller 为 AzureApps,但命名Controller类时,为什么一定要将其命名为: ZureAppsController ?
........ 前言
在 Asp.net MVC 中,开发人员要花费大量的心思在 Controller 的设计上;当用户发起 Http 请求时,Controller 首先获得响应。
试想:用户发出请求 http://hostname:80/AzureApps/BookStore
问自己以下两个问题:
1). MVC 是怎样定位 ZureAppsController 的 ?
2). URI 里确实指明了Controller 为 AzureApps,但命名Controller类时,为什么一定要将其命名为: AzureAppsController ?
........ 预备知识
[1]. 下载 Reflector http://www.red-gate.com/products/reflector/ , 并 Reflect 类 UrlRoutingModule : IHttpModule。

图 1: Reflect UrlRoutingModule
[2]. 下载 MVC 源码 http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&displaylang=en ,
并打开类 MvcHandler:
图 2: MvcHandler
........ Q1: MVC 是怎样定位 ZureAppsController 的 ?
图2清楚地告诉我们,哦,原来Controller 是 MvcHandler 通过 URI 传递的 controllerName 找到的。
但我们并未在 Web.config 中 配置 MvcHandler 啊?
MVC 巧用 MvcRouteHandler 在 RoutingModule 中将 MvcHanlde 带了进来。

Code

public class MvcRouteHandler : IRouteHandler
{

protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MvcHandler(requestContext);
}


IRouteHandler Members#region IRouteHandler Members

IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return GetHttpHandler(requestContext);
}
#endregion
}
但我们也没有配置 "MvcRouteHandler" 啊?
哈哈, 你在配置 Route ,调用扩展方法 MapRoute 时,MVC 做了手脚.

Code
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
Justification = "This is not a regular URL as it may contain special routing characters.")]

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{

if (routes == null)
{
throw new ArgumentNullException("routes");
}

if (url == null)
{
throw new ArgumentNullException("url");
}


Route route = new Route(url, new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints)
};


if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}

routes.Add(name, route);

return route;
}
此时,打开 Reflector, 可以清楚地看到 UrlRoutingModule 在初始化模块时,注册了 OnApplicationPostMapRequestHandler 。
OnApplicationPostMapRequestHandler 通过 MapRoute 指定的 MvcRouteHandler, 取得了 MvcHandler.
MvcHandler 在 ProcessRequest 时,根据 controllerName 找到了对应的 Controller ,并实例化之。
........ 总结
希望本文对和我一样,对第一个问题起初不太清楚的同仁,有些帮助。
下一个问题:
Q2: 命名Controller类时,为什么一定要将其命名为: ZureAppsController ?
因时间有限,留作下次吧。