WebForms和WebServices作为.NET平台构建Web程序的两大利器,以其开发简单、易于部署的特点得到了广泛的应用,但殊不知微软公司在背后为我们做了大量的基础性工作,以至于我们开发人员只需简单地拖拖控件、写写一些页面级的代码就可以轻松地实现一些简单的应用程序。当然这种封装也不是没有好处的,至少从开发的角度而言它就可以极大地降低开发的难度,但是这种过度的封装使得我们开发人员当遇到有可能由底层引起的问题时就会束手无策,而且也会使得我们对知识的掌握和理解只停留在了表面而不得其内在本质。正是基于此,所以作者决定以一种探索的精神去试图解析和研究ASP.NET的内部运行机制,当然由于本人水平有限,也不可能对其各个方面理解很到位,姑且就当作本人的一家之言吧,有不对的地方还请各位同仁指正,这样大家可以共同学习提高。

一、IIS处理模型

  从用户发出一个请求(一般而言就是在浏览器地址栏中键入一个URL),到这个请求到达服务器后,最先作出响应的就是IIS(本部分只关注ASP.NET部分,至于TCP/IP不在讨论范围),所以我们就先从这开始讲起。由于IIS有不同的版本,而且其处理模型也大相径庭,所以我会单独分别加以说明和解释。

IIS 5 处理模型

从上图我们可以清楚地知道,IIS在用户请求到达之后都做了哪些事情:

