- Connective Tissue
- Classic ASP versus ASP.NET
- Deemphasizing ISAPI
- NET: a Common Language Runtime Citizen
- Web Forms
- Custom Server-Side Controls
- Web Services and ASP.NET
- Optimizations: ASP.NET Caching
- Managing Session State
- Conclusion
ASP.NET: a Common Language Runtime Citizen
ASP.NET improves on classic ASP by being a full-fledged CLR language. That is, ASP.NET files are compiled rather than simply interpreted like classic ASP. ASP.NET files are compiled on demand based on source code dependencies. ASP.NET compiles ASPX files once and caches the DLL in a well-established directory. If ASP.NET finds source code that is newer than the DLL, it compiles the new source code into a DLL and caches the DLL. ASP.NET is also superior as a deployment environment because you do not need to shut down your site to update the code. When new source code is added to the application, ASP.NET shadow-copies the old DLL to process existing requests using the preexisting DLL so that running processes may continueyou may upgrade the site without shutting it down.
System.Web.UI.Page
The core of every ASP.NET page is the System.Web.UI.Page class. Most ASP.NET pages work by extending this class. Nearly the whole user interface package for ASP.NET is wrapped up into System.Web.UI.Page. The following listing shows the System.Web.UI.Page class:
class Page : IHttpHandler, TemplateControl { class Page : TemplateControl, IHttpHandler { public Page(); // constructor public HttpApplicationState Application {get;} public Cache Cache {get;} public virtual string ClientID {get;} public string ClientTarget {get; set;} public virtual ControlCollection Controls {get;} public virtual bool EnableViewState {get; set;} public string ErrorPage {get; set;} public virtual string ID {get; set;} public bool IsPostBack {get;} public bool IsValid {get;} public virtual Control NamingContainer {get;} public virtual Page Page {get;} public virtual Control Parent {get;} public HttpRequest Request {get;} public HttpResponse Response {get;} public HttpServerUtility Server {get;} public HttpSessionState Session {virtual get;} public ISite Site {get; set;} public virtual string TemplateSourceDirectory {get;} public TraceContext Trace {get;} public virtual string UniqueID {get;} public IPrincipal User {get;} public ValidatorCollection Validators {get;} public virtual bool Visible {get; set;} public virtual void DataBind(); public void DesignerInitialize(); public virtual void Dispose(); public virtual bool Equals( object obj ; public virtual Control FindControl( string id ); public virtual int GetHashCode(); public string GetPostBackClientEvent( Control control, string argument ); public string GetPostBackClientHyperlink( Control control, string argument ); public string GetPostBackEventReference( Control control ); public Type GetType(); public virtual int GetTypeHashCode(); public virtual bool HasControls(); public virtual void InstantiateIn( Control control ); public bool IsClientScriptBlockRegistered( string key ); public bool IsStartupScriptRegistered( string key ); public UserControl LoadControl( string virtualPath ); public ITemplate LoadTemplate( string virtualPath ); public string MapPath( string virtualPath ); public Control ParseControl( string content ); public void RegisterArrayDeclaration( string arrayName, string arrayValue ); public virtual void RegisterClientScriptBlock( string key, string script ); public virtual void RegisterClientScriptFile( string key, string language, string filename ); public virtual void RegisterHiddenField( string hiddenFieldName, string hiddenFieldInitialValue ); public void RegisterOnSubmitStatement( string key, string script ); public void RegisterRequiresPostBack( Control control ; public virtual void RegisterRequiresRaiseEvent( IPostBackEventHandler control ); public virtual void RegisterStartupScript( string key, string script ); public void RenderControl( HtmlTextWriter writer ); public string ResolveUrl( string relativeUrl ); public void SetIntrinsics( HttpContext context ); public void SetRenderMethodDelegate( RenderMethod renderMethod ); public virtual string ToString(); public event EventHandler AbortTransaction; public event EventHandler CommitTransaction; public event EventHandler DataBinding; public event EventHandler Disposed; public event EventHandler Error; public event EventHandler Init; public event EventHandler Load; public event EventHandler PreRender; public event EventHandler Unload; bool Buffer {set;} protected bool ChildControlsCreated {get; set;} int CodePage {set;} string ContentType {set;} protected HttpContext Context {get;} string Culture {set;} protected bool EnableViewStateMac {get; set;} protected EventHandlerList Events {get;} ArrayList FileDependencies {set;} protected bool HasChildViewState {get;} protected bool IsTrackingViewState {get;} int LCID {set;} string ResponseEncoding {set;} protected bool SmartNavigation {get; set;} protected virtual bool SupportAutoEvents {get;} bool TraceEnabled {set;} TraceMode TraceModeValue {set;} TransactionOption TransactionMode {set;} string UICulture {set;} protected virtual StateBag ViewState {get;} protected virtual bool ViewStateIgnoresCase {get;} protected virtual void AddParsedSubObject( object obj ); protected void AspCompatEndProcessRequest( IAsyncResult result ); protected void BuildProfileTree( string parentId, bool calcViewState ); protected void ClearChildViewState(); protected virtual void CreateChildControls(); protected virtual ControlCollection CreateControlCollection(); protected virtual HtmlTextWriter CreateHtmlTextWriter( TextWriter tw ); protected LiteralControl CreateResourceBasedLiteralControl( int offset, int size, bool fAsciiOnly ); protected virtual NameValueCollection DeterminePostBackMode(); protected virtual void EnsureChildControls(); protected virtual void Finalize(); public virtual Control FindControl( string id ); protected virtual void FrameworkInitialize(); protected virtual void InitOutputCache( int duration, string varyByHeader, string varyByCustom, OutputCacheLocation location, string varyByParam ); protected bool IsLiteralContent(); protected virtual object LoadPageStateFromPersistenceMedium(); protected virtual void LoadViewState( object savedState ); protected object MemberwiseClone(); protected virtual void OnAbortTransaction( EventArgs e ); protected virtual bool OnBubbleEvent( object source, EventArgs args ); protected virtual void OnCommitTransaction( EventArgs e ); protected virtual void OnDataBinding( EventArgs e ); protected virtual void OnError( EventArgs e ); protected virtual void OnInit( EventArgs e ); protected virtual void OnLoad( EventArgs e ); protected virtual void OnPreRender( EventArgs e ); protected virtual void OnUnload( EventArgs e ); protected void RaiseBubbleEvent( object source, EventArgs args ); protected virtual void RaisePostBackEvent( IPostBackEventHandler sourceControl, string eventArgument ); protected virtual void Render( HtmlTextWriter writer ); protected virtual void RenderChildren( HtmlTextWriter writer ); protected virtual void SavePageStateToPersistenceMedium( object viewState ); protected virtual object SaveViewState(); protected void SetStringResourcePointer( IntPtr stringResourcePointer, int maxResourceOffset ); protected virtual void TrackViewState(); protected virtual void Validate(); }
We discuss some of these properties and methods later in the chapter. For now, we are going to discuss how the class works. It is fairly large and contains pretty much everything needed to manage the HTTP protocol between the client browser and the Web server.
System.Web.UI.Page Fundamentals
System.Web.UI.Page implements the core ASP.NET interface named IHttpHandler, enabling the Page class to receive HTTP requests and deliver responses. The Page class is from the Control class used for writing server-side controls. (We discuss the Control class later in this chapter.) This gives the Page class the ability to manage standard controls (like edit boxes and list boxes) and other user interface elements. The following listing shows an ASP.NET file that spits a bit of HTML out to the browser advertising the CLR type of the page. If the syntax looks a bit bizarre at first, do not worry. Later in this chapter, we discuss the specifics of mixing C# and ASP.NET code.
<%@ page language="C#" %> <% // finding out the base type of the Web page string s; s = this.GetType().BaseType.ToString(); // Send some text out to the browser this.Response.Write("<html>"); this.Response.Write("<body>"); this.Response.Write("Based on the following CLR Class:"); this.Response.Write(s); this.Response.Write("</body>"); this.Response.Write("</html>"); %>
Notice that the code in the previous listing is written with C# (indicated by the language directive at the top). When the page shows the type this, notice that the page reports the entire namespace: System.Web.UI.Page. Figure 7-1 shows the output to a browser.
Figure 7-1 Output of the .ASPX File after Executing.
The <% %> block markers specify a block of code and the language to use to execute the block. Notice that the structured C# code fits in with the rest of the page. In addition, notice that the base class is System.Web.UI.Page. The Page class includes a Response object suitable for spitting text out to the browser. The C# code that executes simply asks the page for its CLR type and spits that string out to the browser.
In classic ASP, the Response object was called an "intrinsic object"a global variable. In ASP.NET, the Response object is moved into the CLR Page class, making it a bit easier to manage. You do not need to push all your markup language through the Response object. ASP.NET lets you include markup text as part of the page itself (just as in classic ASP). However, the ASP.NET model makes it easier to customize your output through the Response class as shown previously.
ASP.NET Connection Object Model
HTTP is basically a connectionless protocol. That is, the connection between the client and the Web server is not held. Unlike a connection-intensive protocol like distributed component object model (DCOM), clients connect to the server only for the duration of an HTTP request, meaning there needs to be some way of managing the connections within an application. ASP.NET's connection model is based on the System.Web.Http.Context class. ASP.NET generates one HttpContext object for each request serviced and passes it to HttpHandlers (of which System.Web.UI.Page is one). You can always get to the current HttpContext object because it is exposed as a static property of HttpContext: HttpContext.Current. You can use the HttpContext object to get information about the request and its relationship to your application. For example, HttpContext is useful for getting information about the HTTP request, as shown in the following listing. In addition, HttpContext manages the session state; you can get to the session state information through the HttpContext object via the Session property.
<%@ page language="C#" %> <% string s; // Get The current context... HttpContext httpc = HttpContext.Current; // spit out some text... httpc.Response.Write("URL: "); // find out the URL of the current connection s = httpc.Request.RawUrl; httpc.Response.Output.WriteLine(s); %>
The previous listing shows how to get the current connection state and query it for the current HTTP request and the URL used to get to the page. Figure 7-2 shows the output to the browser.
Figure 7-2 Output Advertising the Raw URL Used to Surf to the Page.
Mixing ASP.NET and C#
Take another peek at the previous listing. You may notice that the language directive at the top of the file immediately indicates the language of choice, in this case C#. (It could just as easily be Visual Basic.NET or some other CLR-compliant language.) The executable code is mixed in, bracketed by the <% and %> markers. This is often a convenient way to quickly mix executable CLR code with your HTML (or other markup language). Unfortunately, this technique can also create messy spaghetti code in your Web pages. ASP.NET supports code behind the pagemixing ASP code with executable code coming from another file. Basically, you write executable code using C# or Visual Basic (or some other CLR language) and insert it into the ASP page using a special directive.
To separate your executable code from the page layout, write a source code file containing your executable code and place it alongside your ASPX page. The following listing shows a C# class whose job it is to print out the date and time to any client connected to the server.
using System; using System.Web.UI; namespace AppliedDotNet { public class CodeBehindPage : Page { public void PrintDate() { String strDate; DateTime dateTime = DateTime.Today; strDate = dateTime.ToString( "D" ); Response.Write(strDate); } public void PrintTime() { String strTime; DateTime dateTime = DateTime.Now; strTime = dateTime.ToString( "T" ); Response.Write(strTime); } } }
Figure 7-3 Output of Listings (pp. 258260).
Figure 7-3 shows the output of the previous listing and the next listing (pp. 258260). Notice that the CodeBehindPage class derives from System.Web.UI.Page. The CLR Page class is the master class of ASP.NET that wraps up all the HTTP request/response functionality. Deriving from the Page class brings your ASP.NET page into the runtime. You can use all the functionality that comes with the runtime. The Page class also includes a Response object that can print formatted text out to the client. These two functions simply figure out the date and time using the CLR-sponsored classes and push the text stream out to the browser. The following listing shows the ASP page that uses the class:
<%@ Page language=C# src=CodeBehindPage.cs Inherits=AppliedDotNet.CodeBehindPage %> <html> <body> <h1>Example of code-behind in ASP.NET</h1> <h1>Hello this beautiful day!</h1> <h2><% PrintDate(); %></h2> <h2>It's <%PrintTime();%></h2> </body> </html>
One of the great advantages of ASP.NET is the ability to segregate the executable code from the presentation. The ASP.NET code-behind technique encourages this separation.
ASP.NET Configuration Files
Although ASP.NET still has a few ties to IIS, it tries to keep them to a minimum. ASP.NET adds the ability to configure Web applications through configuration files. After ASP.NET configures an application using the IIS metabase, ASP.NET looks to an application's configuration file to configure the application. (We already looked at configuration files in Chapters 5 and 6.) The ASP.NET configuration files include configuration information specific to ASP.NET.
ASP.NET configuration files are simply XML files named WEB.CONFIG. They can do a number of things, including mapping file extensions to custom handlers, registering custom extension modules, specifying how session state is implemented, and supporting user-defined element types (and corresponding parser objects).
Like normal CLR configuration files, ASP.NET configuration files include sections. The WEB.CONFIG file may contain several sections above and beyond the normal CLR configuration files:
<authentication>: This section manages ASP.NET's authentication settings, including the default authentication code, the HTTP cookie to use for authentication, the password format, and the log-on user name and password.
<authorization>: This section manages ASP.NET authorization settings, including allowing or disallowing access to a specific resource.
<httpModules>: This section adds, removes, or clears HTTP modules within an application.
<customErrors>: This section specifies custom error messages for an ASP.NET application, including specifying the default URL to direct a browser if an error occurs and whether custom errors are enabled, disabled, or shown only to remote clients.
<identity>: This section controls the application identity of the Web application. Settings include specifying whether client impersonation is used on each request and specifying the user name and password if client impersonation is set to false.
<pages>: This section identifies page-specific configuration settings, such as whether the URL resource uses response buffering, whether session state is enabled, whether view state is enabled, whether page events are enabled, the code-behind class the page inherits, and the virtual root location of the client-side script libraries installed by ASP.NET.
<processModel>: This section configures the ASP.NET process model settings on IIS Web server systems. Settings include whether the process model is enabled, the number of minutes until ASP.NET launches a new worker process to take the place of the current one, the idle time-out before ASP.NET shuts down the worker process, the number of minutes allowed for the worker process to shut down gracefully, the number of requests allowed before ASP.NET automatically launches a new worker process to take the place of the current one, the number of requests allowed in the queue before ASP.NET launches a new worker process and reassigns the requests, the maximum allowed memory size, which processors on a multiprocessor server are eligible to run ASP.NET processes, and managing central processing unit (CPU) affinity.
<httpHandlers>: This section maps incoming URL requests to classes implementing IHttpHandler. The section adds, removes, or otherwise clears HttpHandlers.
<sessionState>: This section configures the session state HttpModule. This includes setting the mode (session state turned off, session state stored in process, session state stored in a remote server, or session state stored on a box running SQL Server), whether to support clients without cookies, time-out period for an idle session, the server name, and the SQL connection string.
<globalization>: This section configures the globalization settings of an application, including such items as the encoding of incoming requests, the encoding of outgoing responses, ASPX file encoding, the default culture to process incoming requests, and the default culture for user interface resources.
<compilation>: This section contains all the compilation settings used by ASP.NET. Settings include enabling debugging, the default language being used on the page, the Visual Basic Explicit option, a time-out period for batch compilation, whether to recompile resources before an application restarts, and enabling the Visual Basic Strict compile option.
<trace>: This section configures the ASP.NET trace service. Settings in this section include enabling tracing, limiting the number of trace requests to store on the server, and enabling trace output at the end of the page.
<browserCaps>: This section configures the settings for the browser capabilities component.
Each section entry is associated with a specific value within the WEB.CONFIG file. (See Chapters 2 and 8 for examples of using configuration files.)