上文介绍了那么多IHttpHandler的用法,都是在WebForm里面的一些实现,我们知道了所有实现了IHttpHandler的类都可以处理Http请求。同样在MVC里面,也定义了一个实现IHttpHandler接口的类型——MvcHandler,用于处理当前的http请求。通过反编译工具可以看到:
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState { MvcHandler(); public MvcHandler(RequestContext requestContext); AddVersionHeader(HttpContextBase httpContext); protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state); IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state); EndProcessRequest(IAsyncResult asyncResult); GetMvcVersionString(); ProcessRequest(HttpContext httpContext); ProcessRequest(HttpContextBase httpContext); private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory); private void RemoveOptionalRoutingParameters(); IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData); void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result); void IHttpHandler.ProcessRequest(HttpContext httpContext); // 省略若干属性 }
MvcHandler实现了IHttpHandler、 IHttpAsyncHandler两个接口,异步请求这里先不做介绍。重点还是来看看ProcessRequest()方法
将HttpContext转换为HttpContextBase对象,继续转到定义。
这里声明了一个IController和IControllerFactory对象,通过this.ProcessRequestInit()方法创建具体的Controller实例。我们将ProcessRequestInit()方法转到定义
我们将代码复制出来,写入相应的注释:
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) { //1.得到当前的上下文 HttpContext current = HttpContext.Current; if (current != null && ValidationUtility.IsValidationEnabled(current) == true) ValidationUtility.EnableDynamicValidation(current); this.AddVersionHeader(httpContext); this.RemoveOptionalRoutingParameters(); requiredString = ); //3.得到Controller工厂对象 factory = this.ControllerBuilder.GetControllerFactory(); //4.根据当前RequestContext对象,从Controller工厂创建具体的Controller对象 controller = factory.CreateController(this.RequestContext, requiredString); [] { factory.GetType(), requiredString })); }
通过上文的注释很好理解整个控制器的实例化过程。本打算看下Controller工厂如何创建以及控制器如何实例化的,奈何这部分反编译不了。我们暂且理解为反射吧,这些实现细节并不影响我们理解整个过程。
创建控制器成功之后,就是执行Action方法了,这个过程在上面反编译的第二张图片的 controller.Execute(this.RequestContext); 方法得到体现。所以,除去细节,理解MvcHandler的ProcessRequest()方法并不是太难。
三、HttpModule除了HttpHandler之外,Asp.net里面还有另外一个重要的角色——HttpModule。和HttpHandler类似,HttpModule指所有实现了IHttpModule接口的一类类型的统称。至于HttpModule、IHttpModule、UrlRoutingModule各个名称的含义和上述HttpHandler相同,在此不做重复说明。
1、HttpModule能干什么通过上文,我们知道HttpHandler的作用非常明确:处理Http请求,生成相应结果。那么,HttpModule又是干什么的呢?
HttpHandler的作用是处理某一类别的请求,比如ashx、aspx、asmx等,在某些情况下,各类请求可能都需要进行某些相同的处理(比如请求拦截、身份认证、检查功能等),不可能在每个类别的HttpHandler里面都去实现这些相同的代码,这个时候怎么办呢?处理某一类通用请求,提高代码的复用率。是不是想到了我们的面向切面编程(AOP),没错,HttpModule就是负责做这个事,HttpModule通过事件订阅的方式,将某类HttpHandler都需要的功能抽取出来,这些功能可以编译成类库供各个模块调用。这种采用事件(观察者)的设计模式使得系统设计上更加灵活。
2、HttpModule的使用先来看看IHttpModule的定义
public interface IHttpModule { Init(HttpApplication context); Dispose(); }
接口定义很简单,一个初始化组件的方法,一个释放对象的方法。
我们来写一个测试的例子具体看看HttpModule如何注册事件,我们新建一个IHttpModule的实现类: