技不如人

Welcome to Rickel's blog.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

无aspx文件部署的方法

Posted on 2005-05-08 11:50  Rickel  阅读(1167)  评论(1编辑  收藏  举报
本文转载自 陈叙远的世界

asp.net项目在部署后,aspx文件并没有被编译,这种情形要一直维持到用户第一次访问页面,该页面文件aspx才会转化成cs,并编译成dll,这次访问速度不会很快,但从此以后,所有访问者将得到理想的访问速度。

那么如何在部署后就让所有的aspx处于已经编译成dll的状态呢?通过上面的描述我们不难想到,只要把所有页面都访问一遍即可,这个访问有一个简单方法,就是递归项目所在的文件夹,把物理路径转化成web访问的http地址,并使用httpRequest访问一遍即可(如果有权限控制,可能要作更多的工作)。

访问后,在\WINNT\Microsoft.NET\Framework\版本号\Temporary ASP.NET Files\项目名称\随机数\随机数
这个目录下会生成对应的文件,其中*.cs是通过aspx生成的类文件(该文件经过处理后,就可以实现无aspx文件的部署),*.dll是通过aspx生成的dll文件,*.res是aspx文件中除去runat=server剩余的不需要编译的部分。

我们只要再作两步工作,就可以实现无aspx部署了:

1、把生成的全部dll文件拷贝到项目的bin目录下;
2、在web.config中加入类似下面的配置节声明
<httpHandlers>
    <add verb="*" path="WebForm1.aspx" type="ASP.WebForm1_aspx, srqmg4mo" />
</httpHandlers>
其中,
srqmg4mo是生成的dll的程序集名称,我们得到的dll文件名和程序集名称相同;
ASP.WebForm1_aspx是命名空间,统一为ASP.aspxFileName_aspx格式;
WebForm1.aspx是我们要处理的aspx文件名

做完这两步之后,就可以把所有的aspx都删掉了

* 所有对aspx的访问都被web.config中指定的httpHandlers处理,并不去找实际的物理文件,这是asp.net的本意
* 对于静态页面,可以写一个自定义的httpHandler,把html内容直接Response.Write出来

---------以下是英文原文

Behind the scenes of ASPX files

ASP.NET pages usually made up from two files the ASPX file which contain the page visualization declaration and *.cs file which contain code to handle page events (Code behind). While all the *.cs files compile into one DLL (with the application name) and the page life cycle is well documented (http://www.15seconds.com/issue/020102.htm) this is not the case of ASPX files.

 

Well what is really happened to those ASPX files? In the end of the day ASP.NET turn each ASPX file into assembly. While page is been called for the first time ASP.NET  :

1)      generate *.cs file holding code that match the ASPX declarations.

2)      Using csc.exe (C# compiler) to compile *cs file into DLL (you can see csc.exe if you monitor running processes).

3)      Running the compiled DLL

This sequence is happened just one time resulting with DLL that will be used for other request until one of the page dependencies file will be change and this sequence will be forced again. If you ever wonder why running application for the first time take so much time you probably got good notion why.

 

To understand better what is going on here let’s take very simple page and follow those steps. I create simple page that hold Panel, Textbox and server side script inside ASPX file. Bellow you can see the ASPX file:

 

<%@ Import Namespace="System.Web" %>

<%@ Page language="c#" Codebehind="WebForm13.aspx.cs" AutoEventWireup="false" Inherits="WebApplication22.WebForm13" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<HTML>

            <HEAD>

                        <title>WebForm13</title>

                        <meta content="Microsoft Visual Studio 7.0" name="GENERATOR">

                        <meta content="C#" name="CODE_LANGUAGE">

                        <meta content="JavaScript" name="vs_defaultClientScript">

                        <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">

            </HEAD>

            <body MS_POSITIONING="GridLayout">

                        <script language="C#" runat="server">

                        private void myfunc(object sender, System.EventArgs e)

                        {

                                    HttpContext.Current.Response.Write("Text Init");                                

                        }

                        </script>

                        <form id="WebForm13" method="post" runat="server">

                                    <asp:TextBox id="TextBox1" OnLoad="myfunc" style="Z-INDEX: 101; LEFT: 101px; POSITION: absolute; TOP: 114px" runat="server" Width="170px" Height="48px"></asp:TextBox>

                                    <asp:Panel id="LblNav" style="Z-INDEX: 102; LEFT: 22px; POSITION: absolute; TOP: 63px" runat="server" Width="269px">Panel</asp:Panel>

                        </form>

            </body>

</HTML>

 

