zoukankan      html  css  js  c++  java
  • [轉]Asp.Net页面执行流程分析

    http://www.cnblogs.com/firstyi/archive/2008/05/08/1188545.html
     
    在我的上一篇文章中说到了HttpModule、HttpHandle的简单使用,我们可以利用它们在页面请求的过程中加入自己的事件处理程序。那么在一个aspx页面请求时后台到底做了什么?当然asp.net做了很多事情,过程也比较复杂,本文主要分析一下大体的流程。总体流程如下:
    请求一个页面时首先被WWW服务截获(inetinfo.exe进程),这个进程首先判断页面的后缀,然后根据IIS中的配置来决定调用哪个扩展程序,比如aspx的页面就会调用c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll,aspnet_isapi.dll将请求发送给w3wp.exe进程(我们在调试IIS中网站时就是把VS2005附加到这个进程上的)。
    接下来w3wp.exe进程就会调用.net类库进行具体处理:
    ISAPIRuntime-->HttpRuntime-->HttpApplicationFactory-->HttpApplication-->HttpModule--HttpHandlerFactory-->HttpHandler 这也是本文主要分析的地方。

    下面只是列出主要流程,如果喜欢钻研的同学可以用Reflector去查看
    一:ISAPIRuntime
           bool useOOP = iWRType == 1;
            wr 
    = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
            wr.Initialize();
            
    string appPathTranslated = wr.GetAppPathTranslated();
            
    string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal;
            
    if ((appDomainAppPathInternal == null|| StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal))
            
    {
                HttpRuntime.ProcessRequestNoDemand(wr);
                
    return 0;
            }

            HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString(
    "Hosting_Phys_Path_Changed"new object[] { appDomainAppPathInternal, appPathTranslated }));
            
    return 1;
    它的主要作用是调用一些非托管代码生成HttpWorkerRequest对象,该对象包含当前请求的所有信息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面中调用的,通过它取得原始的请求信息:
                IServiceProvider provider = (IServiceProvider)HttpContext.Current;
                HttpWorkerRequest wr 
    = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));

    二:HttpRuntime

    最主要的就是private void ProcessRequestInternal(HttpWorkerRequest wr)方法:
            context = new HttpContext(wr, false);
            
            IHttpHandler applicationInstance 
    = HttpApplicationFactory.GetApplicationInstance(context);
            
      IHttpAsyncHandler handler2 
    = (IHttpAsyncHandler) applicationInstance;
      context.AsyncAppHandler 
    = handler2;
      handler2.BeginProcessRequest(context, 
    this._handlerCompletionCallback, context);
            
    1、根据HttpWorkerRequest对象生成HttpContext,HttpContext应该大家都很熟悉的,它包含request、response等属性,在页面中经常会用到的;
    2、调用HttpApplicationFactory来生成IHttpHandler(这里生成的是一个默认的HttpApplication对象,HttpApplication也是IHttpHandler接口的一个实现)
    3、调用HttpApplication对象执行请求

    三:HttpApplicationFactory
    正如2.2中所提到的,这里主要是生成一个HttpApplication对象:

     internal static string GetApplicationFile()
     
    {
         
    return Path.Combine(HttpRuntime.AppDomainAppPathInternal, "global.asax");
     }

    首先会查看是否存在global.asax文件,如果有的话就用它来生成HttpApplication对象,从这里我们可以看到global.asax的文件名是在asp.net的框架中写死的,不能修改的。如果这个文件不存在就使用默认的对象。
    创建好HttpApplication之后对它进行初始化:
        application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
     
    using (ApplicationImpersonationContext context2 = new ApplicationImpersonationContext())
     
    {
         application.InitInternal(context, 
    this._state, this._eventHandlerMethods);
     }

     四、HttpApplication
    这个是比较复杂也比较重要的一个对象
    首先是执行初始化操作,比较重要的一步就是进行HttpModule的初始化:
            private void InitModules()
            
    {
                
    this._moduleCollection = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();
                
    this.InitModulesCommon();
            }
    它会读取web.config中所有HttpModule的配置
    在HookupEventHandlersForApplicationAndModules方法中绑定Module的事件处理程序
    接着进行事件实际绑定:
     if (HttpRuntime.UseIntegratedPipeline)
     
    {
         
    this._stepManager = new PipelineStepManager(this);
     }

     
    else
     
    {
         
    this._stepManager = new ApplicationStepManager(this);
     }

     
    this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

    在ApplicationStepManager的BuildSteps方法中可以看到事件的绑定执行顺序:

    app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);
     steps.Add(new HttpApplication.MapHandlerExecutionStep(app));
     app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);
     steps.Add(new HttpApplication.CallHandlerExecutionStep(app));

     app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);
     steps.Add(
    new HttpApplication.CallFilterExecutionStep(app));
     app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);
     app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);
     
    this._endRequestStepIndex = steps.Count;
     app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);
     steps.Add(
    new HttpApplication.NoopExecutionStep());
    注意上面红色标注的MapHandlerExecutionStep(读取所有的HttpHandler配置)、CallHandlerExecutionStep就是对Handle程序进行处理的,也就是说在web.config中配置的HttpHandler都是在这里进行处理的,执行顺序如上所示
     
    然后就是调用2.3中的方法执行请求:
    Code
    在ResumeSteps中就是执行事件处理程序。 

    五、HttpModule

    在系统web.config中默认的配置有:
    Code
    基本使用方法可以参见我的上一篇文章

    六、HttpHandlerFactory、HttpHandler

    这两个对象在web.config中的配置方法是相同的,默认配置有:
    Code
    要注意的是相同的后缀名配置多次的话,后面的配置会把前面的覆盖。

    这里我们重点看一下aspx的配置:System.Web.UI.PageHandlerFactory
    这是一个HttpHandlerFactory对象,根据不同的Page生成不同的HttpHandler对象(我们自己的Page页面都是一个IHttpHandler):
        Page page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page), context, truetrueas Page;
        
    if (page == null)
        
    {
            
    return null;
        }

        page.TemplateControlVirtualPath 
    = virtualPath;
        
    return page;
    这里会调用web.config中的buildProviders配置编译页面:
    Code

    这样就可以进入我们的Page执行了,大的执行顺序可以参见第四部分的描述,它也就是一个HttpHandler.

  • 相关阅读:
    Google Data Highlighter
    java里的单例实现
    zuul实现的限流
    vscode解决nuget插件不能使用的问题
    springboot~yml里的自定义配置~续
    Cocos2d—X游戏开发之CCToggle(菜单标签切换)CCControlSwitch(开关切换)
    Flash Builder 4的快捷方式和调试技巧
    无刷电机之无感方案控制难点解析
    UVa10815
    [置顶] 学生管理系统验收出现的问题及解决方法
  • 原文地址:https://www.cnblogs.com/godwar/p/1193220.html
Copyright © 2011-2022 走看看