ASP.
net Architecture
Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director New Zealand
A quick word about the RD program
Regional Directors aren't Microsoft employees RDs are independent developers who provide a link between Microsoft and the local community. Find out more: http://www.microsoft.com/rd
Drop us a line if you want to talk shop, ask about the new technology coming out of Microsoft, or just see if we can help with a technical problem you are having New Zealand RDs Lukas Svoboda, Jeremy Boyd
Objectives
Discuss history of ASP.NET
Dynamic web content ASP
Present new ASP.NET architecture
.NET core Compilation Code behind Shadow copying
Migration from ASP
Dynamic Web Content
Dynamic web content has traditionally been generated using CGI, ISAPI, or ASP on Microsoft platforms
The Common Gateway Interface (CGI) provides dynamic content by directly processing requests and issuing responses in a custom process The Internet Services API provides similar capability through filter DLLs, reducing the overhead Active Server Pages (ASP) eliminates the need to author DLLs to provide dynamic content -integrated server-side script generates HTML
ASP
Active Server Pages (ASP) simplify common tasks ISAPI DLLs were being used for
ASP was introduced because web developers were building ISAPI extension DLLs to perform things like database queries and posting back HTML Each different type of request required a new ISAPI extension DLL to be written ASP.DLL is a generic ISAPI DLL that reads .ASP files, parses and executes server side script blocks, and serves up result
ASP.NET == ASP.NExTversion
On one hand, ASP.NET is an evolution of the ASP and is just the next version of ASP
Same intrinsic objects available Script and html can be mixed Some ASP code can be ported with no changes Server-side Javascript is still supported
Sample ASP file
test.asp server-side directive server-side function <%@ <%@language=javascript language=javascript%> %> <script language='JScript' runat='server'> function Add(x, y) { return x+y; } </script> <html> <body> <h1>Test ASP Page</h1> <% %> <h2>2+2=<%=Add(2,2)%></h2> <table border='2'> <% for (var i=0; i<10; i++) { %> %> <% <% %> <% Col1</td></tr> %> <tr><td>Row<%=i%> Col0</td><td>Row<%=i%> <% } %> %> <% </table> <% Response.Write("<h2>Written directly to Response</h2>"); %> <% </body> </html> %>
server-side evaluation syntax
interspersed server-side script
Fundamental change
ASP.NET is more than just the next version of ASP
Pages are compiled into assemblies improving performance and diagnostics Code-behind encourages better separation of code from HTML Extensible, server-side control architecture Server-side data binding model Form validation architecture Web services allow assemblies to expose themselves as SOAP servers
Sample ASP.NET file
server-side directive server-side function test.aspx <%@ <%@Page PageLanguage='C#' Language='C#'%> %> <script runat="server"> int Add(int x, int y) { return x+y; } </script> <html> <body> <h1>Test ASP.NET Page</h1> server-side evaluation syntax <% %> <h2>2+2=<%=Add(2,2)%></h2> <table border="2"> <% for (int i=0; i<10; i++) { %> %> <% <% %> <% Col1</td></tr> %> <tr><td>Row<%=i%> Col0</td><td>Row<%=i%> <% } %> %> <% </table> <% Response.Write("<h2>Written directly to Response</h2>"); %> <% </body> </html> %>
interspersed server-side script
What is ASP.NET?
At a high level, ASP.NET is a collection of .NET classes that collaborate to process an HTTP request and generate an HTTP response
Some classes are loaded from system assemblies Some classes are loaded from GAC assemblies Some classes are loaded from local assemblies To work with ASP.NET, you must build your own classes that integrate into its existing class structure Some of your classes will be in pre-built assemblies Some of your classes will be in assemblies
High-level view of ASP.NET
HTTP Request GET /foo/foo.aspx HTTP Response HTTP/1.1 200 OK ...
ASP.NET Worker Process AppDomain1
System Assemblies
system.web. dll system.data. dll mscorsvr.dll
GAC Assemblies
bargraph.dll mygacutil.dll acmeutil.dll
Local Assemblies
mypage.dll 32wie4kg.dll myctrl.dll
Pipeline architecture
ASP.NET uses the CLR to replace IIS's ISAPI/ASP architecture
User-defined handler objects used to dispatch HTTP requests Requests dispatched through ASP.NET-provided ISAPI extension (aspnet_isapi.dll)
Handlers run in an ASP.NET-provided worker process (aspnet_wp.exe in IIS 5, w3wp.exe in IIS 6) Many IIS features bypassed in favor of ASP.NETprovided features (WAM-based process isolation, ASP object model, and session management)
HttpPipeline architecture (IIS 5.0)
GET /foo/foo.aspx HTTP/1.1 200 OK ... Web Server (Win2000, XP)
aspnet_wp.exe (ASP.NET Worker Process)
named pipe connection
IHttpHandler
handler
aspnet_isapi.dll (ISAPI Extension) INETINFO.EXE (IIS 5.0)
HttpPipeline architecture (IIS 6.0)
Web Server (Win Server 2003)
Application Pool #1 Application Pool #2
w3wp.exe (ASP.NET Worker Process)
IHttpHandler handler
w3wp.exe (ASP.NET Worker Process)
IHttpHandler handler
aspnet_isapi.dll (ISAPI Extension)
aspnet_isapi.dll (ISAPI Extension)
kernel
http.sys
GET /foo/foo.aspx
HTTP/1.1 200 OK ...
Compilation vs. Interpretation
When ASP.NET pages are first accessed, they are compiled into assemblies
Subsequent access loads the page directly from the assembly Eliminates inefficiencies of the scripting model of ASP No performance difference between compiled components and embedded server-side code Debugging tools shared with all .NET development Whenever you author a new .aspx file, you are authoring a new class
Page compilation
Every ASP.NET page is compiled into an assembly on first access
The generated assembly contains a single class that derives from System.Web.UI.Page The generated Page-derived class is the file name of the page, replacing the "." with a "_" (like foo_aspx) The generated assembly is stored in the 'Temporary ASP.NET Files' directory on the server machine
ASP.net Page Compilation
HTTP Request GET /foo/foo.aspx IIS & ASP.NET PageParser:: GetCompiledPageInstance
Locate foo.aspx Generate Page-derived class foo_aspx from file Compile to assembly no
Compiled assembly already exists?
yes
Create foo_aspx instance Call Page::ProcessRequest
HTTP Response HTTP/1.1 200 OK ... Content-Type: text/html; Content-Length: 300 <html><body> ... </body></html>
Page::ProcessRequest calls Page::RenderControl
ASP.NET basics
Each ASP.NET page is parsed and compiled into a class that extends System.Web.UI.Page
Page class implements IHttpHandler A lot of the Page class is dedicated to forms/control processing Exposes HttpContext properties as own properties
.aspx Type Information
<!-- File: ShowPageType.aspx --> <%@ Page Language='C#' %> <html> <body> <h2>Show Page Type</h2> <% Response.Output.Write("<p>Page type {0}</p>", this.GetType()); Response.Output.Write("<p>Page base type {0}</p>", this.GetType().BaseType); %> </body> </html>
System.Web.UI.Page
The Page class provides facilities for rendering HTML
Response and Request objects are available as properties of the class Methods for rendering are provided Events associated with generating the page are defined
System.Web.UI.Page
class Page : TemplateControl, IHttpHandler { // State management public HttpApplicationState Application {get;} public HttpSessionState Session {virtual get;} public Cache Cache {get;} // Intrinsics public HttpRequest Request {get;} public HttpResponse Response {get;} public HttpServerUtility Server {get;} public string MapPath(string virtualPath);
// Client information public string ClientTarget {get; set;} public IPrincipal User {get;} //...
}
System.Web.UI.Page
class Page : TemplateControl, IHttpHandler { // Core public UserControl LoadControl(string virtualPath); public virtual ControlCollection Controls {get;} public override string ID { get; set;}
public bool IsPostBack {get;} protected virtual void RenderControl(HtmlTextWriter writer); // Events public event EventHandler Init; public event EventHandler Load; public event EventHandler PreRender; public event EventHandler Unload;
//...
}
Class creation
Classes created from .aspx files can be customized
Server-side script blocks are added to the class definition
Member variables Member functions
Interspersed script is added to a 'Render' function
Executable code
Aspx == Class
member variable declaration member function declaration <%@ <%@Page PageLanguage="C#" Language="C#"%> %> <html><body> <script language="C#" runat="server"> private ArrayList _values = new ArrayList(); private void PopulateArray() { _values.Add("v1"); _values.Add("v2"); _values.Add("v3"); _values.Add("v4"); } </script> <h2>aspx==class!</h2> <ul> <% <% PopulateArray(); for (int i=0; i<_values.Count; i++) Response.Output.Write("<li>{0}</li>", _values[i]); %> %> </ul> </body> </html>
member function usage
member variable usage
Server Side Code Placement in Page Compilation
// Machine-generated source file // ybngvkuj.0.cs namespace ASP { public class SamplePage_aspx : Page, IRequiresSessionState { <!-- SamplePage.aspx --> <%@ Page Language="C#" %> <html><body> <script language="C#" runat=server> private ArrayList m_values = new ArrayList(); private void PopulateArray() { m_values.Add("v1"); m_values.Add("v2"); m_values.Add("v3"); m_values.Add("v4"); } </script> <ul> <% PopulateArray(); for (int i=0; i<m_values.Count; i++) Response.Output.Write( "<li>{0}</li>", m_values[i]); %> </ul> </body> </html> private ArrayList m_values = new ArrayList(); private void PopulateArray() { m_values.Add("v1"); m_values.Add("v2"); m_values.Add("v3"); m_values.Add("v4"); } public SamplePage_aspx() { /*...*/ } private void __Render__control1( HtmlTextWriter __output, Control parameterContainer) { __output.Write( "<!-- SamplePage.aspx -->\r\n"); __output.Write( "\r\n<html><body>\r\n"); __output.Write("\r\n<ul>\r\n"); PopulateArray(); for (int i=0; i<m_values.Count; i++) Response.Output.Write( "<li>{0}</li>", m_values[i]); __output.Write( "\r\n</ul> \r\n</body> </html>\r\n");
} //...
Code behind
In addition to customizing the generated Page class using embedded code, ASP.NET supports page inheritance
Technique of Page inheritance is called code-behind Supported through the Inherits attribute of the Page directive Promotes separation of code and presentation Code-behind files can be pre-compiled and placed in a directory named /bin at the top level of the application
Code-behind files can be compiled on demand using the src attribute of the Page directive
Sample Page with CodeBehind
<%@ Page Page Language="C#" Language="C#" <%@ Inherits="EssentialAspDotNet.Architecture.SamplePage"%> Inherits="EssentialAspDotNet.Architecture.SamplePage"%> <html><body> <h2>aspx==class!</h2> <ul> <% <% WriteArray(); %> %> </ul> </body> </html>
SamplePage.cs
namespace EssentialAspDotNet.Architecture { public class SamplePage : Page { private ArrayList _values = new ArrayList(); public SamplePage() { _values.Add("v1"); _values.Add("v2"); _values.Add("v3"); _values.Add("v4"); } protected void WriteArray() { for (int i=0; i<_values.Count; i++) Response.Output.Write("<li>{0}</li>", _values[i]); } } }
Class Hierarchy created using code behind
System.Web.UI.Page
EssentialAspDotNet. Architecture. SamplePage
ASP.CodeBehind_aspx
Using src attribute to automatically compile code behind
<%@ Page Page Language="C#" Language="C#" src="SampleCodeBehind.cs" src="SampleCodeBehind.cs" <%@ Inherits="EssentialAspDotNet.Architecture.SamplePage"%> Inherits="EssentialAspDotNet.Architecture.SamplePage"%> <html><body> <h2>aspx==class!</h2> <ul> <% <% WriteArray(); %> %> </ul> </body> </html>
Shadow Copying
All assemblies in the /bin directory are shadow copied
Placing assemblies in /bin makes them available to all pages in that application These assemblies are not referenced directly by ASP.NET Instead they are copied to an obscure location prior to loading If the original file ever changes, the file is re-copied Enables xcopy deployment
Shadow Copy Mechanism
ShadowCopyDirectories
Referenced Assembly (Original)
Copied by assembly loader
Shadow Copy (actually loaded)
Fusionmanaged directories
ASP->ASP.NET Migration
Several options for migrating 'classic' ASP applications
Run ASP side-by-side with ASP.NET, developing new pages/apps in ASP.NET
Quickest path, but session and application state is not shared
Convert existing ASP pages to ASP.NET (but keep using old libraries - ADO and msxml)
Access to COM libraries incurs interop boundary crossing
Convert existing ASP pages to ASP.NET with new libraries (ADO.NET and System.XML)
Converting ASP pages to ASP.NET
Some pages can be converted by simply renaming to .aspx Most pages will need some 'touch up'
Many directives have been changed (or removed) VBScript is not directly supported (must be VB.NET) COM object interaction may require ASPCOMPAT mode Code block placement different in ASP.NET
Updating directives from ASP->ASP.NET
Several directives in ASP are no longer supported
<% option explicit %> <%@ language="vbscript" %>
Instead, use equivalent ASP.NET directives/attributes
<%@ Page Language="VB" Explicit="true" %>
Not VBScript = VB.NET
Many language changes mean VBScript code needs to be updated
VB.NET doesn't support default properties
objRS("au_fname") => objRS.Fields("au_fname")
IsNull won't work when testing DB results
IsNull(dbField) => IsDBNull(dbField)
Let and Set are no longer supported
Set obj = CreateObject("xx") => obj = CreateObject("xx")
Not VBScript = VB.NET
Date() is no longer an expression (it is a type)
Date() => DateTime.Now
Parameters must be passed within parentheses
Response.Write "hi" => Response.Write("hi")
Interacting with COM
By default, ASP.NET applications will run in an MTA thread when accessing COM objects through interop
Many classic ASP components are STA-threaded which means that all calls incur a thread-switch Avoid this by using the AspCompat attribute <%@ Page AspCompat="true" %>
Summary
ASP.NET is an evolution of dynamic web page generation techniques All pages in ASP.NET are compiled assemblies Code-behind is a useful technique for separating code logic from presentation Shadow copying enables 'xcopy' deployment Migrating ASP applications typically requires some explicit conversion on your