.NET 1.1 Pre-compiling ASP.NET page Implementation principle [1] Analysis of Automatic Preparation Mechanism

xiaoxiao2021-03-06  26

Analysis of the principle of pre-compiling the ASP.NET page in .NET 1.1

From: http://www.cnblogs.com/flier/archive/2004/07/08/22339. A large feature when publishing ASP.NET is different from Script language such as ASP and PHP, ASP. Net is actually a compilation fast web development environment. This makes the ASP.NET in terms of development and modification, while not affordable losses. Implement ASP.NET is similar to JSP, the engine is compiled into a class before using a page for the first time, automatically generates assembly and load execution. In the article "Embed an ASP.NET" in the WinForm program, we can understand that the ASP.NET engine can actually be used without the Web server calls such as IIS, which makes the manual pre-compilation ASP.NET page becomes may. In fact, this demand is generally existed. As early as the ASP era, there is a third-party product support to compile the ASP page into binary procedures to improve the efficiency and protection of code security, and will accompany the ASP.NET 2.0 published by Whidbey. Directly built-in the functionality of the precompiled ASP.NET page.

In fact, some people have discussed the implementation of the simulated pre-compilation characteristics in the ASP.NET 1.1, such as the following two articles.

Pre-Compiling ASP.NET Web Pages Pre-Compile Aspx Pages in .NET 1.1

Its ideas are basically traversed through all page files that need to be precompiled, and then triggered the ASP.NET engine's automatic pre-compilation mechanism by simulating web page requests. The benefits of doing this are completely simulated, there is no need to understand the principle of implementation of the ASP.NET engine; however, it will also be subject to many restrictions. If the precompiled result is opaque, you can't get it from the original ASP.NET page file, but also unable to make us Understand the implementation of pre-compilation characteristics from principle.

Below I will be divided into three to four sections, briefly discuss the implementation of the ASP.NET automatic compilation mechanism, the implementation of the ASP.NET page file compilation and how to implement manual precompiled pages and corresponding distribution mechanisms in ASP.NET 1.1.

[1] Analysis of Automatic Preparation Mechanism

In this section, we will discuss in detail in .NET 1.1, the ASP.NET engine implements the principle of automatic page pre-compilation.

First, what we said is actually divided into four categories:

1.Web application file Global.asax 2.Web page file * .aspx 3. User custom control file * .ascx 4.Web service file * .asmx

Web application files are optional for each web application, used to process events at the ASP.NET application level, and will be precompiled as subclasses for a System.Web.httpApplication class; web page The file is an ordinary ASP.NET page, handles the event of a specific page, will be precompiled as subclasses for a System.Web.ui.page class; user-defined control files are special ASP.NET pages, handle control itself Events will be precompiled as subclasses for a System.Web.ui.userControl class; the web service program file is a special page file that is not too the same as the top three, which is not discussed for the time being.

Then, the compilation timing of the first three ASP.NET files is not exactly the same. The web application file is automatically compiled when this web application file is first used; the web page file is automatically compiled when this web page is first used, and it is actually called the httpruntime.processRequest function triggers pre-compilation; user customizes The control file is automatically compiled when he first is used by the web page. It is actually called the page.loadControl function to trigger pre-compilation. After understanding these basic knowledge, let's analyze the automatic preparatory implementation mechanism.

The httpruntime.processRequest function is the call initiator that handles the web page request, the pseudo code is as follows:

The following is quoted:

