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

    在一个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.

  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/tommyli/p/1205067.html
Copyright © 2011-2022 走看看