当前位置: 移动技术网 > IT编程>开发语言>.net > asp.net运行原理 详解

asp.net运行原理 详解

2017年12月12日  | 移动技术网IT编程  | 我要评论

滴血的秘密,格尔木市邮编,镭波f630

主要类:
  system.web.httpruntime
  system.web.httpapplicationfactory
  system.web.httpapplication
  system.web.compilation.buildmanager
  system.web.compilation.applicationbuildprovider
  system.web.compilation.buildproviderscompiler
  system.web.ui.pagehandlerfactory

  请求处理简要流程图:


阅读建议:

  用reflector工具边查看asp.net 2.0的源代码边阅读。

分析:

当我们通过浏览器向asp.net 2.0网站的一个asp.net页面发起请求时,在服务器端首先是iis收到请求,iis一看是asp.net页面,心里很开心,因为这个请求不用它处理,交给asp.net isapi就行了。asp.net isapi的工作也比较轻松,他的主要任务就是安排aspnet_wp.exe处理请求,并监视aspnet_wp.exe进程的执行情况,如果aspnet_wp.exe进程太累了,不能出色地完成任务,asp.net isapi就要让他下岗,换一个新的aspnet_wp.exe来处理工作。

  aspnet_wp.exe的主要任务是将请求交给一系列称为的 http 管道的托管对象。如果把asp.net isapi比做销售经理,那aspnet_wp.exe就是生产经理,而http 管道就是生产的流水线。负责流水线的小组就是httpruntime,生产经理aspnet_wp.exe会将订单(http请求)交给httpruntime小组的工作人员processrequest(httpworkerrequest wr),httpruntime根据内部的分工,最终由processrequestinternal(httpworkerrequest wr)在流水线上进行生产,所以processrequestinternal(httpworkerrequest wr)是我们分析的重点。

processrequestinternal的主要工作是:

  1. 创建httpcontext实例。

  2. 对第一次请求进行初始化(ensurefirstrequestinit)。

  a) 在ensurefirstrequestinit中通过调用system.web.httpruntime.firstrequestinit进行一些初始化工作,比如:将web.config配置读到到runtimeconfig中,从bin目录中装载所有dll文件。

  3. 创建httpwriter实例。

  4. 通过调用httpapplicationfactory.getapplicationinstance创建httpapplication实例。

  在httpapplicationfactory.getapplicationinstance中有三个关键方法:

httpapplicationfactory._theapplicationfactory.ensureinited();
httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);
httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);

下面我们对这三个方法逐个进行分析:

  1) httpapplicationfactory._theapplicationfactory.ensureinited();

  该方法检查httpapplicationfactory是否被初始化,如果没有,就通过httpapplicationfactory.init()进行初始化。
在init()中,先获取global.asax文件的完整路径,然后调用compileapplication()对global.asax进行编译。
那编译是如何进行的呢?

  编译的工作由buildmanager完成的。buildmanager先得到globalasaxtype(也就是httpapplication),然后调用buildmanager.getglobalasaxbuildresult()=》getglobalasaxbuildresultinternal()=》ensuretoplevelfilescompiled()进行编译。

  在ensuretoplevelfilescompiled中,先进行compilationstage.toplevelfiles编译,对下面三个目录中的文件进行编译:
