asp.net

位置:IT落伍者 >> asp.net >> 浏览文章

深入了解ASP.NET运行内幕


发布日期:2023年11月25日
 
深入了解ASP.NET运行内幕

事情要知道根本所在原理所在写程序更应该知道程序的运行机制本文主要介绍 的运行内幕

HttpApplication触发事件来通知你的程序有事发生以此来负责请求流转这作为HttpApplicationInit()函数的一部分发生(用Reflector查看SystemWebHttpApplicationInitInternal()方法和HttpApplicationResumeSteps()方法来了解更多详情)连续设置并启动一系列事件包括执行所有的处理器(handler)这些事件处理器映射到globalasax中自动生成的哪些事件中同时它们也映射到所有附加的HttpModule(它们本质上是HttpApplication对外发布的额外的事件接收器(sink))

HttpModule和HttpHandler两者都是根据nfig中对应的配置被动态载入并附加到事件处理链中HttpModule实际上是事件处理器附加到特殊的HttpApplication事件上然而HttpHandler是用来处理应用级请求处理的终点

HttpModule和HttpHandler两者都是在HttpApplicationInit()函数调用的一部分中被载入并附加到调用链上显示了不同的事件它们是何时发生的以及它们影响管道的哪一部分

事件在ASPNET http管道中流转的过程HttpApplication对象的事件驱动请求在管道中流转Http Module可以拦截这些事件并覆盖或者扩展现有的功能

HttpContext HttpModules 和 HttpHandlers

httpApplication它本身对发送给应用程序的数据一无所知它只是一个通过事件来通讯的消息对象它触发事件并通过HttpContext对象来向被调用函数传递消息实际的当前请求的状态数据由前面提到的HttpContext对象维护它提供了所有请求专有的数据并从进入管道开始到结束一直跟随请求显示了ASPNET管道中的流程注意上下文对象(即HttpContext)这个从请求开始到结束一直都是你朋友的对象可以在一个事件处理函数中保存信息并在以后的事件处理函数中取出

一旦管道被启动HttpApplication开始象图六那样一个个的触发事件每个事件处理器被触发如果事件被挂接这些处理器将执行它们自己的任务这个处理的主要任务是最终调用挂接到此特定请求的HttpHandler处理器(handler)是ASPNET请求的核心处理机制通常也是所有应用程序级别的代码被执行的地方记住ASPNET页面和Web服务框架都是作为HttpHandler实现这里也是处理请求的的核心之处模块(module)趋向于成为一个传递给处理器(handler)的上下文的预处理或后处理器ASPNET中典型的默认处理器包括预处理的认证缓存以及后处理中各种不同的编码机制

有很多关于HttpHandler和HttpModule的可用信息所以为了保持这篇文章在一个合理的长度我将提供一个关于处理器的概要介绍

HttpModule

当请求在管道中传递时HttpApplicaion对象中一系列的事件被触发我们已经看到这些事件在Globalasax中作为事件被发布这种方法是特定于应用程序的可能并不总是你想要的如果你要建立一个通用的可用被插入任何Web应用程序的HttpApplication事件钩子你可用使用HttpModule这是可复用的不需要特定语应用程序代码的只需要nfig中的一个条目

模块本质上是过滤器(fliter)功能上类似于ISAPI过滤器但是它工作在ASPNET请求级别上模块允许为每个通过HttpApplication对象的请求挂接事件这些模块作为外部程序集中的类存贮在nfig文件中被配置在应用程序启动时被载入通过实现特定的接口和方法模块被挂接到HttpApplication事件链上多个HttpModule可用被挂接在相同的事件上事件处理的顺序取决于它们在nfig中声明的顺序下面是在nfig中处理器定义

<configuration>

<systemweb>

<httpModules>

<add name= BasicAuthModule

type=HttpHandlersBasicAuthWebStore />

</httpModules>

</systemweb>

</configuration>

注意你需要指定完整的类型名和不带dll扩展名的程序集名

模块允许你查看每个收到的Web请求并基于被触发的事件执行一个动作模块在修改请求和响应数据方面做的非常优秀可用为特定的程序提供自定义认证或者为发生在ASPNET中的每个请求增加其他预处理/后处理功能许多ASPNET的功能像认证和会话(Session)引擎都是作为HttpModule来实现的

虽然HttpModule看上去很像ISAPI过滤器它们都检查每个通过ASPNET应用的请求但是它们只检查映射到单个特定的ASPNET应用或虚拟目录的请求也就是只能检查映射到ASPNET的请求这样你可以检查所有ASPX页面或者其他任何映射到ASPNET的扩展名你不能检查标准的HTM或者图片文件除非你显式的映射这些扩展名到ASPNET ISAPI dll上就像图中展示的那样一个常见的此类应用可能是使用模块来过滤特定目录中的JPG图像内容并在最上层通过GDI+来绘制样品字样

实现一个HTTP模块是非常简单的:你必须实现之包含两个函数(Init()和Dispose())的IHttpModule接口传进来的事件参数中包含指向HTTPApplication对象的引用这给了你访问HttpContext对象的能力在这些方法上你可以挂接到HttpApplication事件上例如如果你想挂接AuthenticateRequest事件到一个模块上你只需像列表中展示的那样做

列表:基础的HTTP模块是非常容易实现的

public class BasicAuthCustomModule : IHttpModule

{

public void Init(HttpApplication application)

{

// *** Hook up any HttpApplication events

applicationAuthenticateRequest +=

new EventHandler(thisOnAuthenticateRequest);

}

public void Dispose() { }

public void OnAuthenticateRequest(object source EventArgs eventArgs)

{

HttpApplication app = (HttpApplication) source;

HttpContext Context = HttpContextCurrent;

… do what you have to do… }

}

记住你的模块访问了HttpContext对象从这里可以访问到其他ASPNET管道中固有的对象如请求(Request)和响应(Response)这样你还可以接收用户输入的信息等等但是记住有些东西可能是不能访问的它们只有在处理链的后段才能被访问

你可以在Init()方法中挂接多个事件这样你可以在一个模块中实现多个不同的功能然而将不同的逻辑分到单独的类中可能会更清楚的将模块进行模块化(译注:这里的模块化和前面的模块没有什么关系)在很多情况下你实现的功能可能需要你挂接多个事件例如一个日志过滤器可能在BeginRequest事件中记录请求开始时间然后在EndRequest事件中将请求结束写入到日志中

注意一个HttoModule和HttpApplication事件中的重点:ResponseEnd()或HttpApplicationCompleteRequest()会在HttpApplication和Module的事件链中抄近道注意ResponseEnd()来获得更多信息

注意ResponseEnd()

当创建HttpModule或者在Globalasax中实现事件钩子的时候当你调用ResponseEnd或 AppplicationCompleteRequest的时候要特别注意这两个函数都结束当前请求并停止触发在HTTP管道中后续的事件然后发生将控制返回到Web服务器中当你在处理链的后面有诸如记录日志或对内容进行操作的行为时因为他们没有被触发有可能使你上当例如sample中logging的例子就会失败因为如果调用ResponseEnd()的话EndRequest事件并不会被触发

上一篇:使用ASP.NET两种发送邮件的方法

下一篇:ASP.NET 2.0的Web Part Framework