A Free Trial That Lets You Build Big!
Start building with 50+ products and up to 12 months usage for Elastic Compute Service
As an ASP. NET developer, you may be very clear about how ASP. NET handles the code in. aspx resources, how to analyze tags, and dynamically convert them to Visual BasicOr C # class. But what about next? Where do files generated by ASP. NET be stored? How can I use them to meet page requests? Since last month, I began to pay attention to this process. In this month's content, I will analyze the operations on the server, so that you can avoid some common problems. I will discuss the storage of ASP. NET temporary files and the source code of dynamically generated classes used to provide services for page responses. In addition, I will build a program that can work with any ASP. NET 2.0 or ASP. the resource manager tool used by the net Ajax (formerly known as "Atlas") application to view and debug the actual code executed on your page. But before that, you need to know a few things. (Like last month's column, this section is based on the detailed working principles of ASP. NET that are not documented. These implementation details will be available in the future MicrosoftThe. NET Framework Version may change .)
What is saved in the temporary ASP. NET Files folder?
Some temporary files are required for processing ASP. NET page requests. When you install ASP. NET 2.0 on the Web server, the created folder hierarchy is as follows:
The version number here refers to the retail version of ASP. NET 2.0. Each released version of ASP. NET (including each transitional internal version) has a unique version number, and different folder trees are created to support parallel execution of different versions. Therefore, it is extremely important to specify the ASP. NET version that your application applies. In ASP. NET 1.XApplications Running in ASP. NET 2.0 and ASP. NET are physically independent folders. Under the Microsoft. NET \ framework folder, you will find the same number of VX files as the number of installed ASP. NET versions.X.XxxxSubfolders (see figure 1 ).
In the root folder of the installed version, you will see many subdirectories. The config folder contains the computer configuration files, including machine. config and basic web. config files for all sites. The folder named ASP. netwebadminfiles contains the source file that constitutes the website management tool.2005 run the tool internally. Finally, the temporary ASP. Net Files folder contains all temporary files and assemblies created to provide services for pages and resources. To find a file dynamically created for your web page, you need to view this file clip tree. Note that the temporary ASP. NET Files directory is the default location for storing dynamically created files. However, you can use the <compilation> section in the web. config file to configure it by application:
<compilation tempDirectory="d:\MyTempFiles" />
When an application is executed on a computer for the first time, a new sub-folder is created in the temporary file directory. The name of the compiled subfolder is the same as that of the IIS virtual directory of the application. If you only use the Web server embedded in Visual Studio 2005 to test the application, the subfolders use the name of the root folder of the Web application. If you call from the web server's root folder page, you will find their temporary files under the root folder (see figure 2 ).
Under the application compilation sub-folder, there is a group of directories that use the hash name. This shows the path where temporary files can be found. (The last two directories contain false names, but they are actually displayed .)
\v2.0.50727\Temporary ASP.NET Files\MyWebApp\3678b103\e60405c7
You can use the following statement to retrieve the path of the subfolders of the temporary files of the specified application programmatically:
Dim tempFilesFolder As String = HttpRuntime.CodegenDir
ASP. net will regularly clean up the compiling folder and delete outdated resources when the application needs to be re-compiled, but temporary ASP. the size of the subtree under the. NET Files directory may increase significantly, especially on the test computer. As an administrator, you should pay close attention to the directories under temporary ASP. Net files and ensure that all directories are related to the currently active applications. If you accidentally delete the child tree of an active application, you don't have to worry. You will lose all pre-compiled pages and resources and reset the application to its initial compilation status. However, the next request will trigger for each page or batch of pages (depending on the configuration) execute the new compilation process, so that no information or pages will be lost in the end, but the user will feel the first hit delay when processing the next request. Now let's take a look at the contents of the compilation folder of an application.
For each page in an application, the page compilation process generates a file with the following name:
The [Page] placeholder represents the name of The. aspx resource. The [Folder-Hash] placeholder is a hash value, which keeps the file name unique and avoids confusion with files of the same name originally in other folders. Such files are called reserved files because they contain important information that can help ASP. net Runtime Library to quickly retrieve the Assembly and retrieve the type name of the HTTP handler that will be used to provide services for page requests. In addition, the reserved file contains a file hash value to check whether the file content has changed since the last access.
All. aspx pages that constitute an application are compiled in the same Temporary Folder, even if they have the same name and are in different folders. How can this be achieved? Assume that your application contains two pages named test. aspx, which are located in different folders-folder1 and folder2. The two pages will be compiled in the same Temporary Folder, but they can be distinguished by their hash values, because the hash values are calculated based on the path information, not just the file name, therefore, their hash values are different. Therefore, the names of the two files on the test. ASPX page are different only in the folder hash value section:
The internal storage cache of the hash value enables the ASP. NET Runtime Library to identify the hash value of any specified page url and quickly find the corresponding reserved file. If no reserved file is found, ASP. NET will dynamically compile the page. This happens when you deploy an application without pre-compilation. On the other hand, when you pre-compile a site, the retained files on each page are created and placed in the bin folder.
Keep the file as a pure XML file. Figure 3 shows the content of an example file.
Figure 4 lists the attributes of a file. The <filedeps> section lists the files on the current page. Any changes made to any dependency will cause the page to be re-compiled. The filehash value indicates the snapshot of the dependency state, while the hash value indicates the snapshot of the file state on the current page. It is worth noting that when you stop or restart a web application, the mechanism for detecting dynamic file changes completely based on the file change notification will fail. Saves the page and dependency status based on the hash value, so that you can detect changes at any time.
The Type attribute sets the name of the dynamically created class (which will be used to provide services for requests. By default, the type name is ASP. [Page] _ aspx, where [Page] indicates the name of the page file. However, you can change this name by setting the classname attribute in the @ page command of your. aspx file. The root namespace is not changed, so the type name can be ASP. [classname].
The Assembly attribute indicates the name of the dynamically created assembly, which contains the page class used to provide services for requests. The name and content of this type of assembly depend on the settings in the <compilation> section of the web. config file.
By default, application pages are compiled in batch mode, which means ASP. NET will try to accommodate as many uncompiled pages as possible in a program set. You can use the maxbatchsize and maxbatchgeneratedfilesize attributes to limit the number of pages encapsulated in a program and the total size of the Assembly. By default, each batch compilation has no more than 1000 pages, and all the assembly is not greater than 1 MB. In general, when you compile a large number of pages for the first time, you should not let the user wait too long. At the same time, you should not load a large assembly in the memory, but simply provide services for a small page, or start compilation for each page. The maxbatchsize and maxbatchgeneratedfilesize attributes help you find a good balance between the first hit latency and memory usage. If you select site pre-compilation (see extreme ASP.. Net), so you do not have to worry about the first hit delay, but you should still consider the best batch processing parameters to avoid the memory overload of the Web server.
When batch processing is enabled, the first 1000 pages in the application (the actual number depends on maxbatchsize) are compiled into an Assembly named app_web _ [random, [random] is a random sequence consisting of eight characters. If batch processing is disabled, each page generates its own assembly. The Assembly name is as follows:
To disable batch processing, add the following content to the Web. config file:
<compilation batch="false" />
If you view the compilation folder of a sample application, you will find the file containing the cbmresult in the name, and A. CCU file with the same name, as shown below:
The first file in the list is a reserved file. So what are the other two uses? CCU represents the code compilation unit, which is the codedom tree created to generate the source code of the dynamic page class. The CCU file is a binary file that contains the serialized page codedom tree. The cbmresult file is a reserved file used to check whether the CCU is up-to-date, where it is located, and which files it is based on.
The cbmresult file is a module that communicates with the clientbuildmanager class (for example, Visual Studio 2005 designer and intelliisense ).. These modules query the structure of the page to obtain the statement end information. The CCU file retains the latest copy of The codedom structure on the pages that are prepared to provide services for these requests.
Dynamic page source code
As mentioned above,. aspx resources are parsed as Visual Basic or C # classes. This class inherits from system. Web. UI. Page, or is likely to inherit from a class inherited from system. Web. UI. Page. In fact, in most common cases, the dynamic page class has the following prototype:
Namespace ASPPublic Class test_aspxInherits Test : Implements System.Web.IHttpHandler...End ClassEnd Namespace
In this example, the test class is defined in the Code File class on the page. It includes any event handlers and helper routines written in the class files attached to the page. When using Visual Studio 2005, you may have noticed that this code file class lacks the definition of page members. For each runat = server tag that you find in the. aspx source file, the corresponding type of members should be defined in the Code file. The ASP. NET Runtime library system generates the test branch class, which includes all these members and two additional attributes-profile and applicationinstance. Figure 5 shows a class set that participates in a request to provide services for A. aspx resource.
The classes in Figure 5 span two different source files. The first includes the Division class, which is used to improve the class in the code file and the derived actual page class used to provide services for requests. The second file is a copy of the code file you created in the project. These files are named based on the Assembly name. The name structure is as follows: [Assembly].X. VB. (If you use C #, It Is. CS) x is the incremental index value starting from 0, which ensures that the file name is unique.
If you view the contents of the compilation folder on the sample test. ASPX page, you will find that the third file is created, as shown in the following example:
Namespace __ASPFriend Class FastObjectFactory_app_web_test_aspx_cdcab7d2_xg83msu0Private Sub New()MyBase.NewEnd SubShared Function Create_ASP_test_aspx() As ObjectReturn New ASP.test_aspxEnd FunctionEnd ClassEnd Namespace
The class name is the name of the page Assembly prefixed with the string fastobjectfactory. This class has _Xxx(If written in C #, It is a static function ).XxxIs the name of the page class to be instantiated. As the name suggests, this is a helper class. The ASP. NET Runtime library uses it to accelerate the creation of page instances-this is a very common operation. Compared with compiling a page, it takes a very short time to create this type. On the other hand, it is much faster to use the factory analogy to indirectly create objects using activator. createinstance.
The content of the factory class changes according to the batch compilation settings. By default, when batch processing is enabled, the factory class contains the same number of create _XxxFunction. The name of the factory class is the same as that of the batch assembly:
' Used to serve test.aspxShared Function Create_ASP_test_aspx() As ObjectReturn New ASP.test_aspxEnd Function' Used to serve default.aspxShared Function Create_ASP_default_aspx() As ObjectReturn New ASP.default_aspxEnd Function
If the batch processing is disabled, the factory class has the same name as a single page assembly and only contains one shared function-the facotry of the specific page. In this case, each page in the application will have its own factory class.
Runtime public API
With the help of the information discussed above, it is not very difficult to explore the content of the compiling folder. However, it is very convenient to use a tool to help you quickly find the information you need. I will design a resource manager tool to navigate the dynamically generated ASP. NET application source code later, but let's take a look at some Runtime Library APIs in. NET Framework 2.0. In particular, you may want to know more about the following two classes: httpruntime and clientbuildmanager.
The httpruntime class has a large number of shared attributes and can return information about various system paths including the bin folder of the current application, ASP. NET installation path, compilation folder, and current appdomain ID. You can also use the following code to easily obtain the list of assemblies loaded in the current appdomain:
Dim listOfAssemblies() As AssemblylistOfAssemblies = AppDomain.CurrentDomain.GetAssemblies()
This code is not specific to ASP. net, but when. NET application, it returns an array containing the assembly in the appdomain, including all the Assembly generated for your page.
The clientbuildmanager class does not have much information. Except for the codegendir attribute, this attribute returns the same information as the codegendir attribute of httpruntime. However, clientbuildmanager provides many methods to read configuration information (such as supported browsers) and pre-compile applications. Get is a method in this class that returns a list of application directories (which monitor important changes that will trigger the closure of the appdomain application ). These directories are: app_browsers, app_code, app_globalresources, app_webreferences, and bin.
Build a resource manager tool
For debugging, it is often very useful to quickly access the source code and other runtime information of the running page. Any tool that provides this function must be compatible with all ASP. NET applications and require limited configuration or no configuration at all. Nikhil Kothari's excellent web development helper tool is perfect if it can provide ASP. NET Runtime Library Information. This tool is implemented as a browser help object (BHO). BHO is a tool for Microsoft Internet ExplorerThe com-based plug-in on the user interface. BHO will be a very good host environment for the monitoring tools I have built in this column, but unfortunately I am a little lazy and have not done so. Therefore, I have compiled my tool into an HTTP module located between the page and the browser, which can search for query strings. If it is an explicit call, it can be used. To install the HTTP module in an ASP. NET application, you only need to add a line of statements to Web. config, and you can easily enable or disable the installation:
Figure 6 shows most of the code of the explorer HTTP module. This module registers the postmaprequesthandler Application Event and connects it to the page class. The postmaprequesthandler event is triggered when the ASP. NET Runtime Library determines the HTTP handler object required to provide services for the request. If the request query string contains the source = true parameter and the handler is a class inherited from system. Web. UI. Page, the module starts to work.
The ASP explorer module is connected to the page class and registers its own handler for the prerendercomplete event. This design prevents the HTTP module from modifying the request runtime processing and interfering with page compilation. When the source parameter is specified for the query string and set it to true, the module will play a role. As shown in section 6, all the module has to do is use the less common "page" class method setrendermethoddelegate to delegate the page registration presentation (rendering delegate ). When the rendering delegate is specified for the page, the encapsulated method replaces the standard rendering processing. In other words, once this module is installed, if you use test. aspx for calling, you will see the standard output of the page; if you use test. aspx? Source = true. You can see all the page-related runtime information collected by the module.
The source code of ASP explorer defines a class to map the content of the retained file on the current page. It reads the reserved file and copies all the information in the class shown in figure 7. The sourcefiles attribute is a set of all source files designed to contain pages. This collection contains information not found in the reserved files obtained from the compilation folder. In particular, it includes all source files in. VB or. CS format related to a page. These file names start with the name of the dynamic page assembly. The getwebpageinfo method (see figure 6) captures all information and builds output content for requests in source mode. The page output includes the runtime information and the source code of the dynamic page class. Figure 8 shows the actual running ASP explorer.
Figure 8 ASP explorer module running (click the image to get a small view)
Figure 8 ASP explorer module running (click the image to get a large view)
Sample Page Analysis
Now that you have available tools, let's take a brief look at the structure of the code generated by ASP. NET for each. aspx file. It is worth noting that, without the analysis and compilation tools provided by the ASP. NET Runtime Library, you must write code to run the ASP. NET page in person!
The dynamic page class (test_aspx in figure 5) overrides several methods in the system. Web. UI. Page class: frameworkinitialize, processrequest, and gettypehashcode. Processrequest does not change. It only calls its base class method. Gettypehashcode returns the hash code of the page, which uniquely identifies the control hierarchy on the page. When the page is compiled, the hash value is calculated dynamically and inserted as a constant to the source file.
The most noteworthy is the rewriting of frameworkinitialize. This method controls the creation of the Control tree on the page and calls a private method named _ buildcontroltree. This method uses a new instance of the control corresponding to the runat = server tag in the. aspx source file to fill in the control set of the page class. _ Buildcontroltree analyzes all server tags and creates an object for each tag.<asp:textbox runat="server" id="TextBox1" text="Type here" />
The following is a typical code for obtaining the above mark:Private Function __BuildControlTextBox1() As TextBoxDim __ctrl As New TextBox()Me.TextBox1 = __ctrl__ctrl.ApplyStyleSheetSkin(Me)__ctrl.ID = "TextBox1"__ctrl.Text = "Type here"Return __ctrlEnd Function
What if the control has an event handler or data binding expression? Let's first consider the button with "click" event handler. You need to add a line of statement:__ AddHandler __ctrl.Click, AddressOf Me.Button1_Click
For data binding expressions <% #... %>, Except for the databinding event, the generated code is similar:AddHandler __ctrl.DataBinding, AddressOf Me.DataBindingMsg
The Code related to the handler depends on the property of the bound control and the code to be bound. For the text attribute of the label control, the code is similar:Public Sub DataBindingMsg(ByVal sender As Object, ByVal e As EventArgs)Dim target As Label = DirectCast(sender, Label)target.Text = Convert.ToString(..., _CultureInfo.CurrentCulture);End Sub
The expression passed to convert. tostring is <% #... %> Code in the expression. Forced type conversion also depends on the involved type.
If a master page and a topic exist, the number of source files and the dependency list will increase. However, with ASP explorer, you can track the source files as needed.
ASP. NET performs On-Demand dynamic code compilation for its resource types. This function greatly promotes rapid iterative development of Web applications, but requires ASP. NET to write files to disks. Compiling folders is an important folder, and many of ASP. NET's magic points are shown here. You can only study this folder out of interest, but sometimes you can use it to diagnose and debug tricky issues. Of course, most of the functions discussed here are internal functions of ASP. NET. Therefore, these functions may be changed without notice in future versions. However, the working principle of ASP. NET 2.0 is as described in this article. By the way, you can use ASP Explorer with ASP. NET Ajax applications. The tool runs very well.
Start building with 50+ products and up to 12 months usage for Elastic Compute Service