1.当用户请求到达后,工作在内核模式的TCP/IP驱动首先检测到请求,然后将其直接路由到inetinfo.exe进程;

  • inetinfo.exe通过监听WinSock端口(常见的TCP 80端口)接收请求,然后对其进行处理或者交由其扩展组件(ISPAI Extensions)进行处理;
  • IIS中的Metabase维护着一份脚本映射扩展表,即ISAPI Extension Mapping数据表,是用Binary写的。该数据表的作用就是当请求到达IIS的时候,IIS会分析该请求的资源文件的后缀名,然后再通过ISAPI Extension Mapping找到对应的ISAPI Extension;
  • 找到对应的ISAPI Extension后就可以把此请求交由其处理了,例如.aspx文件将由aspnet_isapi.dll来处理;
  • 如果找不到,即一个文件的扩展名没有被映射到ASP.NET,那么ASP.NET就不会去接收这个请求,当然更不会去处理此请求;
  • 我们可以自定义一个Handler去处理一个特殊的文件名扩展,当然前提是你必须得Map到ASP.NET并且必须在你应用程序的Web.config文件中注册这个自定义的Handler,更多信息,请参看文章//TODO
  • 3.用户请求由命名管道(为了提高性能,否则要在两个不同的进程间传递)从inetinfo.exe传给工作者进程aspnet_wp.exe;

    4.aspnet_wp.exe将用户请求交由HTTP运行时即.NET Runtime处理(接下来的处理流程将会在后面讨论)。

    IIS 6 处理模型

    从上图来分析IIS 6架构的处理流程:

  • HTTP.SYS:运行于Windows核心(Kernel)的一个组件,它负责侦听(Listen)来自于外部的HTTP请求(通常来自网络中另一台计算机上的浏览器),根据请求的URL将其转发给相应的应用程序池 (Application Pool)。当此HTTP请求处理完成时,它又负责将处理结果发送出去(其接收者通常为发出HTTP请求的浏览器)。为了提供更好的性能,HTTP.SYS内部建立了一个缓冲区,将最近的HTTP请求处理结果保存起来。
  • Application Pool:  相对于IIS5,IIS6改变了这个处理模型,IIS不再直接寄宿像ISAPI扩展的任何外部可执行代码。代替的是,IIS总会保持一个单独的工作进程:应用程序池。所有的处理都发生在这个进程里,包括ISAPI dll的执行。对于IIS6而言,应用程序池是一个重大的改进,因为它们允许以更小的粒度控制一个指定进程的执行。你可以为每一个虚拟目录或者整个Web站点配置应用程序池,这可以使你很容易的把每一个应用程序隔离到各自的进程里,这样就可以把它与运行在同一台机器上其他程序完全隔离。从Web处理的角度看,如果一个进程死掉,至少它不会影响到其它的进程。
    当应用程序池接收到HTTP请求后,交由在此应用程序池中运行的工作者进程Worker Process: w3wp.exe来处理此HTTP请求。
  • Worker Process: 当工作者进程接收到请求后,首先根据后缀找到并加载对应的ISAPI扩展 (对于aspx而言就是aspnet_isapi.dll),工作者进程加载完aspnet_isapi.dll后,由aspnet_isapi.dll负责加载ASP.NET应用程序的运行环境即CLR (.NET Runtime)。
    注意:工作者进程运行在非托管环境,而.NET中的对象则运行在托管环境之上(CLR),它们之间的桥梁就是ISAPI扩展。
  • WAS(Web Admin Service:这是一个监控程序,它一方面可以存取放在InetInfo元数据库(Metabase)中的各种信息,另一方面也负责监控应用程序池(Application Pool)中的工作者进程的工作状态况,必要时它会关闭一个老的工作者进程并创建一个新的取而代之。
  • 二、.NET运行时

      上面的图形简单描述了大概的处理流程,下面再用文字做些简单的说明:

    1.当请求到达.NET Runtime后,接下来的处理操作就将在托管环境中完成。首先.NET Runtime做两个动作,一是准备Hosting Environment,二是由ApplicationManager创建一个AppDomain并且把处理权交由AppDomain继续完成;

    2.在AppDomain中,由对象ISAPIRuntime启动操作,一方面经方法ProcessRequest()得到HttpWorkerRequest对象,另一方面由方法StartProcessing()生成HttpRuntime对象,接下来把处理权交给了HttpRuntime(HttpWorkerRequest对象将作为HttpRuntime方法中的参数被使用);

    3.HttpRuntime中,方法ProcessRequest将处理请求:

    [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]

    public static void ProcessRequest(HttpWorkerRequest wr)

    {

        if (wr == null)

        {

            throw new ArgumentNullException("wr");

        }

        if (UseIntegratedPipeline)

        {

            throw new PlatformNotSupportedException(System.Web.SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" }));

        }

        ProcessRequestNoDemand(wr);

    }

    internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)

    {

        RequestQueue queue = _theRuntime._requestQueue;

        if (queue != null)

        {

            wr = queue.GetRequestToExecute(wr);

        }

        if (wr != null)

        {

            CalculateWaitTimeAndUpdatePerfCounter(wr);

            wr.ResetStartTime();

            ProcessRequestNow(wr);

        }

    }

    internal static void ProcessRequestNow(HttpWorkerRequest wr)

    {

        _theRuntime.ProcessRequestInternal(wr);

    }

    ProcessRequestInternal

     

    private void ProcessRequestInternal(HttpWorkerRequest wr)

    {

        HttpContext context;

        try

        {

            context = new HttpContext(wr, false);

        }

        catch

        {

            wr.SendStatus(400, "Bad Request");

            wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");

            byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");

            wr.SendResponseFromMemory(bytes, bytes.Length);

            wr.FlushResponse(true);

            wr.EndOfRequest();

            return;

        }

        wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);

        Interlocked.Increment(ref this._activeRequestCount);

        HostingEnvironment.IncrementBusyCount();

        try

        {

            try

            {

                this.EnsureFirstRequestInit(context);

            }

            catch

            {

                if (!context.Request.IsDebuggingRequest)

                {

                    throw;

                }

            }

            context.Response.InitResponseWriter();

            IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);

            if (applicationInstance == null)

            {

                throw new HttpException(System.Web.SR.GetString("Unable_create_app_object"));

            }

            if (EtwTrace.IsTraceEnabled(5, 1))

            {

                EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start");

            }

            if (applicationInstance is IHttpAsyncHandler)

            {

                IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;

                context.AsyncAppHandler = handler2;

                handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);

            }

            else

            {

                applicationInstance.ProcessRequest(context);

                this.FinishRequest(context.WorkerRequest, context, null);

            }

        }

        catch (Exception exception)

        {

            context.Response.InitResponseWriter();

            this.FinishRequest(wr, context, exception);

        }

    }

    虽然上面给出了4个方法,但实际的处理是在第四个方法即最后一个中,请注意方法中的
    context = new HttpContext(wr, false); -- 基于HttpWorkerRequest生成HttpContext
    IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); -- 得到HttpApplication
    handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context); -- 由HttpApplication处理请求

    4.下面我们来看看HttpApplicationFactory.GetApplicationInstance(context)到底做了什么?

    internal static IHttpHandler GetApplicationInstance(HttpContext context)

    {

        if (_customApplication != null)

        {

            return _customApplication;

        }

        if (context.Request.IsDebuggingRequest)

        {

            return new HttpDebugHandler();

        }

        _theApplicationFactory.EnsureInited();

        _theApplicationFactory.EnsureAppStartCalled(context);

        return _theApplicationFactory.GetNormalApplicationInstance(context);

    }

    private HttpApplication GetNormalApplicationInstance(HttpContext context)

    {

        HttpApplication application = null;

        lock (this._freeList)

        {

            if (this._numFreeAppInstances > 0)

            {

                application = (HttpApplication) this._freeList.Pop();

                this._numFreeAppInstances--;

                if (this._numFreeAppInstances < this._minFreeAppInstances)

                {

                    this._minFreeAppInstances = this._numFreeAppInstances;

                }

            }

        }

        if (application == null)

        {

            application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);

            using (new ApplicationImpersonationContext())

            {

                application.InitInternal(context, this._state, this._eventHandlerMethods);

            }

        }

        return application;

    }

    通过上面的方法我们最终获得了HttpApplication对象;

    5.如果我们继续追踪代码application.InitInternal(context, this._state, this._eventHandlerMethods);看会获得什么?

    InitInternal

     

    internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)

    {

        this._state = state;

        PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);

        try

        {

            try

            {

                this._initContext = context;

                this._initContext.ApplicationInstance = this;

                context.ConfigurationPath = context.Request.ApplicationPathObject;

                using (new HttpContextWrapper(context))

                {

                    if (HttpRuntime.UseIntegratedPipeline)

                    {

                        try

                        {

                            context.HideRequestResponse = true;

                            this._hideRequestResponse = true;

                            this.InitIntegratedModules();

                            goto Label_006B;

                        }

                        finally

                        {

                            context.HideRequestResponse = false;

                            this._hideRequestResponse = false;

                        }

                    }

                    this.InitModules();

                Label_006B:

                    if (handlers != null)

                    {

                        this.HookupEventHandlersForApplicationAndModules(handlers);

                    }

                    this._context = context;

                    if (HttpRuntime.UseIntegratedPipeline && (this._context != null))

                    {

                        this._context.HideRequestResponse = true;

                    }

                    this._hideRequestResponse = true;

                    try

                    {

                        this.Init();

                    }

                    catch (Exception exception)

                    {

                        this.RecordError(exception);

                    }

                }

                if (HttpRuntime.UseIntegratedPipeline && (this._context != null))

                {

                    this._context.HideRequestResponse = false;

                }

                this._hideRequestResponse = false;

                this._context = null;

                this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);

                if (HttpRuntime.UseIntegratedPipeline)

                {

                    this._stepManager = new PipelineStepManager(this);

                }

                else

                {

                    this._stepManager = new ApplicationStepManager(this);

                }

                this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

            }

            finally

            {

                this._initInternalCompleted = true;

                context.ConfigurationPath = null;

                this._initContext.ApplicationInstance = null;

                this._initContext = null;

            }

        }

        catch

        {

            throw;

        }

    }

    请注意方法的这些地方
    this.InitModules();初始化所有的Modules,包含用户自定义的HttpModules

    private void InitModules()

    {

        this._moduleCollection = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();

        this.InitModulesCommon();

    }

    private void InitModulesCommon()

    {

        int count = this._moduleCollection.Count;

        for (int i = 0; i < count; i++)

        {

            this._currentModuleCollectionKey = this._moduleCollection.GetKey(i);

            this._moduleCollection[i].Init(this);

        }

        this._currentModuleCollectionKey = null;

        this.InitAppLevelCulture();

    }

    this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

    internal override void BuildSteps(WaitCallback stepCallback)

    {

        ArrayList steps = new ArrayList();

        HttpApplication app = base._application;

        bool flag = false;

        UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;

        flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);

        steps.Add(new HttpApplication.ValidatePathExecutionStep(app));

        if (flag)

        {

            steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));

        }

        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());

        this._execSteps = new HttpApplication.IExecutionStep[steps.Count];

        steps.CopyTo(this._execSteps);

        this._resumeStepsWaitCallback = stepCallback;

    }

    你看到什么?对,这就是我们常说的管道事件序列(具体的Pipelines也会在下一部分介绍)

    我们继续深入代码来看看CreateEventExecutionSteps()和CallHandlerExecutionStep()

    private void CreateEventExecutionSteps(object eventIndex, ArrayList steps)

    {

        AsyncAppEventHandler handler = this.AsyncEvents[eventIndex];

        if (handler != null)

        {

            handler.CreateExecutionSteps(this, steps);

        }

        EventHandler handler2 = (EventHandler) this.Events[eventIndex];

        if (handler2 != null)

        {

            Delegate[] invocationList = handler2.GetInvocationList();

            for (int i = 0; i < invocationList.Length; i++)

            {

                steps.Add(new SyncEventExecutionStep(this, (EventHandler) invocationList[i]));

            }

        }

    }

    internal CallHandlerExecutionStep(HttpApplication app)

    {

        this._application = app;

        this._completionCallback = new AsyncCallback(this.OnAsyncHandlerCompletion);

    }

    6.接下来就是开始HttpApplication的BeginProcessRequest()方法了
    handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context)

    IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

    {

        this._context = context;

        this._context.ApplicationInstance = this;

        this._stepManager.InitRequest();

        this._context.Root();

        HttpAsyncResult result = new HttpAsyncResult(cb, extraData);

        this.AsyncResult = result;

        if (this._context.TraceIsEnabled)

        {

            HttpRuntime.Profile.StartRequest(this._context);

        }

        this.ResumeSteps(null);

        return result;

    }

    ResumeSteps

     

    [DebuggerStepperBoundary]

    internal override void ResumeSteps(Exception error)

    {

        bool flag = false;

        bool completedSynchronously = true;

        HttpApplication application = base._application;

        HttpContext context = application.Context;

        HttpApplication.ThreadContext context2 = null;

        AspNetSynchronizationContext syncContext = context.SyncContext;

        lock (base._application)

        {

            try

            {

                context2 = application.OnThreadEnter();

            }

            catch (Exception exception)

            {

                if (error == null)

                {

                    error = exception;

                }

            }

            try

            {

                try

                {

                Label_0040:

                    if (syncContext.Error != null)

                    {

                        error = syncContext.Error;

                        syncContext.ClearError();

                    }

                    if (error != null)

                    {

                        application.RecordError(error);

                        error = null;

                    }

                    if (syncContext.PendingOperationsCount > 0)

                    {

                        syncContext.SetLastCompletionWorkItem(this._resumeStepsWaitCallback);

                    }

                    else

                    {

                        if ((this._currentStepIndex < this._endRequestStepIndex) && ((context.Error != null) || base._requestCompleted))

                        {

                            context.Response.FilterOutput();

                            this._currentStepIndex = this._endRequestStepIndex;

                        }

                        else

                        {

                            this._currentStepIndex++;

                        }

                        if (this._currentStepIndex >= this._execSteps.Length)

                        {

                            flag = true;

                        }

                        else

                        {

                            this._numStepCalls++;

                            context.SyncContext.Enable();

                            error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);

                            if (completedSynchronously)

                            {

                                this._numSyncStepCalls++;

                                goto Label_0040;

                            }

                        }

                    }

                }

                finally

                {

                    if (context2 != null)

                    {

                        try

                        {

                            context2.Leave();

                        }

                        catch

                        {

                        }

                    }

                }

            }

            catch

            {

                throw;

            }

        }

        if (flag)

        {

            context.Unroot();

            application.AsyncResult.Complete(this._numStepCalls == this._numSyncStepCalls, null, null);

            application.ReleaseAppInstance();

        }

    }

    ExecuteStep

     

    internal Exception ExecuteStep(IExecutionStep step, ref bool completedSynchronously)

    {

        Exception exception = null;

        try

        {

            try

            {

                if (step.IsCancellable)

                {

                    this._context.BeginCancellablePeriod();

                    try

                    {

                        step.Execute();

                    }

                    finally

                    {

                        this._context.EndCancellablePeriod();

                    }

                    this._context.WaitForExceptionIfCancelled();

                }

                else

                {

                    step.Execute();

                }

                if (!step.CompletedSynchronously)

                {

                    completedSynchronously = false;

                    return null;

                }

            }

            catch (Exception exception2)

            {

                exception = exception2;

                if (ImpersonationContext.CurrentThreadTokenExists)

                {

                    exception2.Data["ASPIMPERSONATING"] = string.Empty;

                }

                if ((exception2 is ThreadAbortException) && ((Thread.CurrentThread.ThreadState & System.Threading.ThreadState.AbortRequested) == System.Threading.ThreadState.Running))

                {

                    exception = null;

                    this._stepManager.CompleteRequest();

                }

            }

            catch

            {

            }

        }

        catch (ThreadAbortException exception3)

        {

            if ((exception3.ExceptionState != null) && (exception3.ExceptionState is CancelModuleException))

            {

                CancelModuleException exceptionState = (CancelModuleException) exception3.ExceptionState;

                if (exceptionState.Timeout)

                {

                    exception = new HttpException(System.Web.SR.GetString("Request_timed_out"), null, 0xbb9);

                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TIMED_OUT);

                }

                else

                {

                    exception = null;

                    this._stepManager.CompleteRequest();

                }

                Thread.ResetAbort();

            }

        }

        completedSynchronously = true;

        return exception;

    }

    void HttpApplication.IExecutionStep.Execute()

    {

        string str = null;

        if (this._handler != null)

        {

            if (EtwTrace.IsTraceEnabled(5, 2))

            {

                str = this._handler.Method.ReflectedType.ToString();

                EtwTrace.Trace(EtwTraceType.ETW_TYPE_PIPELINE_ENTER, this._application.Context.WorkerRequest, str);

            }

            this._handler(this._application, this._application.AppEvent);

            if (EtwTrace.IsTraceEnabled(5, 2))

            {

                EtwTrace.Trace(EtwTraceType.ETW_TYPE_PIPELINE_LEAVE, this._application.Context.WorkerRequest, str);

            }

        }

    }

    HttpApplication.IExecutionStep.Execute

     

    void HttpApplication.IExecutionStep.Execute()

    {

        HttpContext context = this._application.Context;

        IHttpHandler handler = context.Handler;

        if (EtwTrace.IsTraceEnabled(4, 4))

        {

            EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_ENTER, context.WorkerRequest);

        }

        if ((handler != null) && HttpRuntime.UseIntegratedPipeline)

        {

            IIS7WorkerRequest workerRequest = context.WorkerRequest as IIS7WorkerRequest;

            if ((workerRequest != null) && workerRequest.IsHandlerExecutionDenied())

            {

                this._sync = true;

                HttpException exception = new HttpException(0x193, System.Web.SR.GetString("Handler_access_denied"));

                exception.SetFormatter(new PageForbiddenErrorFormatter(context.Request.Path, System.Web.SR.GetString("Handler_access_denied")));

                throw exception;

            }

        }

        if (handler == null)

        {

            this._sync = true;

        }

        else if (handler is IHttpAsyncHandler)

        {

            IHttpAsyncHandler handler2 = (IHttpAsyncHandler) handler;

            this._sync = false;

            this._handler = handler2;

            IAsyncResult result = handler2.BeginProcessRequest(context, this._completionCallback, null);

            if (result.CompletedSynchronously)

            {

                this._sync = true;

                this._handler = null;

                try

                {

                    handler2.EndProcessRequest(result);

                }

                finally

                {

                    context.Response.GenerateResponseHeadersForHandler();

                }

                if (EtwTrace.IsTraceEnabled(4, 4))

                {

                    EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);

                }

            }

        }

        else

        {

            this._sync = true;

            context.SyncContext.SetSyncCaller();

            try

            {

                handler.ProcessRequest(context);

            }

            finally

            {

                context.SyncContext.ResetSyncCaller();

                if (EtwTrace.IsTraceEnabled(4, 4))

                {

                    EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);

                }

                context.Response.GenerateResponseHeadersForHandler();

            }

        }

    }

    具体的含义就不去解释了,代码中全有,如果自己想追踪每一步,可用Reflector做反编译调试。

    三、管道事件序列Pipelines

      MSDN上的链接http://msdn.microsoft.com/en-us/library/system.web.httpapplication(v=vs.80).aspx

    深入理解ASP.NET的内部运行机制(转)的更多相关文章

    1. IIS 内部运行机制及Asp.Net执行过程详解

      一直以来对一个Asp.net页面穿过IIS后就返回给浏览器一个HTML页面感觉很是神奇.虽然做技术这么长时间了,也曾经大致了解过一点来龙去脉,但是如果你真的问起我比较详细的过程,我还真的回答不上来,好 ...

    2. ASP.NET MVC的运行机制--url的全局分析

      全局 首先我们来看一副图片       首先,用户通过Web浏览器向服务器发送一条url请求,这里请求的url不再是xxx.aspx格式,而是http://HostName/ControllerNam ...

    3. Windows程序内部运行机制 转自http://www.cnblogs.com/zhili/p/WinMain.html

      一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

    4. 深入浅出话VC++(1)——Windows程序内部运行机制

      一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

    5. 简述ASP.NET的页面运行机制

      在深入学习ASP.NET之前,首先需要先了解一下ASP.NET的页面运行机制: 浏览以下内容需要对ASP.NET管道有一定的了解,附上很不错的几个链接: 选择HttpHandler还是HttpModu ...

    6. 关于js内部运行机制的一本好书

      读<单页Web应用一书>,第二章讲了js内部运行机制,感觉棒极了.之前读<你不知道的js>,看的云里雾里,似懂非懂.没想到单页Web一书将此内容讲的如此通俗易懂,好多困惑已久的 ...

    7. windows程序内部运行机制

      Windows程序内部运行机制 2007-10-21 19:52 1010人阅读 评论(0) 收藏 举报 windowsvc++applicationcallbackwinapistructure W ...

    8. 深入理解asp.net里的HttpModule机制

      刚工作的时候看<asp.net深入解析>,第一次知道HttpModule和HttpHandler.当时对我而言,它们不过就是两个新名词而已,仅仅知道工作原理但是理解的不深刻.随着经验的累积 ...

    9. 理解JAVA与C的运行机制

      1.java的运行机制 java的编译过程,将java的源程序(扩展名为.java的文件),由java编译程序将java的字节码文件(.class文件)在jvm上运行,机器码有cpu运行, jvm编译 ...

    随机推荐

    1. DBA_Oracle数据库运维监控(案例)

      2014-07-27 Created By BaoXinjian

    2. Hololens开发笔记之Gaze凝视射线

      凝视是HoloLens首要输入方式,形式功能类似于桌面系统的光标,用于选择操作全息对象.然而在Unity中并没有明确的Gaze API或者组件. 概念上来说,Gaze是通过用户头部两眼之间发出一条向前 ...

    3. StringIO 模块用于在内存缓冲区中读写数据

      模块是用类编写的,只有一个StringIO类,所以它的可用方法都在类中.此类中的大部分函数都与对文件的操作方法类似. 例: #coding=gbk import StringIO s=StringIO ...

    4. 92、App Permissions(权限管理)实例

      •Manifest权限声明 •Permission Groups-权限组 •权限的区分-安装时授权于运行时授权 •撤销权限 •检查.请求权限 •在应用中如何合理的处理权限请求逻辑   在Android ...

    5. Codeforces 626E Simple Skewness 「数学」「二分」

      题意: 给你一堆无序数,寻找它的一个子堆,使得子堆的平均数减中位数最大. 数字的个数n<=2e5 0<=xi<=1e6. 思路: 首先可以证明这堆数一定是奇数个,证明方法是尝试在奇数 ...

    6. SQL行转列汇总

      PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P ...

    7. oracle 11g 服务端下载地址及安装说明

          oracle 11g 服务端下载地址及安装说明         分类:             Oracle              2013-11-17 19:40     988人阅读  ...

    8. Servlet(Response,Request)

      1.response控制码表的3种方法:输出1; 2,文件下载 3.控制浏览器定时刷新网页(REFRESH) 4.控制浏览器缓存当前文档内容 5. 通过response实现请求重定向. 6.setHe ...

    9. php中引用符号(&)的使用详解

      php的引用就是在变量或者函数.对象等前面加上&符号,在PHP 中引用的意思是:不同的名字访问同一个变量内容,下面介绍如何使用PHP的引用 与C语言中的指针是有差别的.C语言中的指针里面存储的 ...

    10. Mplayer 官方中文手册

      MPlayer 名称总览描述交互式控制用法配置文件配置集通用选项播放器选项(仅适用于MPLAYER)分离器/媒体流选项OSD/字幕选项音频输出选项(仅适用于MPLAYER)音频输出驱动(仅适用于MPL ...