Public Static Void HttPruntime.ProcessRequest (HttpWorkerRequest WR) {// Check the current caller has an authority as an ASP.NET host (Host) INTERSECURITYPERMILMEDIUM.DEMAND ();

IF (WR == null) {throw new argumentnullexception ("Custom");

Requestqueue queue = httpruntime._theruntime._requestqueue;

IF (Queue! = NULL) {// Put the web page request in the parameter to the request queue / / /// from the queue to get a page request WR = queue.getRequestToExecute (WR);}

IF (wr! = null) {// Update performance counter httpruntime.calculateWaitTimeandUpdatePerfCounter (WR); // actually completed page request work httpruntime.processRequestNow (WR);}}

The httpruntime.processRequestNow function calls the default HTTPRuntime instance's ProcessRequestinternal function to complete the actual page request, the pseudo code is as follows:

The following is quoted:

Internal static void httpruntime.processRequestNow (httpruntime._theruntime.processRequestinternal (WR);}

HttPruntime.ProcessRequestinternal function logic is slightly more complicated, which can be roughly divided into four parts.

First, check the current HttpRuntime instance is first called, if it is the first call through FirstRequestInit function initializes; then calls HttpResponse.InitResponseWriter function returns an object HttpWorkerRequest.Response initial page request; and then call the function to get the current Web application HttpApplicationFactory.GetApplicationInstance Program instance; finally uses the web application instance to complete the actual page request work.

The pseudo code is as follows:

The following is quoted:

Private void httpruntime.processRequestinternal (httpWorkerRequest WR) {// Construct HTTP call context object httpContext ctxt = new httpcontext (wr, 0);

// Set the sending end asynchronous callback function Wr.seetendofsendNotification (this._asyncendofsendCallback, CTXT);

// Update Request Counter Interlocked.Increment (& (this._activeRequestCount);

try {// check the current HttpRuntime instance is first invoked if (this._beforeFirstRequest) {lock (this) {// Use Double-Checked locking mode to avoid redundancy if (this._beforeFirstRequest) {this._firstRequestStartTime = DateTime. Utcnow; this.firstRequestinit (CTXT); // Initialize the current HTTPRuntime runtime environment this._beforefirstRequest = false;}}}

/ / According to the configuration file settings, the role ctxt.impersonation.start (true, false) with higher privilege is placed; Try {// Initialization page Request returning object ctxt.Response.initResponseWriter () Finally {CTXT.ImPersonation. STOP ();

// Get the current web application instance httphandler handler = httpApplicationfactory.getApplicationInstance (CTXT);

IF (Handler == Null) {throw new httpexception (httpruntime.formatResourceString ("Unable_create_app_oad");}

// application instance using the Web page request to complete the actual work if ((handler as IHttpAsyncHandler) = null!) {IHttpAsyncHandler asyncHandler = ((IHttpAsyncHandler) handler); ctxt.AsyncAppHandler = asyncHandler; // use asynchronous processing mechanism asyncHandler.BeginProcessRequest (ctxt, this._handlerCompletionCallback, ctxt);} else {handler.ProcessRequest (ctxt); this.FinishRequest (ctxt.WorkerRequest, ctxt, null);}} catch (Exception E) {ctxt.Response.InitResponseWriter (); this .FinishRequest (WR, CTXT, E);}}

In the httpruntime.processRequestinternal function, there are two parts involving file precompilation: First, when the current web application instance is obtained, it will automatically determine if the Web application file is pre-compiled according to the situation; the second is to complete the actual page request, will The precompiled behavior is triggered when a page is used for the first time.

Let's take a look at the processing of the web application file.

The httpApplicationFactory.GetApplicationInstance function is called in the HTTPRUNTime.ProcessRequestinternal function to get the current web application instance. System.Web.httpApplicationFactory is an internal class to implement management and cache for multiple web application instances. The GetApplicationInstance function returns an IHTTPHANDLER interface, providing the IHTTPHANDLER.PROCESSREQUEST function to process the web page file. The pseudo code is as follows: The following is a reference:

internal static IHttpHandler HttpApplicationFactory.GetApplicationInstance (HttpContext ctxt) {// custom application if (HttpApplicationFactory._customApplication = null!) {return HttpApplicationFactory._customApplication;} // debug request if (HttpDebugHandler.IsDebuggingRequest (ctxt)) {return new HttpDebugHandler ( }

// Judgment whether it is necessary to initialize the current httpApplicationFactory instance if (! HttpapplicationFactory._theapplicationfactory._INITED) {httpapplicationfactory factory = httpApplicationfactory._theapplicationfactory;

lock (HttpApplicationFactory._theApplicationFactory); {// Use Double-Checked locking mode to avoid redundancy if (HttpApplicationFactory._theApplicationFactory._inited!) {// Initialize the current instance HttpApplicationFactory HttpApplicationFactory._theApplicationFactory.Init (ctxt); HttpApplicationFactory._theApplicationFactory._inited = True;}}}

// Get the web application instance return httpapplicationfactory._theapplicationfactory.getnormalalapplicationInstance (CTXT);

After processing special circumstances and possible instance initialization, call the httpApplicationFactory.GetNormalapplicationInstance function to complete the actual functionality of obtaining the web application instance, the pseudo code is as follows:

The following is quoted:

Private httpapplication httpapplicationfactory.getnormalaLApplicationInstance (httpApplication app = null;

// Try to get Lock (this._numfreeAppinstances> 0) {app = (httpappinstances> 0) {app = (httpappinstances> 0) {app = (httpappinstances> 0); this._numfreeAppinstances--;} } IF (app == null) {// Constructs a new web application instance app = (httpapplication) system.web.httpruntime.createnonpublicinstance (this._theapplicationType);

// Initialize the web application example app.initinternal (Context, this._state, this._eventhandlermeth 4;

Return APP;

The code constructs a new web application instance is simple. It is actually a simple packaging of the Activator.createInstance function, the pseudo code is as follows:

The following is quoted:

internal static object HttpRuntime.CreateNonPublicInstance (Type type, object [] args) {return Activator.CreateInstance (type, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, args, null);}

INTERNAL static object httpruntime.createnonpublicinstance (Type Type) {Return httpruntime.createnonpublicinstance (Type, null);}

To this way, the web application instance is integrated, and then the initialization of the initinternal function can begin the actual page processing. The _TheApplicationType type of the HTTPApplicationFactory instance is the resulting Global.asax class after precompiled. The actual precompilation is completed in the httpapplicationfactory.init function, and the pseudo code is as follows:

The following is quoted:

Private void httpapplicationfactory.init (httpcontext ctxt) {if (httpApplicationFactory._customApplication! = null) return;

using (HttpContextWrapper wrapper = new HttpContextWrapper (ctxt)) {ctxt.Impersonation.Start (true, true); try {try {this._appFilename = HttpApplicationFactory.GetApplicationFile (ctxt); this.CompileApplication (ctxt); this.SetupChangesMonitor () Finally {ctxt.impersonation.stop ();}} catch (object) {} this.fireApplicationonstart (ctxt);}}

GetApplicationFile function returns the Global.asax file path in the physical directory; the CompileApplication function is based on this file exists. It is determined that the precompiled and loaded the compiled type, or directly returns the default httpApplication type, the pseudo code is as follows: Quote:

Internal static string httpapplicationFactory.getApplicationFile (httpContext ctxt) {rett path.combine (ctxt.request.physicalApplicationPivePivePivePivePivePath, "global.asax");}

Private void httpapplicationfactory.CompileApplication (httpContext ctxt) {if (fileutil.fileexists (this._appfilename) {ApplicationFileParser Parser;

// Get Web applications compiled type this._theApplicationType = ApplicationFileParser.GetCompiledApplicationType (this._appFilename, context, out parser); this._state = new HttpApplicationState (parser1.ApplicationObjects, parser.SessionObjects); this._fileDependencies = parser. SourceDependencies;} else {this._theapplicationType = typeof (httpapplication); this._state = new httpApplicationState ();} this.ReflectonApplicationType ();}

Analysis here we can find that the GetCompiLEPLICATIONTYPE function for internal type System.Web.ui.ApplicationFileParser is a place that actually performs WEB application compilation. But now we will stop, wait for the next analysis to analyze the compilation process. :)

Then we look at the processing of the web page file.

When analyzing the httpruntime.processRequestinternal function, we have learned that after obtaining the web application instance, the IHTTPASYNCHANDAL interface or IHTTPHANDLER interface of this instance is used to complete the actual page request. Whether or not there is a Global.asax file, the finally returned web application instance is an instance of an HTTPApplication class or its subclass, which implements the IHTTPASYNCHANDLER interface, supports asynchronous web page request work. The processed pseudo code for this interface is as follows:

The following is quoted:

Private void httpruntime.processRequestinternal (HttpWorkerRequest WR) {...

// application instance using the Web page request to complete the actual work if ((handler as IHttpAsyncHandler) = null!) {IHttpAsyncHandler asyncHandler = ((IHttpAsyncHandler) handler); ctxt.AsyncAppHandler = asyncHandler; // use asynchronous processing mechanism asyncHandler.BeginProcessRequest (CTXT, this._handlercompletioncallback, ctxt);} else {handler.processRequest (ctxt); this.finishRequest (ctxt.workerRequest, ctxt, null);} ...}

The httpruntime.processRequestinternal function starts the page request work by calling the httpapplication.ihttpasynchandler.beginprocessRequest function. The httpapplication actually does not support the IHTTPHANDLER interface in synchronous form, and the pseudo code is as follows:

The following is quoted:

Void httpapplication.processRequest (System.Web.httpContext context) {throw new httpexception (httpruntime.formatResourceString ("Sync_not_supported");}

Bool httpapplication.get_isreusable () {return true;}

In the httpapplication.ihttpasynchandler.beginprocessRequest function, the very complex asynchronous calls are completed. This is not more than Luo Luo, and there is a chance to write articles to discuss the asynchronous operation in the ASP.NET. And its final call or use system.web.ui.pageParser to parse and compile the web page that needs to be processed.

Finally, we look at the processing of the user-defined control file.

The LoadControl function of the page class is actually implemented in abstract class TemplateControl. The pseudo code is as follows:

The following is quoted:

public Control LoadControl (string virtualPath) {virtualPath = UrlPath.Combine (base.TemplateSourceDirectory, virtualPath); Type type = UserControlParser.GetCompiledUserControlType (virtualPath, null, base.Context); return this.LoadControl (type1);}

The actual user-defined control precompiled operation is done in the UserControlParser class.

At this section, in this section we have roughly understand the implementation principle of ASP.NET automatically pre-compile, and when doing pre-transcribes page files. The next section we will analyze ApplicationFileParser, PageParser, and UserControlParser to learn how ASP.NET is pre-compiled.

转载请注明原文地址:https://www.9cbs.com/read-65443.html

New Post(0)