All the files that ASP.NET generated will be placed in this folder: C:\$WINDOWSDir$\Microsoft.NET\Framework\v1.0.3705\Temporary ASP.NET Files\$YourWebAppName$\42343\654564. Where the last two folders are randomly numbers generated by ASP.NET. The fun begins from the last directory. That folder holds all the files generated for ASPX files, ASCX files (user control) and ASAX file. The last folder also contain folder called Assembly that holds another directory: dl2. The “dl2” folder contains sub folders with randomly number names each for every referenced assembly from the web project, including the application DLL. We will be focused in the folder that contains all the files generated for ASPX, ASCX and ASAX files.

 

The first file that we interest in is XML file holding the page name (WebForm13.aspx.4689d8a0.xml) . This file contains information that map between the web page name and randomly number that will be used by ASP.NET to generate that page files. Beside the mapping information this file contains data on the decency files of that page (change in that files will cause recreation of ASPX files and recompilation). :

 

<preserve assem="jibrfh34" type="ASP.WebForm13_aspx" hash="49b238a170c332">

    <filedep name="c:\inetpub\wwwroot\WebApplication22\bin\WebApplication22.DLL" />

    <filedep name="c:\inetpub\wwwroot\WebApplication22\WebForm13.aspx" />

</preserve>

 

After grasping that every file that starting with “jibrfh34“ are files that generated for certain page lets see what every file used to. The most important file is *.cs. this file holds the generated C# lines correspond to ASPX Tags and code, we will discuss it later.  The *res file holds resources that the compiler will use them. *cmdline holds the command line that will be use by ASP.NET to compile the *cs file. The file includes reference to other assemblies and optimization settings. *.err file contains errors (if ocured)  while compiling *.cs file. *out file contain outputs from the compilation process. *.dll and *pdb are naturally the compilation output.

 

Out next step is deep diving into *.cs file:

namespace ASP {

    using System;

    using System.Collections;

    using System.Collections.Specialized;

    using System.Configuration;

    using System.Text;

    using System.Text.RegularExpressions;

    using System.Web;

    using System.Web.Caching;

    using System.Web.SessionState;

    using System.Web.Security;

    using System.Web.UI;

    using System.Web.UI.WebControls;

    using System.Web.UI.HtmlControls;

    using ASP;

   

   

    [System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()]

    public class WebForm13_aspx : WebApplication22.WebForm13, System.Web.SessionState.IRequiresSessionState {

       

       

        #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

        protected System.Web.UI.HtmlControls.HtmlForm WebForm13;

       

        #line default

       

        private static bool __intialized = false;

       

        private static object __stringResource;

       

        private static System.Collections.ArrayList __fileDependencies;

       

       

        #line 13 "http://localhost/WebApplication22/WebForm13.aspx"

       

                        private void myfunc(object sender, System.EventArgs e)

                        {

                                    HttpContext.Current.Response.Write("Text Init");                                

                        }

                       

        #line default

       

        public WebForm13_aspx() {

            System.Collections.ArrayList dependencies;

            if ((ASP.WebForm13_aspx.__intialized == false)) {

                ASP.WebForm13_aspx.__stringResource = System.Web.UI.TemplateControl.ReadStringResource(typeof(ASP.WebForm13_aspx));

                dependencies = new System.Collections.ArrayList();

                dependencies.Add("c:\\inetpub\\wwwroot\\WebApplication22\\WebForm13.aspx");

                ASP.WebForm13_aspx.__fileDependencies = dependencies;

                ASP.WebForm13_aspx.__intialized = true;

            }

            this.Server.ScriptTimeout = 30000000;

        }

       

        protected override bool SupportAutoEvents {

            get {

                return false;

            }

        }

       

        protected ASP.Global_asax ApplicationInstance {

            get {

                return ((ASP.Global_asax)(this.Context.ApplicationInstance));

            }

        }

       

        public override string TemplateSourceDirectory {

            get {

                return "/WebApplication22";

            }

        }

       

        private System.Web.UI.Control __BuildControlTextBox1() {

            System.Web.UI.WebControls.TextBox __ctrl;

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl = new System.Web.UI.WebControls.TextBox();

           

            #line default

            this.TextBox1 = __ctrl;

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.ID = "TextBox1";

           

            #line default

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            ((System.Web.UI.IAttributeAccessor)(__ctrl)).SetAttribute("style", "Z-INDEX: 101; LEFT: 101px; POSITION: absolute; TOP: 114px");

           

            #line default

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Width = System.Web.UI.WebControls.Unit.Parse("170px", System.Globalization.CultureInfo.InvariantCulture);

           

            #line default

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Height = System.Web.UI.WebControls.Unit.Parse("48px", System.Globalization.CultureInfo.InvariantCulture);

            

            #line default

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Load -= new System.EventHandler(this.myfunc);

           

            #line default

           

            #line 20 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Load += new System.EventHandler(this.myfunc);

           

            #line default

            return __ctrl;

        }

       

