Asp.net| compilation
Code-behind
Although the code-behind model is different in 2.0, its syntax has been changed a little. In fact, the change is subtle, and if you don't look carefully, you can't even notice it.
Figure 1 Syntax in asp.net 2.0
Default.aspx
<%@ Page language= "C #" autoeventwireup= "true"
Codefile= "Default.aspx.cs" inherits= "Msdnmag.default"%>
Default.aspx.cs
Namespace Msdnmag
{
public partial class Default:System.Web.UI.Page
{
protected void Page_Load (object sender, EventArgs e)
{
}
}
}
Figure 1 shows the new code-behind syntax.
The model has two differences from the previous 1.x model-the CodeFile attribute is introduced in the @ Page directive, and the code-behind class is declared as a partial class. When you start building the page, you'll notice another difference-server-side controls no longer need to be explicitly declared in code-behind classes, but you can still access them programmatically. For example
Figure 2 implicit server-side control Access
Default.aspx
<%@ Page language= "C #" autoeventwireup= "true"
Codefile= "Default.aspx.cs" inherits= "Msdnmag.default"%>
<! DOCTYPE HTML Public "..." "..." >
< title>untitled page</title>
<body>
<form id= "Form1" runat= "Server"
<div>
Enter your name:
<asp:textbox id= "_nametextbox" runat= "server"/><br/>
<asp: Button id= "_enterbutton" runat= "Server"
text= "Enter"/> <br/>
<asp:label id= "_ Messagelabel "runat=" Server "/>
</div>
< /form>
</body>
Default.aspx.cs
Namespace Msdnmag
{
public partial class Default:System.Web.UI.Page
{
protected void _enterbutton_click (object sender, EventArgs e)
{
_messagelabel.text = "Hello There" + _nametextbox.text + "!";
}
}
}
The form in Figure 2 has several server-side controls that are used programmatically in code-behind files, but you can note that any explicit control declarations are missing from the code-behind class.
The reason for this is related to some of the keywords applied to the code-behind class. In addition to converting the. aspx file to a class definition using the method that renders the page, ASP.net now generates a sibling class for the code-behind class that contains the protected control member variable declaration. Your class is then compiled with the generated class definition and used as the base class for the class that is generated for the. aspx file. As a result, you are basically writing code-behind classes in a way that you often use, but you no longer need to declare (or let the server declare) a member variable declaration for a server-side control. This has always been an unstable relationship in 1.x, because if you accidentally modify a control declaration so that it no longer matches the ID of the control declared on the form, it suddenly stops working. The member variables are now declared implicitly and always correct.
Figure 3 Class Generation with Codebehind
Class for ASPX file generated by asp.net
Namespace ASP
{
public class Default_aspx:MsdnMag.Default
{
...
}
}
Sibling partial class generated by asp.net
Namespace Msdnmag
{
public partial class Default:irequiressessionstate
{
protected TextBox _nametextbox;
protected Button _enterbutton;
protected Label _messagelabel;
Private HtmlForm Form1;
...
}
}
Codebehind partial class that you write
Namespace Msdnmag
{
public partial class Default:page
{
void _enterbutton_click (object sender, EventArgs e)
{
_messagelabel.text = "Hello There" + _nametextbox.text + "!";
}
}
}
Figure 3 shows an example of the class set involved.
Note that the section classification model is used only when using the CodeFile keyword in the @ Page directive. If you use a Inherits keyword with no CodeFile (or src attribute), ASP.net uses the 1.x code-behind type and simply sets the class to the unique base class for the. aspx file. Also, if you don't have code-behind at all, class generation will be exactly the same as it would be in 1.x. Because ASP.net 2.0 is backwards and 1.x compliant, there are a number of code-behind options available for you to use.
Visual Studio 2005 will use any new part of the Web form to hide the model, and if you use the Conversion Wizard, it will also be a good way to convert the Visual Studio. NET 2003 project to use the new model. Because some of the new features of ASP.net 2.0 depend on its causes, it is best to convert all files to the new code-behind model if possible (if you are using Visual Studio, the conversion is almost the only option because Visual Studio 2005 does not open the 1.x that is not converted) Project). For example, strongly typed access to the profile property bundle is added to the sibling class of the code-behind class in 2.0, but if you use the 1.x code-behind model, the strongly typed accessor is added directly to the class definition generated by the. aspx and is not available for code-behind classes. This also applies to strongly typed master pages and previous page accesses.
Back to the top of the page
Compile
At this point, you may wonder why the ASP.net team is using this new code-behind model to use inheritance. asp.net in addition to rendering methods from. aspx files into partial classes (and then merging them with a simplified code-behind class), you can easily generate all control variable declarations. This is how Windows forms works in the. NET Framework 2.0. All the code generated by the designer is placed in the sibling class (and then the class is merged with your application logic). An event handler is placed in a single class that is driven by a form, thus creating a complete separation between computer-generated code and developer code without the need for inheritance.
Well, the original implementation of code-behind in ASP.net 2.0 also performs this action-the code-behind class is just a partial class that is merged with the parsed. aspx file class definition. It's simple and effective, but unfortunately it's not flexible enough. The problem with this model is that code-behind files in a precompiled binary assembly can no longer be deployed with the complete. aspx file, because they now have to be compiled at the same time (one limitation of using a partial class is that all parts of a class must be merged in a single compilation and that the class definition cannot span the assembly). For many developers, this restriction is unacceptable because they are accustomed to deploying the binary code-behind assembly with the complete. aspx file, which then makes the appropriate updates without having to recompile. In fact, this is the model that is used by default in Visual Studio. NET 2003 and is very popular in practice.
Because the inheritance model is reintroduced and some classes are moved to the base class, the. aspx file can now be deployed and compiled independently from the code-behind class. To do this, you need some way to generate a sibling part of the class during compilation or deployment, which contains the control variable declaration, as it has been in the past for the request. Go near the asp.net compiler.
In asp.net 2.0, the asp.net compiler (Aspnet_compiler.exe) was originally introduced as a way to fully precompile the entire site, making it possible to deploy only binary assemblies (even precompiled for. aspx and. ascx files). This is very appealing because it eliminates any on-demand compilation when the request is made, eliminating the first post-deployment clicks that are currently visible on some sites. It also makes it more difficult to make modifications to a deployed site (because you cannot open an. aspx file and change the content), which is tempting when deploying applications that only want to change through the standard deployment process. The release version of ASP.net 2.0 provides compiler support for only binary deployment models. However, it has also been enhanced to support an updatable deployment model in which all source code in the site is precompiled into a binary assembly, but all. aspx and. ascx files are basically intact, So that you can make changes on the server (changes to. aspx and. ascx files, which involve the CodeFile properties that are removed, and the Inherits properties that make modifications to include the assembly name). This model is possible because inheritance has been reintroduced in the code-behind model. In this way, the peer-part class that contains the control declaration can define build and compile independently of the actual. aspx file class.
Figure 4 using Aspnet_compiler.exe for binary deployment
Figure 4 shows the invocation of the Aspnet_compiler.exe utility using the binary deployment option, as well as the result output for the deployment directory. Note that the. aspx file in the deployment directory is just a tag file with no content. They are there to ensure that files with an endpoint name are available when the "Check that file exists" option is set in an IIS application with an. aspx extension. The Precompiledapp.config file is used to track how the application is deployed and to asp.net whether any files need to be compiled when requested. To build an "updatable" site, you need to add a-u to the command line, and the resulting. aspx file will contain their original content (instead of an empty tag file). Note that this feature is also available through the build of Visual Studio 2005 | The Publish Web Site menu item is accessed graphically, as shown in Figure 5. Both the command-line tool and Visual Studio rely on the ClientBuildManager class of the System.Web.Compilation namespace to provide this functionality.
Figure 5 Build in Visual Studio 2005 | Publish Web Site Tool
Using the Aspnet_compiler utility handy, you don't have to worry about how your application will be deployed in general, because any site can be deployed in one of the following three ways-Quanyuan, full binary, or updatable (source code in binaries and. aspx files in Source)- You do not need to make any changes to the page properties or code files used in development. This is not possible in previous versions of ASP.net, because you must decide at development time whether to use the Src attribute to refer to code-behind files, or to precompile them and deploy the assembly to the/bin directory. The full binary deployment is not even an option.
Back to the top of the page
Assembly generation
Since compiling to an assembly can occur in three of cases (explicitly by the developer, using Aspnet_compiler.exe, or in request processing), it becomes more important to understand the mapping of files to assemblies. In fact, depending on how you write the page, you can actually get an application that works as a full source or full binary deployment, but fails to compile when you deploy with an updatable switch.
The model asp.net a separate assembly that typically uses the contents of the App_Code directory, as well as Global.asax files (if they exist), and then compiles all the. aspx pages in each directory into a separate assembly. (if pages in the same directory are made in different languages, or if they are dependent on each other through the @ Reference instruction, they can also form separate assemblies.) user controls and master pages are often compiled independently of. aspx pages. For example, if you want to include Visual basic® and C # source code in a project, you can also configure the App_Code directory to create multiple assemblies. There are some nuances in the details of the assembly creation, depending on the deployment pattern that you selected
Figure 6 Assembly Generation
Deployment Mode
All Source all Binary updatable (mixed)
What compiles into a unique assembly App_Code directory
Global.asax
. ascx and associated codebehind file (separate assembly for all user control)
. master and associated codebehind file (separate assembly for each master page)
All. aspx files and their codebehind files in a given directory (separate assembly per directory) App_Code directory
Global.asax
. ascx and. master files and their associated codebehind files
All. aspx files and their codebehind files in a given directory (separate assembly per directory) App_Code directory (D)
Global.asax (R)
. ascx and. master Files (R)
codebehind files for. ascx and. master Files (D)
All. aspx files in a given directory (separate assembly per directory) (R)
All codebehind files associated with. aspx files in a given directory (separate assembly per directory) (D)
When it's compiled request time deployment time (R) = compiled in Request time
(D) = Compiled at deployment time
Figure 6 describes the components of a specific Web site that is compiled into a separate assembly based on the deployment pattern that you want to use. (Note that I want to ignore resources, themes, and browser directories because they do not contain code, although they are also compiled into separate assemblies.) As mentioned earlier, the target Assembly also differs depending on the language and the reference dependencies. )
Another technique for assembly generation is to compile each. aspx file into a separate assembly using the Aspnet_compiler-fixednames option request, which is consistent across different invocations of the compiler. This is useful if you want to update a single page without modifying other assemblies on the deployment site. It can also generate a large number of assemblies for any large site, so be sure to test your deployment before using this option.
If you find this more complicated, I can tell you the advantages of it, that is, you don't have to spend a lot of time thinking about which files to map to a separate assembly. The. aspx file has been compiled at the end and has always included references to all other generated assemblies, so it usually works regardless of which deployment model you choose.
One important difference in deployment that might actually affect how you make your code on a page is when you use a split in compilation when you are using updatable deployment. When you deploy an updatable site, the code-behind file is compiled into a separate assembly before deployment. Classes generated from the. aspx file are not compiled unless the actual request is made to the file in the directory. This contrasts with the binary deployment, where all files are compiled before deployment, and the source deployment, where all files are compiled on request. The following simple example explains how this leads to a problem,
Figure 7 User Control
MyUserControl.ascx
<%@ control language= "C #"%>
<script runat= "Server" >
public string Color
{
get {return (string) viewstate["Color"]?? "White"; }
set {viewstate["color"] = value;}
}
protected override void OnLoad (EventArgs e)
{
_mainpanel.backcolor = System.Drawing.Color.FromName (Color);
Base. OnLoad (e);
}
</script>
<asp:panel runat= "Server" id= "_mainpanel" >
Other text
</asp:Panel>
Default.aspx
<%@ Page language= "C #" autoeventwireup= "true" codefile= "Default.aspx.cs" inherits= "_default"%>
<%@ Register src= "MyUserControl.ascx" tagname= "MyUserControl" tagprefix= "uc1"%>
<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en"
"' Target=_blank>http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd" >
<title>untitled page</title>
<body>
<form id= "Form1" runat= "Server" >
<div>
<uc1:myusercontrol id= "MyUserControl1" runat= "Server" >
</uc1:MyUserControl></div>
</form>
</body>
Default.aspx.cs
Using System;
Using System.Web.UI;
public partial class _default:system.web.ui.page
{
protected void Page_Load (object sender, EventArgs e)
{
Myusercontrol1.color = "Purple";
}
}
Consider the user control (. ascx file) with the embedded property in Figure 7, and a related page that uses the control and sets the property from its code-behind class.
The page in Figure 7 will be compiled and run in either source or binary deployment mode, but will not compile when deployed as an updatable site because the definition of the user Control Color property is not available at deployment time (the restriction also exists in the 1.x model). To avoid this type of problem, you can usually put all your code in a code-behind file, or simply leave the code in an. aspx and. ascx file without using a code-behind file.
Another note about file to assembly mapping is the use of internal keywords to prevent external assemblies from accessing methods in the class, which may only work in some deployment scenarios and not in other scenarios because there are different assembly mapping options. Unless you plan in advance which deployment option to use, it is best to avoid using internal methods on the page and continue to use type-scoped protection keywords: public, protected, and private.
Back to the top of the page
Summary
For ASP.net developers, the new code-behind model in ASP.net 2.0 is both familiar and unfamiliar. Familiarity is because it still uses inheritance to associate a code-behind class with the class definition generated by its. aspx, and is unfamiliar because the implicit generation of elements such as some classes and control member variable declarations are basic transformations. In fact, you may not notice many differences in usage, but it is important to understand the class relationships and assembly mappings described in this article, regardless of when you are doing unconventional operations (for example, creating a universal base Page class, or mixing code-behind with an inline code model).