a. compileresourcesdirectory();

  编译app_globalresources目录。

  b. compilewebrefdirectory();

  编译app_webreferences目录。

  c. compilecodedirectories();

  编译app_code目录。

  接着进行compilationstage.globalasax 编译,对global.asax进行编译,方法调用情况:compileglobalasax()=》applicationbuildprovider.getglobalasaxbuildresult(buildmanager.isprecompiledapp)。

  在getglobalasaxbuildresult中具体的编译是由applicationbuildprovider与buildproviderscompiler共同完成的。

  buildproviderscompiler.performbuild();进行编译工作。

  applicationbuildprovider.getbuildresult得到编译的结果。

  编译成功后,会在c:\windows\microsoft.net\framework\v2.0.50727\temporary asp.net files\相应的目录中生成类似app_global.asax.mlgx7n2v.dll的dll文件。

  编译生成的类名为asp.global_asax,继承自httpapplication。

  注:如果web目录中没有global.asax文件,就不会编译生成app_global.asax.mlgx7n2v.dll这样的文件。

  2) httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);

  创建特定的httpapplication实例,触发applicationonstart事件,执行asp.global_asax中的application_start(object sender, eventargs e)方法。这里创建的httpapplication实例在处理完事件后,就被回收。

  3) httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);

  该方法创建httpapplication实例并进行初始化(调用system.web.httpapplication. initinternal()方法)。
创建httpapplication实例是根据实际的_theapplicationtype进行创建。如果web目录中没有global.asa文件,也就是说没有动态编译生成asp.global_asax类型,那就直接实例化httpapplication。如果创建了asp.global_asax类型,那就对asp.global_asa进行实例化。

  创建httpapplication实例之后就是调用实例的initinternal方法。

  initinternal方法也是我们重点分析的方法,该方法的主要功能如下:

  1. initmodules():根据web.config的设置,创建相应的httpmodules。

  2. hookupeventhandlersforappplicationandmodules:根据发生的事件,调用httpapplication实例中相应的事件处理函数。

  3. 创建很多实现iexecutionstep接口的类的实例并添加到当前httpapplication实例的_execsteps中,等待回调时执行。从这里我们可以看到httpapplication是以异步的方式处理请求,对请求的很多处理工作都放入了_execstep等待回调时执行。

  _execstep中主要的处理工作如下:

  1) 对请求的路径进行安全检查,禁止非法路径访问(validatepathexecutionstep)。

  2) 如果设置了urlmappings, 进行rewritepath(urlmappingsexecutionstep)。

  3) 执行事件处理函数,比如:beginrequest、authenticaterequest等等。

  4) 获取处理当前请求的httphandler,asp.net页面的运行时编译也是在这里进行的。(maphandlerexecutionstep)
该处理是通过调用system.web.httpapplication. maphttphandler方法。

  在maphttphandler中,首先根据访问的地址从web.config获取相应的实现ihttphandlerfactory的类型。对于asp.net页面,默认是pagehanlderfactory。然后创建pagehanlderfactory实例,调用gethandlerhelper,在gethandlerhelper中调用buildmanager.createinstancefromvirtualpath编译并创建当前请求的asp.net页面的实例(如果已经编译过,直接从缓存中加载)。
createinstancefromvirtualpath经过几次方法调用,将编译任务给了buildmanager. compilewebfile()。compilewebfile从web.config得到相应的buildprovider,对于.aspx文件,相应的buildprovider是pagebuildprovider。pagebuildprovider是如何进行页面编译的,这里就不再就进一步分析了,如果你感兴趣,可以进一步研究asp.net 2.0的源代码。

  5) 调用相应httphandler的.processrequest方法处理请求(如果是异步方式,调用beginprocessreques)。(callhandlerexecutionstep)

  6) 将响应内容写入filter。(callfilterexecutionstep)

  5. 调用httpapplication实例的beginprocessrequest异步处理请求。

上面所讲的_execsteps中所发生的许多事情,都是在httpruntime调用httpapplication beginprocessrequest之后,在beginprocessrequest中调用resumesteps后执行的。

  asp.net 2.0运行时是asp.net 2.0中非常复杂、难以理解也是很重要的部分,对asp.net 2.0运行时源代码的研究有处于我们加深对asp.net 2.0原理的理解,会给我们开发asp.net 2.0应用程序带来不少帮助。这篇文章是我初次学习asp.net 2.0运行时,为了帮助自己更好地理解asp.net 2.0运行时而写的,欢迎你对文章内容提出批评与建议。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网