        private System.Web.UI.Control __BuildControlLblNav() {

            System.Web.UI.WebControls.Panel __ctrl;

           

            #line 21 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl = new System.Web.UI.WebControls.Panel();

           

            #line default

            this.LblNav = __ctrl;

           

            #line 21 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.ID = "LblNav";

           

            #line default

           

            #line 21 "http://localhost/WebApplication22/WebForm13.aspx"

            ((System.Web.UI.IAttributeAccessor)(__ctrl)).SetAttribute("style", "Z-INDEX: 102; LEFT: 22px; POSITION: absolute; TOP: 63px");

           

            #line default

           

            #line 21 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Width = System.Web.UI.WebControls.Unit.Parse("269px", System.Globalization.CultureInfo.InvariantCulture);

           

            #line default

            System.Web.UI.IParserAccessor __parser = ((System.Web.UI.IParserAccessor)(__ctrl));

           

            #line 21 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(new System.Web.UI.LiteralControl("Panel"));

           

            #line default

            return __ctrl;

        }

       

        private System.Web.UI.Control __BuildControlWebForm13() {

            System.Web.UI.HtmlControls.HtmlForm __ctrl;

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl = new System.Web.UI.HtmlControls.HtmlForm();

           

            #line default

            this.WebForm13 = __ctrl;

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.ID = "WebForm13";

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __ctrl.Method = "post";

           

            #line default

            System.Web.UI.IParserAccessor __parser = ((System.Web.UI.IParserAccessor)(__ctrl));

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n\t\t\t"));

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            this.__BuildControlTextBox1();

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(this.TextBox1);

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n\t\t\t"));

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            this.__BuildControlLblNav();

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(this.LblNav);

           

            #line default

           

            #line 19 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n\t\t"));

           

            #line default

            return __ctrl;

        }

       

        private void __BuildControlTree(System.Web.UI.Control __ctrl) {

            System.Web.UI.IParserAccessor __parser = ((System.Web.UI.IParserAccessor)(__ctrl));

           

            #line 1 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(this.CreateResourceBasedLiteralControl(0, 397, true));

           

            #line default

           

            #line 1 "http://localhost/WebApplication22/WebForm13.aspx"

            this.__BuildControlWebForm13();

           

            #line default

           

            #line 1 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(this.WebForm13);

           

            #line default

           

            #line 1 "http://localhost/WebApplication22/WebForm13.aspx"

            __parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n\r\n\t</body>\r\n</HTML>\r\n"));

           

            #line default

        }

       

        protected override void FrameworkInitialize() {

            SetStringResourcePointer(ASP.WebForm13_aspx.__stringResource, 397);

            this.__BuildControlTree(this);

            this.FileDependencies = ASP.WebForm13_aspx.__fileDependencies;

            this.EnableViewStateMac = true;

        }

       

        public override int GetTypeHashCode() {

            return 423941586;

        }

    }

}

 

In a fast glimpse you can notice that the file contains notes that map the code to the HTML lines in the source ASPX file. You can use those lines to see how ASP.NET converts HTML lines and learn from it a lot.

Every file is definition of class that inherits from the code behind class and implement interface:

 

public class WebForm13_aspx : WebApplication22.WebForm13, System.Web.SessionState.IRequiresSessionState

 

This class (WebForm13_aspx) will be called before the code behind class. First the class constructor will be called. The constructor initialize the class dependencies files. The first function to be called is FrameworkInitialize. FrameworkInitialize called __BuildControlTree function that responsible to create all the page controls. __BuildControlTree called __ BuildControlWebForm13 that create the Form and called __BuildControlXXX for every control on the form. If control holds child’s controls a call will be made to the corresponding __BuildControlXXX of every child control. Every function create object by the ASPX declaration set its attribute and attached all events that declared on ASPX file. Every function declared in ASPX file generate as class method and connected to the correspond delegate, if needed.

 

As I mention the *CS file is compiled into assembly just the first time ASP.NET is calling a page. More then once I saw that changes that made in the ASPX file are not reflected in the HTML send to the browser. In such scenario deleting the files under the right folder under Temporary ASP.NET will solve the problem since all the files will be recreated. Another issue that you should be aware of is that events of control initialization in c# aren’t happened in the code behind file but works perfectly in the ASPX code.

 

After understanding what goes with ASPX files, let go back to the page life cycle and update it. There are two classes in that process:

1)      The code behind class – WebForm1.

2)      The generated class for ASPX file – adbdef.

 

The calls orders are:

1)      Constructing of adbdef.

2)      Constructing of WebForm1.

3)      FrameworkInitialize method of adbdef class will be called.

4)      Calling __ BuildTree and other control build functions.

5)      Calling the Page and controls events by their order. If event will be declared in ASPX file and code behind, the ASPX event will be called first following by the code behind event.